如何有效地混淆Python代码?

143 投票
22 回答
288720 浏览
提问于 2025-04-16 01:54

我想知道怎么隐藏我的Python源代码。

print "Hello World!" 

我该怎么把这个例子编码成不容易被人看懂的样子?有人告诉我可以用base64,但我不太清楚怎么做。

22 个回答

43

你可以把你的代码嵌入到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)可能也会对你有帮助:

https://pypi.org/project/pyarmor/

44

所以这样就不能被人看懂了吗?

我的意思是,整个文件都是编码的!当你打开它时,你根本看不懂里面的内容……这正是我想要的。

最多,你可以把你的源代码编译成字节码,然后只分发字节码。但即使这样也可以被逆向还原。字节码可以被反编译成半可读的源代码。

Base64编码对于任何人来说都很简单可以解码,所以它不能真正提供保护,只能让完全不懂电脑的人看不懂。而且,如果你打算通过任何方式运行这段代码,你就必须把解码器直接放进脚本里(或者放在你的分发包中的另一个脚本里,这个脚本需要合法用户来运行),这样一来,你的编码/加密方式就会暴露出来。

混淆技术通常包括去掉注释和文档、修改变量名、插入无用代码等等,所以即使你反编译了字节码,你得到的源代码也不会太容易阅读。不过,它们仍然是Python源代码,而Python并不擅长变得一团糟。

如果你真的需要保护某些功能,我建议使用编译语言,比如C或C++,编译并分发.so/.dll文件,然后使用Python绑定来调用这些受保护的代码。

114

这只是一个有限的、初级的代码混淆解决方案,但它是内置的:Python有一个编译器可以把代码转换成字节码:

python -OO -m py_compile <your program.py>

这会生成一个 .pyo 文件,里面包含了字节码,并且去掉了文档字符串等内容。你可以把这个 .pyo 文件改名为 .py 后缀,然后用 python <你的程序.py> 来运行,就像运行你的程序一样,但里面不包含你的源代码。

补充说明:这种“有限”的混淆程度是可以恢复代码的(虽然变量名还在,但没有注释和文档字符串)。具体怎么做可以看看第一条评论。不过在某些情况下,这种混淆程度可能已经足够了。

再补充:如果你的程序导入了像这样混淆过的模块,那么你需要把它们改名为 .pyc 后缀(我不确定这将来不会出问题),或者你可以继续使用 .pyo 文件,并用 python -O ….pyo 来运行(导入应该可以正常工作)。这样Python就能找到你的模块(否则,Python会去找 .py 模块)。

撰写回答