PyInstaller与Cython

在PyInstaller第一弹PyInstaller打包Python代码与其不安全因素验证中验证了稍微研究下就可以获得源码,那么怎么使用Cython来提高点反编译门槛呢?

代码结构

还是以第一弹中的代码为例子,稍作修改,文件结构如下:

1
2
3
4
5
6
$ tree
.
├── calc.py
└── exec.py

0 directories, 2 files

假设我们不希望别人能通过第一弹的方式获取calc.py的源码,想对其加密,由exec.py进行调用,分别看一下calc.pyexec.py的代码内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/python3
# -*- coding=utf8 -*-
# cython: language_level=3

import numpy as np


class Calc:
def __init__(self):
self.a_array = [[1, 0], [0, 1]]
self.b_array = [[4, 1], [2, 2]]

def calc_matmul(self):
return np.matmul(self.a_array, self.b_array)
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/python3
# -*- coding=utf8 -*-

import sys

sys.path.append('./calc/')
from calc import Calc

if __name__ == '__main__':
c = Calc()
result = c.calc_matmul()
print(result)

Cython编译

我们现在将calc.py编译为SO文件,新建setup.py,写入如下内容:

1
2
3
4
5
6
7
8
9
10
# cython: language_level=3
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

ext_modules = [
Extension("calc", ["calc.py"]),
]

setup(name='calc', ext_modules=cythonize(ext_modules), requires=['Cython'])

然后进行执行编译:

1
2
3
4
5
6
7
8
9
10
$ python setup.py build_ext
Compiling calc.py because it changed.
[1/1] Cythonizing calc.py
running build_ext
building 'calc' extension
creating build
creating build/temp.linux-x86_64-3.7
x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/home/top/CodeWork/Python/ABC/venv/include -I/usr/include/python3.7m -c calc.c -o build/temp.linux-x86_64-3.7/calc.o
creating build/lib.linux-x86_64-3.7
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.7/calc.o -o build/lib.linux-x86_64-3.7/calc.cpython-37m-x86_64-linux-gnu.so

将生成的build/lib.linux-x86_64-3.7目录下的calc.cpython-37m-x86_64-linux-gnu.so文件拷贝至calc目录:

1
2
$ mkdir calc
$ cp build/lib.linux-x86_64-3.7/calc.cpython-37m-x86_64-linux-gnu.so calc

spec文件加入so

按照第二弹PyInstaller与资源文件的方式生成spec文件:

1
2
3
$ pyi-makespec --onefile exec.py 
wrote /home/top/CodeWork/Python/ABC/addso/exec.spec
now run pyinstaller.py to build the executable

将刚编译好的so文件加入datas中:

1
2
3
4
5
6
7
8
9
10
11
12
a = Analysis(['exec.py'],
pathex=['/home/top/CodeWork/Python/ABC/addso'],
binaries=[],
datas=[("./calc/calc.cpython-37m-x86_64-linux-gnu.so", "calc")],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)

进行打包:

1
pyinstaller exec.spec

现在就和之前一样了,拷贝到另一台机器做测试:

1
2
3
4
$ chmod +x exec 
$ ./exec
[[4 1]
[2 2]]

这样就成功的将PyInstaller与Cython结合使用,能在一定程度上提高反编译门槛,保护我们的源码。顺便看一下反编译SO文件的样子吧(到这里真的就只是看看):

结束

PyInstaller连着写了三篇,到这算是告一段落了,实际工作中的情况肯定比文章中举例要复杂的多,后面会不会深入研究其他功能再说吧,比如Bootloader

0%