如何有效地混淆Python代码?
我想知道怎么隐藏我的Python源代码。
print "Hello World!"
我该怎么把这个例子编码成不容易被人看懂的样子?有人告诉我可以用base64,但我不太清楚怎么做。
22 个回答
你可以把你的代码嵌入到C/C++中,然后编译它,具体可以参考在其他应用中嵌入Python
embedded.c
#include <Python.h>
int
main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("print('Hello world !')");
Py_Finalize();
return 0;
}
在Ubuntu/Debian系统中
$ sudo apt-get install python-dev
在Centos/Redhat/Fedora系统中
$ sudo yum install python-devel
编译命令是
$ gcc -o embedded -fPIC -I/usr/include/python2.7 -lpython2.7 embedded.c
运行命令是
$ chmod u+x ./embedded
$ time ./embedded
Hello world !
real 0m0.014s
user 0m0.008s
sys 0m0.004s
初始脚本:hello_world.py:
print('Hello World !')
运行这个脚本
$ time python hello_world.py
Hello World !
real 0m0.014s
user 0m0.008s
sys 0m0.004s
不过,有些Python代码的字符串可能会出现在编译后的文件里
$ grep "Hello" ./embedded
Binary file ./embedded matches
$ grep "Hello World" ./embedded
$
如果你想增加一点混淆,可以使用base64编码
...
PyRun_SimpleString("import base64\n"
"base64_code = 'your python code in base64'\n"
"code = base64.b64decode(base64_code)\n"
"exec(code)");
...
例如:
创建你代码的base64字符串
$ base64 hello_world.py
cHJpbnQoJ0hlbGxvIFdvcmxkICEnKQoK
embedded_base64.c
#include <Python.h>
int
main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("import base64\n"
"base64_code = 'cHJpbnQoJ0hlbGxvIFdvcmxkICEnKQoK'\n"
"code = base64.b64decode(base64_code)\n"
"exec(code)\n");
Py_Finalize();
return 0;
}
所有命令
$ gcc -o embedded_base64 -fPIC -I/usr/include/python2.7 -lpython2.7 ./embedded_base64.c
$ chmod u+x ./embedded_base64
$ time ./embedded_base64
Hello World !
real 0m0.014s
user 0m0.008s
sys 0m0.004s
$ grep "Hello" ./embedded_base64
$
更新:
这个项目(pyarmor
)可能也会对你有帮助:
所以这样就不能被人看懂了吗?
我的意思是,整个文件都是编码的!当你打开它时,你根本看不懂里面的内容……这正是我想要的。
最多,你可以把你的源代码编译成字节码,然后只分发字节码。但即使这样也可以被逆向还原。字节码可以被反编译成半可读的源代码。
Base64编码对于任何人来说都很简单可以解码,所以它不能真正提供保护,只能让完全不懂电脑的人看不懂。而且,如果你打算通过任何方式运行这段代码,你就必须把解码器直接放进脚本里(或者放在你的分发包中的另一个脚本里,这个脚本需要合法用户来运行),这样一来,你的编码/加密方式就会暴露出来。
混淆技术通常包括去掉注释和文档、修改变量名、插入无用代码等等,所以即使你反编译了字节码,你得到的源代码也不会太容易阅读。不过,它们仍然是Python源代码,而Python并不擅长变得一团糟。
如果你真的需要保护某些功能,我建议使用编译语言,比如C或C++,编译并分发.so/.dll文件,然后使用Python绑定来调用这些受保护的代码。
这只是一个有限的、初级的代码混淆解决方案,但它是内置的:Python有一个编译器可以把代码转换成字节码:
python -OO -m py_compile <your program.py>
这会生成一个 .pyo
文件,里面包含了字节码,并且去掉了文档字符串等内容。你可以把这个 .pyo
文件改名为 .py
后缀,然后用 python <你的程序.py>
来运行,就像运行你的程序一样,但里面不包含你的源代码。
补充说明:这种“有限”的混淆程度是可以恢复代码的(虽然变量名还在,但没有注释和文档字符串)。具体怎么做可以看看第一条评论。不过在某些情况下,这种混淆程度可能已经足够了。
再补充:如果你的程序导入了像这样混淆过的模块,那么你需要把它们改名为 .pyc
后缀(我不确定这将来不会出问题),或者你可以继续使用 .pyo
文件,并用 python -O ….pyo
来运行(导入应该可以正常工作)。这样Python就能找到你的模块(否则,Python会去找 .py
模块)。