文章目录
前言
注意此博文代码仅限于在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 = (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)
{
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){
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);
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;
}
编译即可使用,代码量稍多,刚开始写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领取。
Original: https://blog.csdn.net/qq_42455809/article/details/126467196
Author: 工丨具丨人
Title: python加密Django框架代码(通过修改Cpython解释器)
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/736857/
转载文章受原作者版权保护。转载请注明原作者出处!