- 通过 python -m <module> 的方式来加载模块时 , 其入口函数是 Py_Main 函数
- 通过 import <module> 的方式来加载模块时 , 其入口函数是 builtin___import__ 函数
- 通过 reload(<module>) 的方式来加载模块时 , 其入口函数是 builtin_reload 函数
[Python/import.c]--------------------------------------static struct filedescr *find_module(char *fullname, char *subname, PyObject *path, char *buf,size_t buflen, FILE **p_fp, PyObject **p_loader){...fp = fopen(buf, filemode);...}
我们在 find_module 函数中找到了打开文件的逻辑 , 如果直接改成前文实现的 decrypt_open , 岂不是就能达成加载模块时解密的目的了?总体思路是这样的 , 但有个细节需要注意 , buf 不一定就是 .py 文件 , 也可能是 .pyc 文件 , 我们只对 .py 文件做改动 , 则可以这么写:
[Python/import.c]--------------------------------------static struct filedescr *find_module(char *fullname, char *subname, PyObject *path, char *buf,size_t buflen, FILE **p_fp, PyObject **p_loader){...if (fdp->type == PY_SOURCE) {fp = decrypt_open(buf, filemode);}else {fp = fopen(buf, filemode);}...}
经过上述改动 , 就实现了加载模块时解密的目的了 。支持指定密钥文件前文中还留有一个待解决的问题:我们一开始是假定解释器已获取到了密钥内容并存放在了全局变量 aes_passwd 中 , 那么密钥内容怎么获取呢?
我们需要 Python 解释器能支持一个新的参数选项 , 通过它来指定已加密的密钥文件 , 然后再通过非对称算法进行解密 , 得到 aes_passed。
假定这个参数选项是 -k <filename> , 则可使用如 python -k enpasswd.txt 的方式来告知解释器加密密钥的文件路径 。其实现如下:
[Modules/main.c]--------------------------------------/* 命令行选项 , 注意k:是新增的内容 */#define BASE_OPTS "3bBc:dEhiJk:m:OQ:RsStuUvVW:xX?".../* Long usage message, split into parts < 512 bytes */static char *usage_1 = "...-k key : decrypt source file by using key filen...";...intPy_Main(int argc, char **argv){...char *keyfilename = NULL;...while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {...case 'k':keyfilename = (char *)malloc(strlen(_PyOS_optarg) + 1);if (keyfilename == NULL)Py_FatalError("not enough memory to copy -k argument");strcpy(keyfilename, _PyOS_optarg);keyfilename[strlen(_PyOS_optarg)] = '';break;...}...if (keyfilename != NULL) {int passwdlen;char *passwd = NULL;passwdlen = rsa_decrypt(keyfilename, &passwd);set_aes_passwd(passwd);if (passwdlen < 0) {fprintf(stderr, "%s: parsing key file '%s' errorn", argv[0], keyfilename);free(keyfilename);return 2;} else {free(keyfilename);}}...}
其逻辑如下:- k: 中的 k 表示支持 -k 选项; : 表示选项后跟一个参数 , 即这里的已加密密钥文件的路径
- 解释器在处理到 -k 参数时 , 获取其后所跟的文件路径 , 记录在 keyfilename 中
- 使用自定义的 rsa_decrypt 函数(限于篇幅 , 不列出如何实现的逻辑)对已加密密钥文件进行非对称解密 , 获得密钥的原始内容
- 将该密钥内容写入到 aes_passwd 中
禁用字节码不生成 .pyc 文件首先要做的就是不生成 .pyc 文件 , 这样 , 恶意用户就没法直接根据 .pyc 文件来得到源码 。
我们知道 , 通过 -B 选项可以告知 Python 解释器不生成 .pyc 文件 。既然定制的 Python 解释器就不生成 .pyc 我们干脆禁用这个选项:
[Modules/main.c]--------------------------------------/* 命令行选项 , 注意移除了B */#define BASE_OPTS "3bc:dEhiJm:OQ:RsStuUvVW:xX?".../* Long usage message, split into parts < 512 bytes */static char *usage_1 = "...//-B: don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=xn...";...intPy_Main(int argc, char **argv){...// 不生成 py[co]Py_DontWriteBytecodeFlag++;...}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Elasticsearch中数据是如何存储的?
- Windows 7用户必看 如何升级至Windows 10
- HTTP是如何使用TCP连接
- 如何将 Python 的一个类方法变为多个方法?
- 如何在Mac下生成ssh密钥?
- 这一次,让你完全理解 HTTPS 到底是如何做到数据传输安全的
- 程序员告诉你微信营销号如何防封、解封
- 黑客是如何控制你手机的?出现这几种情况,你的手机可能已中招
- 一文教会你如何申请ios开发者账号
- 更年期的女性 练太极对你的好处到底有多大