• python加密Django框架代码(通过修改Cpython解释器)



    前言

    注意此博文代码仅限于在linux系统下使用,因为没有做windows的适配。
    本文承接上篇博文链接: 加密python单文件代码(无import自造模块)
    并在其上进行以下改进:
    1.现在在import自造模块之前会对模块代码进行解密,并加载进内存。
    2.去掉了Cpython解释器中默认的pyc文件缓存(即__pycache__目录)以减少通过pyc文件解密py文件的可能。
    3.新增可以在目录中递归查找.py后缀文件的工具,以方便用户将指定目录下的所有py文件全部加密。
    4.可以加密django框架代码,并保证代码的运行正常。


    一、实现效果

    1.加密之前文件树
    请添加图片描述
    2.使用工具加密py文件
    在这里插入图片描述
    3.加密后文件树
    在这里插入图片描述
    注意其中的bw_code目录是加密后的文件,文件已经按原来项目的结构安排好了。

    4.运行加密后的项目
    请添加图片描述
    成功运行。
    5.访问网页
    请添加图片描述

    二、代码修改

    1.加密工具代码

    代码如下:

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define FILEPATHLENGTH 1024
    
    char *bw_dir_path_preffix = "/bw_code";
    
    // 读取文件
    long fileRead(char fileName[FILEPATHLENGTH],char **buffer){
         //打开文件 
         FILE *fp = fopen(fileName,"rb");
         if(fp == NULL){
             printf("open file is failed");
             exit(1); 
         }
         //把文件指针移到文件末尾
         fseek(fp,0,SEEK_END);
         //保存文件的长度
         long fileSize = ftell(fp);
         //把文件指针移到文件开头
         fseek(fp,0,SEEK_SET);
         //读取文件,保存到buffer中
         *buffer = (char*)malloc(fileSize);
         fread(*buffer,1,fileSize,fp);
         //关闭文件
         fclose(fp);
         return fileSize;
     }
     
    // 加密文件写入
    void fileWrite(char fileName[FILEPATHLENGTH],char *buffer,long fileSize){
         //创建文件进行写入 
         FILE *fp = fopen(fileName,"wb");
         if(fp == NULL){
             printf("open file is failed");
             exit(1); 
         }
         fwrite(buffer,1,fileSize,fp);
         fclose(fp); 
     }
     
    // 加密主要函数
    void encrypt_decode(char encryptFile[FILEPATHLENGTH],char encryptedFile[FILEPATHLENGTH],int key){
        char *buffer;
        long fileSize = fileRead(encryptFile,&buffer);
        //加密 / 解密 
        for(int i = 0; i < fileSize; i++){
            buffer[i] = buffer[i]^key;
        }
        fileWrite(encryptedFile,buffer,fileSize);
    }
    
    // 获取文件后缀
    char *get_file_ext(char *filename){
        int len = (int)strlen(filename);
        for(int i=len-1;i>=0;i--){
            if(filename[i]=='.'){
                return filename+i+1;
            }
        }
        return NULL;
    }
    
    // 创建文件夹
    int mkdirs(char *path) 
    {
        char str[512];    
        strncpy(str, path, 512);
        int len=strlen(str);
        for(int i=0; i<len; i++ )
        {
            if( str[i]=='/' )
            {
                str[i] = '\0';
                if( access(str,0)!=0 )
                {
                    mkdir( str, 0755 );
                }
                str[i]='/';
            }
        }
        if( len>0 && access(str,0)!=0 )
        {
            mkdir( str, 0755 );
        }
    	struct stat s;
    	stat(path,&s);
    	if(S_ISDIR(s.st_mode) )return 0;
        return 1;
    }
    
    // 此函数介绍不知道咋写,建议自己意会
    char *get_remain_path(char *base_path, char *dir_path){
        if(strlen(base_path)>=strlen(dir_path)){
            return NULL;
        }
        for(int i=0; i<strlen(base_path);i++){
            if(base_path[i]!=dir_path[i]){
                return &(dir_path[i]);
            }
        }
        return &(dir_path[strlen(base_path)]);
    }
    
    // 加密逻辑函数
    int encrypt(char * path, char *base_path , int recursive)
    {
    	DIR * p_dir;
    	struct dirent * entry;
    	size_t len;
    	char * sub_path;
    	
    	p_dir = opendir(path);
    	if (p_dir == NULL)
    	{
    		printf("Can not open %s/n", path);
    		return -1;
    	}
    	while((entry = readdir(p_dir)) != NULL)
    	{
    		len = strlen(path) + strlen(entry->d_name) + 3;
    		sub_path = calloc(len, 1);
    		if (sub_path == NULL)
    		{
    			printf("out of memory/n");
    			closedir(p_dir);
    			return -1;
    		}
            char code_dir_root[strlen(base_path)+strlen(bw_dir_path_preffix)+1];
            strcpy(code_dir_root, base_path);
            strcat(code_dir_root, bw_dir_path_preffix);
            mkdirs(code_dir_root);
    
    
    		strcpy(sub_path, path);
    		strcat(sub_path, "/");
    		strcat(sub_path, entry->d_name);
            
    		if (entry->d_type == DT_DIR && recursive != 0 && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
    		{
                // 在这创建目录,格式为basepath/bw_dir_path_preffix/dirpath
    
                // 获取当前目录比base_path多的部分
                char *remain_path = get_remain_path(base_path, sub_path);
                if(remain_path!=NULL){
                    // 拼接
                    char code_dir[strlen(base_path)+strlen(bw_dir_path_preffix)+strlen(remain_path)+1];
                    strcpy(code_dir, base_path);
                    strcat(code_dir, bw_dir_path_preffix);
                    strcat(code_dir, remain_path);
                    if(code_dir!=NULL){
                        mkdirs(code_dir);
                    }
                    encrypt(sub_path, base_path,recursive);
                }else{
                    printf("remain_path is NULL\n");
                    exit(1);
                }
    		}
            if(entry->d_type == DT_REG){
                // 打开文件
                // 判断文件是py结尾
                char *ext = get_file_ext(sub_path);
                if(ext!=NULL && strcmp(ext,"py")==0){
                    char *remain_path = get_remain_path(base_path, sub_path);
                    if(remain_path!=NULL){
                        // 拼接
                        char code_file[strlen(base_path)+strlen(bw_dir_path_preffix)+strlen(remain_path)+1];
                        strcpy(code_file, base_path);
                        strcat(code_file, bw_dir_path_preffix);
                        strcat(code_file, remain_path);
                        //把.py改为.bw
                        code_file[strlen(code_file)-1] = 'w';
                        code_file[strlen(code_file)-2] = 'b';
                        code_file[strlen(code_file)-3] = '.';
                        encrypt_decode(sub_path, code_file,12);
                    }else{
                        printf("remain_path is NULL\n");
                        exit(1);
                    }
                }
            }
    		free(sub_path);
    	}
    	closedir(p_dir);
    	return -1;
    }
     
    int main(int argv, char **argc){
        if(argv!=2){
            printf("Usage: enc [file_abs_path]");
            return -1;
        }
        encrypt(argc[1], argc[1], 12);
        return 0;
     } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200

    编译即可使用,代码量稍多,刚开始写C代码还是不大习惯,如有纰漏欢迎指出。
    注意现在只支持绝对路径。

    2.Cpython代码修改

    关于import导入的流程我可能会单独写一篇博文,现在只介绍部分关键代码,整个改完的解释器代码我已经上传github,链接https://github.com/MakeEarthBetter/cpythondiy/tree/master。注意分支是master,十分期望您的star❤。

    一.添加自己文件后缀的import loader.

    import时会遍历loaders,尝试找到对应后缀的文件,我们在这添加我们自己的bw文件
    请添加图片描述
    Cpython默认的loaders为
    请添加图片描述
    第二个是pyc文件,第三个是py文件

    二.修改Cpython找到文件时的操作

    请添加图片描述
    此处是Cpython加载文件代码的部分,在此处先将bw文件解码。

    三. 删除解码后的文件

    这里是加载代码处,由于此处为必经之路,在此处进行中间文件的删除。
    在这里插入图片描述


    总结

    由于修改的部分主要在Cpython代码处,而import的流程在瓷片博文又不想走一遍,所以就写到这吧。import流程请见下篇博文。代码请到github领取。

  • 相关阅读:
    制作MySQL8绿色版&轻量版
    MySQL 自建数据库慢日志分析
    registry镜像仓库通过HTTP API删除镜像
    二十、W5100S/W5500+RP2040树莓派Pico<MQTT连接阿里云控制板载LED>
    Unified Access Control
    nginx目录树美化
    NX二次开发-ug表达式函数ug_find_file读取当前prt所在路径
    若枚举映射的值不存在,则不进行反序列化
    一个悄然崛起的AI开源项目!
    第k小的数
  • 原文地址:https://blog.csdn.net/qq_42455809/article/details/126467196