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

9 篇文章 0 订阅


前言

注意此博文代码仅限于在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 <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#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;
 } 

编译即可使用,代码量稍多,刚开始写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领取。

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值