我看过 在Cython中制作可执行文件 和BuvinJ的回答 如何有效混淆Python代码? 并想测试一下用Cython编译的源代码在编译后是否真的 "不存在了"。使用Cython是保护Python源代码的一种方式,这的确是一种流行的观点,例如请看文章 用Cython保护Python源代码.
让我们来看看这个简单的例子 test.pyx
:
import json, time # this will allow to see what happens when we import a library
print(json.dumps({'key': 'hello world'}))
time.sleep(3)
print(1/0) # division error!
那就用Cython吧。
cython test.pyx --embed
这将产生一个 test.c
. 让我们来编译它。
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
cl test.c /I C:\Python37\include /link C:\Python37\libs\python37.lib
能用!它产生了一个140KB的 test.exe
可执行的,不错!
但在这个答案中 如何有效混淆Python代码? 有人隐晦的说,这种 "编译 "会隐藏源码。这似乎不是真的,如果你运行 test.exe
,你会看到。
```
Traceback (most recent call last):
File "test.pyx", line 4, in init test
print(1/0) # division error! <-- the source code and even the comments are still there!
ZeroDivisionError: integer division or modulo by zero
```
这说明 源码还在那里.
问题。是否有办法用Cython编译代码,从而使声称的 "源码不再透露" 是真的吗?
注意:我正在寻找一个既不存在源代码也不存在字节码(.pyc)的解决方案(如果字节码.pyc被嵌入,那么用 uncompyle6)
PS:我记得几年前我也做过同样的观察,但现在已经找不到了,经过深入研究这里就有了。是否可以反编译一个.dll.pyd文件来提取Python源代码?
代码在你的exe旁边的原始pyx-文件中找到。Deletedon没有把这个pyx-file和你的exe一起分发。
当你查看生成的C代码时,你会发现为什么你的可执行文件会显示错误信息。
对于一个突起的错误,Cython会发出一个类似于下面的代码。
__PYX_ERR(0, 11, __pyx_L3_error)
其中 __PYX_ERR
是一个宏,定义为。
#define __PYX_ERR(f_index, lineno, Ln_error) \
{ \
__pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \
}
而变量 __pyx_f
定义为
static const char *__pyx_f[] = {
"test.pyx",
"stringsource",
};
基本上 __pyx_f[0]
告诉我们在哪里可以找到原始代码。现在,当出现异常时, (嵌入式) Python 解释器会查找你的原始 pyx-文件,并找到相应的代码 (这可以在 __Pyx_AddTraceback
当出现错误时被调用)。)
一旦这个 pyx-file 不在身边,原始的源代码将不再被 Python 解释器和其他任何人所知。然而,错误跟踪仍然会显示函数的名称和行号,但不再显示任何代码片段。
由此产生的可执行文件 (或扩展,如果创建了的话) 不包含任何字节码 (如 pyc-files),并且不能用类似于 uncompyle
:当py-file被翻译成Python-opcodes时,会产生字节码,然后在Python-opcodes中进行评估。巨大的循环 ceval.c
. 然而对于内建的cython模块,不需要字节码,因为生成的代码直接使用Python的C-API,省去了对操作码的评估--这些模块跳过了解释,这也是它们的一个原因。更快. 因此,可执行文件中不会有字节码。
但有一点很重要。我们应该检查链接器是否包含调试信息 (因此可以在C代码中找到pyx文件内容的注释)。MSVC与 /Z7
options就是这样一个例子。
然而,生成的可执行文件可以被反汇编成汇编器,然后生成的C代码可以被逆向工程--因此,虽然cython化可以让人难以理解代码,但它不是隐藏密钥或安全算法的正确工具。