Python代码的加密和混淆
2021年3月19日 - 由Bo 0 评论 2369 阅读
当需要发布用Python编写的程序时,保密性往往是需求之一,以避免核心代码的泄露,避免业务功能的实现细节的泄露。
接下来介绍几种方式,包括有效的,和看起来有效实际无效的。
先在同一目录里创建两个测试文件:
# a.py
class Test:
def add(self, i, j):
return i+j
def divide(self, i, j):
return i/j
# b.py
from a import Test
t = Test()
print(t.add(1,3))
print(t.divide(9,3))
加密
这里再回顾一下python的一些文件类型:
.py: python的源码文件.
.pyc: Python源码import模块后,编译生成的字节码.
.pyo: Python源码编译优化生成的字节码。pyo比pyc并没有优化多少,只是去掉了断言.
.pyd: Python的动态链接库(Windows平台).
将python源码编译为.so文件或者windows上的.pyd文件(可行)
上面的两个测试文件是b文件调用a文件的类,于是可以将a文件编译为.so或.pyd格式。
先安装cython
pip install cython
在当前目录添加一个setup.py:
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("a.py")
)
接着运行:
python setup.py build_ext --inplace
此时在当前目录能看到编译后的文件和中间文件,比如a.c、a.so。
现在只保留a.so和b.py,然后运行python b.py仍然能正常运行,不过a.py中的内容已对外保密了。
windows上也是类似的操作,如果遇到错误提示"error: Unable to find vcvarsall.bat",那么需要安装vc,到这个链接里: The latest supported Visual C++ downloads
将python源码转换为字节码即.pyc文件(不可行)
在python文件调用模块时,被调用的模块会先解释为字节码并存于.pyc文件中,以提高效率。也可以指定将所有文件都转换为字节码。
但是字节码并不安全,可以轻易地查看.pyc文件中的字节码的操作指令,也能将pyc文件重新转回py文件。
关于pyc文件可以看这篇:理解Python中的字节码
将python源码打包为windows上的exe文件(不可行)
可以用pyinstaller或py2exe将python文件打包,但是这只是方便了去除环境依赖的运行,并不对安全产生作用。
exe文件看似保密,但实际上仍可以通过解压等方式获得源码。于是需要对exe文件进行加壳操作(未尝试)。或者转换为pyd文件后统一打包为exe文件才行。
代码混淆
代码混淆是将原文件转换为功能上不变,但是难以阅读理解的文件。
这样代码仍然可以被执行,但其中的细节却无法轻易复制。
比如可以是将变量、函数、类名变成无意义的名字,甚至于加上特殊字符。或者以一定规则插入无意义的字符,这样不知晓规则的人就无从获得原来代码的样子。
可以用pyminifier来做代码混淆。
pip install pyminifier
比如现在随便用几句python语句试试,原文件内容是:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
topic_url = "https://www.zhihu.com/topic/19552832/hot"
chrome_options = Options()
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
chrome_driver = "./chromedriver"
driver = webdriver.Chrome(chrome_driver, chrome_options=chrome_options)
driver.get(topic_url)
driver.quit()
执行一个简单的命令指定用unicode更改其中的变量:
pyminifier --nonlatin --replacement-length=10 run.py >> run_new.py
新的文件就会变成下面图片这个样子(我也保存不进去了),但这个只是增加了难度,并不意味着绝对安全,并会带来运行和调试的问题。注意多设置一些条件,注意混淆变量名、函数名、类名、内外模块名。未仔细研究了。