使用python语言如何保密源代码以防止逆向工程?

Python0102

使用python语言如何保密源代码以防止逆向工程?,第1张

大家都很忙,谁有时间看你的的烂代码! 如果真的怕泄露,别用python. 我以前做过这类事情,而且当时更严格,需要打包部署到客户的服务只在有效期内有效,超过有效期必须更新证书才行。 Python代码用任何方法都没法保证保密性,这个时候你可以考虑用一个工具「nuitka」,这个工具会把你的python源代码映射为c++然后编译为二进制,因此对方是无论如何得不到你的源代码的。 代价就是nuitka这个工具并不完美,有一些限制并不能100%完美的转换所有python代码。 1.用Cython编译python成 Windows的pyd文件或Linux的so文件,二进制文件相对安全性较高。 2.用源码混淆器把代码搞的又臭又长。。。混淆完了再用Cython编译为二进制。。。这样静态反编译逆向难度也不小。 3.同其他语言程序一样,可以对调试状态进行检测,当处于调试状态时退出程序或进入混乱代码耗费逆向工程人员心神。 4.分享一个跨平台反调试手段,检测函数运行时间,加断点会导致函数运行时间变长,也可感知正在被调试。 Python是提倡开源的,既然选择Python还是拥抱开源才好~ 都开源还担心逆向工程嘛没有不能逆的软件。 只要汇编语言过关,逆向工程都是可以实现的,不要有其它想法。 你唯一可以做的,就是不让别人用python读取源代码而已。那样实现起来比较简单。 python 适合开发服务器程序,或者自己科研使用的程序,如果是 作为用户程序,安装到 pc 或手机上,还是 其它 c++ 或java 比较合适 1)可以把需要保护的部分用c语言实现,从而编译成so等文件,这样逆向的成本会比较高,可以防止直接打开python文件看到代码逻辑。 2)so文件通过ida等工具也是可以反汇编的,可以通过对c语言进行代码混淆,花指令等操作,提高通过ida等反汇编工具的分析难度。 3)不存在绝对无法逆向的技术手段,因此只能是看具体需求,选择具体的防逆向的技术手段。 有工具类似py2exe转成可执行程序,隐藏全部源代码,虽然bytecode还是可以反编译,但是难度大多了 1. 最稳的就是你改cpython加载代码的过程,改zip包读取最稳。 2. 借助一些加密工具在编译pyc之前进行一定的混淆,可以防君子,自我安慰一下。 商用一般都是用第一种办法,小打小闹用第二种。可以考虑使用pymod工具,使用pymod pack 将模块加密打包,发布的时候一个模块就一个文件。 先睹为快,看看一个项目发布的时候,只有几个文件, main.py 项目程序入口 setting.py 项目配置 apps 项目模块 plusins 项目插件目录创建项目 pymod create demo1 cd demo1 创建模块 pymod add mod1 启动pycharm 开始编写功能模块 一个模块默认由三个文件组成 __init__.py 、 handlers.py 、param_schemas.py 业务逻辑主要在handlers.py中编写 __init__.py from pymod.blueprint import Blueprint api = Blueprint("/mod1") from .handlers import * param_schemas.py schema_sfz = { "type": "object", "required": ["sfz", "nl"], "properties": { "sfz": { "type": "string", "minLength": 18, "maxLength": 18, "description": "身份证明号码" }, "nl": { "type": "integer", "minimum": 0, "maximum": 150, "description": "年龄" } } } handlers.py from . import api from pymod.ext import RequestHandler, params_validate,TrueResponse,FalseResponse from .param_schemas import schema_sfz from pymod.plugins import sfz_check @api.add_route('/hello') class Hello(RequestHandler): def get(self): self.write('Hello World') @params_validate(schema_sfz) def post(self): sfz = self.get_json_arg("sfz") nl =self.get_json_arg("nl") # self.write(TrueResponse(sfz=sfz, nl=nl)) if sfz_check.check_sfzmhm(sfz): self.write(TrueResponse(hint="身份证明号码验证通过")) else: self.write(FalseResponse(hint="身份证明号码验证失败")) 三、项目部署 程序调试 修改setting.py # 开发模式下 运行的模块名称必须填写 modules = ["mod1"] modules_config ={ "mod1": { "deny_ip": "", "allow_ip": "*" } } 启动程序 python main.py 调试没有问题,进入发布模式 在项目目录下 pymod pack mod1 在target目录下生成mod1.mod文件,将其复制到apps目录中 修改setting.py # 开发模式下 运行的模块名称必须填写 modules = [] 再次运行 python main.py 测试 一切OK,系统就可以发布了。说不能保密的,是没有研究过python的机制的。我做个一个项目,所有源代码自定义加密,运行时解密。

代码加密

大概整理了以下几种方法:

编译成pyc文件

使用py2exe将python代码转成window下执行的exe文件

关键代码部分使用c或者c++写,然后在python中调用

用C写一个license,进行license验证

作为一门解释型的语言,加密的难度超级大。下面来简单分析上面的解决方案:

编译成pyc文件几乎跟pyc没有区别,保护力度太低

要是在linux机器上就没法使用,而且这种exe文件也可以被破解的

核心代码部分是计算密集型,用的是pandas,numpy等库,用c重写,简直不可能,工作量太大。

没搞过,不知道………

看来上面的解决方案都是不行的,在stackoverflow上对这个问题也进行了详细的讨论,用我蹩脚的英文来翻译(意译)一下得票率最高的:

“有什么方法来解决这个问题吗?(加密的问题)”没有。任何保护都可以被逆向工程破解。就连DVD机的固件都可以被破解,尽管法律判定其为非法,但是AACS加密密钥还是泄露出来。

因为没有技术的方法可以阻止你的客户看你的代码,你必须用传统的商业方法。

1. 许可证,合约,条款,条件。只要用户签订了这些东西,及时用户可以看见代码,也会有法律约束(不过此建议在中国目前貌似不顶用)

2. 提供巨大的价值。如果你的东西非常好,而且价格很合理,那么用户很难拒绝——没必要浪费时间和金钱去搞逆向工程啥的,因为逆向工程是很费银子的。让你的产品有足够的性价比。

3. 经常性的升级和增加新的功能,使得逆向工程不那么好使。当下一个版本破坏了逆向工程,那么以前的破解就没有意义了。

4. 定制化生产,为不同的客户提供不同的产品。(貌似代价有点高啊)

5. 使用有时间限制的许可证,这会给你带来不好的名声,但是会保证你的软件会停止工作

6. 设计为web service.

代码混淆

既然加密不是一个好方法,那要还是不死心,那就做一个简单的混淆算了,虽然只能”防君子,不防小人“。但是不能就这样把代码暴露出来。

这里推荐一个找了好久的东西: pyobfuscate这个东西在window7中的cmd中貌似总是混淆失败,无奈用了MINGW32,居然搞定了。官方的资料有这样的介绍:

pyobfuscate有几种转化代码的方式,有些可逆,有些不可逆。

移除注释和文档 ( 不可逆)

改变缩进(可逆)

在tokens之间加入空格(一定程度上可逆)

重命名函数,类,和变量(不可逆)

在空白行中加入无效的代码

我没有选择混淆函数名和类名,因为其他地方还要调用呢。下面是我混淆的结果,还挺好看的:

def my_fuction_to_test ( self , start_date , end_date ) :

iiiii11iII1 = self . get_something ( start_date , end_date )

O0o = [ ]

for oO0 in iiiii11iII1 :

if oO0 [ "isOpen" ] == 1 :

IIIi1i1I = { }

OOoOoo00oo = dt . strptime ( oO0 [ 'calendarDate' ] , '%Y-%m-%d' )

IIIi1i1I [ 'day' ] = OOoOoo00oo . strftime ( '%Y%m%d' )

IIIi1i1I [ 'week' ] = oO0 [ 'isWeekEnd' ]

IIIi1i1I [ 'month' ] = oO0 [ 'isMonthEnd' ]

IIIi1i1I [ 'weekday' ] = OOoOoo00oo . weekday ( )

O0o . append ( IIIi1i1I )

iiI11 = pd . DataFrame ( O0o )

return iiI11

可以使用pymod对代码加密部署

先睹为快,看看一个项目发布的时候,只有几个文件,

main.py 项目程序入口

setting.py 项目配置

apps 项目模块

plusins 项目插件目录

项目发布目录一览

二、创建项目

创建项目 pymod create demo1

cd demo1

创建模块 pymod add mod1

启动pycharm 开始编写功能模块

一个模块默认由三个文件组成

__init__.py 、 handlers.py 、param_schemas.py

业务逻辑主要在handlers.py中编写

__init__.py

from pymod.blueprint import Blueprintapi = Blueprint("/mod1")from .handlers import *

param_schemas.py

schema_sfz = {

"type": "object",

"required": ["sfz", "nl"],

"properties": {

"sfz": {

"type": "string",

"minLength": 18,

"maxLength": 18,

"description": "身份证明号码"

},

"nl": {

"type": "integer",

"minimum": 0,

"maximum": 150,

"description": "年龄"

}

}

}

handlers.py

from . import api

from pymod.ext import RequestHandler, params_validate,TrueResponse,FalseResponse

from .param_schemas import schema_sfz

from pymod.plugins import sfz_check

@api.add_route('/hello')

class Hello(RequestHandler):

def get(self):

self.write('Hello World')

@params_validate(schema_sfz)

def post(self):

sfz = self.get_json_arg("sfz")

nl =self.get_json_arg("nl")

# self.write(TrueResponse(sfz=sfz, nl=nl))

if sfz_check.check_sfzmhm(sfz):

self.write(TrueResponse(hint="身份证明号码验证通过"))

else:

self.write(FalseResponse(hint="身份证明号码验证失败"))

三、项目部署

程序调试 修改setting.py

# 开发模式下 运行的模块名称必须填写

modules = ["mod1"]

modules_config ={

"mod1": {

"deny_ip": "",

"allow_ip": "*"

}

}

启动程序 python main.py

调试没有问题,进入发布模式

在项目目录下

pymod pack mod1

在target目录下生成mod1.mod文件,将其复制到apps目录中

修改setting.py

# 开发模式下 运行的模块名称必须填写

modules = []

再次运行 python main.py 测试

一切OK,系统就可以发布了。

pymod 使用指南,访问 https://pymod.cn