Python 源码混淆与加密

Python 源码混淆与加密Python是一种解释型语言,没有编译过程,发布程序的同时就相当于公开了源码,这也是其作为开源语言的一个特性。但在某些场景下,我们的源码是不想被别人看到的,例如开发商业软件、编写0day漏洞POC/EXP、免杀shellcode等。多人学习python,不知道从何学起。很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。很多已经做案例的人,却不知道如何去学习更加高深的知识。那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

Python 是一种解释型语言,没有编译过程,发布程序的同时就相当于公开了源码,这也是其作为开源语言的一个特性。但在某些场景下,我们的源码是不想被别人看到的,例如开发商业软件、编写 0day 漏洞 POC/EXP、免杀 shellcode 等。

多人学习python,不知道从何学起。

很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。

很多已经做案例的人,却不知道如何去学习更加高深的知识。

那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!??¤

QQ群:1057034340

以免杀为例,如果打包的源码没做任何处理,安全研究人员在捕获到样本后连分析的过程都省掉了,直接通过源码锁定特征,很快免杀就会失效,这显然不是我们想看到的。因此对源码做相应的保护还是有必要的。

注:本文代码只为介绍源码保护方法,不涉及免杀姿势。

目前保护 Python 代码主要有以下几种方式:

  • 对代码进行混淆以降低源码可读性

  • 将 py 文件编译为二进制 pyc 文件

  • 使用 Pyinstaller 打包源码为二进制可执行文件

  • 使用 PyArmor 加密脚本

  • 将 py/pyc 文件使用 AES 加密为 pye 文件

  • 将 py 文件转为 c 文件后编译为动态链接库文件

代码混淆

代码混淆是指在不改变代码逻辑的情况下,对代码结构进行变换,通过一些带有混淆性质的命名、注释等,使代码变得晦涩难懂,从而达到保护代码的作用。这里提供两种代码混淆的方式:

代码混淆库 pyobfuscate

pyobfuscate 会对代码中用户定义的类、函数、变量等进行重命名、更改代码缩进(默认1)、移除注释、添加不影响逻辑的代码语句,最终起到混淆的作用。不过 pyobfuscate 使用 Python2 编写,无法解析 Python3 中的 f-string 等特殊语法,因此使用前需要将源码进行一定程度的修改,当然也可以直接修改 pyobfuscate 库,增加对 Python3 版本的支持。

样例 (对 malicious.py 文件进行混淆):

python2 pyobfuscate.py malicious.py > malicious_obfuscated.py

Python 源码混淆与加密

效果如下图所示,左侧为一段从云端获取 shellcode 加载进内存执行的代码,右图为其混淆后的结果。

Python 源码混淆与加密

可以看出代码虽然进行了一定程度的变换,但代码结构基本还是原来的样子,并不能很有效的增加激活成功教程难度。

利用 AST 混淆源码

AST,即抽象语法树,它可以将源代码以树状结构表示。Python 内置了 ast 模块,该模块通过内置函数 compile() 和 parse() 将  Python 源代码解析为 AST,之后可以利用 ast 模块内的方法对 ast 节点进行相应的操作,混淆处理后使用 codegen 库将 AST 重新生成为 Python 源码。

样例:

python2 astobf.py malicious.py > malicious_astobfed.py

Python 源码混淆与加密

效果如下图所示,AST 混淆后的代码略有修改,以保证 Python3 下脚本可正常执行。

Python 源码混淆与加密

混淆后的代码使用 __import__ 动态导入模块、使用 getattr 调用类方法,这样就可以以字符串方式传入模块名和方法名,借由字符串翻转拼接、数字计算等方式达到混淆目的,相比之下,AST 方式的混淆效果明显要优于 pyobfuscate 库。

编译为 pyc 文件

pyc 文件是 Python 的字节码文件,其存在的意义在于每次调用模块时,不用重新对该模块进行解释,从而提高效率,减少性能损耗。但是在运行一个单独的脚本时,该脚本是不会被编译为 pyc 文件的,这是由于 Python 的解释器认为只有导入的包才会被不断复用,才有编译的价值。不过 Python 提供了 py_compile 库和 compileall 程序用于手动编译 py 文件。

py_compile

import py_compile py_compile.compile(file="malicious.py")

compileall

python -m compileall ./

Python 源码混淆与加密

编译为字节码文件后,确实没办法直接读取源码了,但是 Python 有 uncompyle6 这么一个跨版本反编译器,可以将 Python 字节码转换回等效的 Python 源代码。

python -m pip install uncompyle6 uncompyle6 malicious.cpython-37.pyc > malicious_Decompiled.py

Python 源码混淆与加密

Python 源码混淆与加密

而且 pyc 还有一个弊端,就是它依赖于 Python 解释器的版本,使用某版本解释器编译的 pyc 文件必须使用相同版本解释器运行才能正常工作, 所以实际上将 py 文件编译为 pyc 文件的实用性并不是很大。

打包为独立可执行程序

通过将 Python 文件打包为独立可执行程序也是一种保护源码的方式。Windows 平台下 ,有 Pyinstaller 、 py2exe 和 cx_Freeze 等多种打包程序可以使用,以 Pyinstaller 为例,打包 malicious.py 命令如下:

python -m pip install pyinstaller pyinstaller -Fw -i myicon.ico malicious.py

-F 表示生成单文件,-w 表示隐藏控制台窗口,-i 表示为生成的 exe 文件添加图标。

Python 源码混淆与加密

Python 打包的 exe 程序并不是将文件编译为真正的机器码,而是将脚本编译为 pyc 后连同依赖文件、当前的 Python 解释器一同打包起来,根据命令参数生成文件夹或打包成单独的可执行文件。之后运行 exe 时,实际运行的是一个引导加载程序,引导加载程序会创建一个临时的 Python 环境,通过解释器副本来执行 pyc 文件。 

由于这种运行方式的特殊性,Pyinstaller 打包的 exe 文件也是可以被还原出源码的。使用 pyinstxtractor 解包 exe:

python pyinstxtractor.py malicious.exe

Python 源码混淆与加密

解包后的文件夹内包含了 malicious.pyc 文件,之后使用 uncompyle6 反编译该文件就可以拿到源码。所以将 Python 打包为 exe 只相当于在编译为 pyc 的基础上添加了一步打包操作,同样不能很有效的对源码进行保护。 

使用 PyArmor 加密代码

PyArmor 是一个用于加密和保护 Python 脚本的工具。它能够在运行时刻保护 Python 脚本的二进制代码不被泄露,设置加密后 Python 源代码的有效期限,绑定加密后的 Python 源代码到硬盘、网卡等硬件设备。

它的保障机制主要包括:

  • 加密编译后的代码块,保护模块中的字符串和常量

  • 在脚本运行时候动态加密和解密每一个函数(代码块)的二进制代码

  • 代码块执行完成之后清空堆栈局部变量

  • 通过授权文件限制加密后脚本的有效期和设备环境

PyArmor 的工作原理相对复杂,有兴趣的朋友可以参考官方的说明文档:

https://pyarmor.readthedocs.io/。

使用 PyArmor 默认加密方式加密 malicious.py:

pyarmor obfuscate malicious.py

Python 源码混淆与加密

Python 源码混淆与加密

加密后的文件前两行代码是引导代码,用于加载 pytransform 动态链接库和添加三个内置函数到 builtins 模块,之后调用 __pyarmor__ 导入加密模块执行加密代码。加密后的文件目录还有一个名叫 pytransform 的运行辅助包,它是解密文件所必须的,因此打包加密文件时需要同时将运行辅助包打包进去。

pyinstaller -Fw --add-data "pytransform;pytransform" malicious.py

Python 源码混淆与加密

PyArmor 使用分片式技术来保护 Python 脚本。所谓分片保护,就是单独加密每一个函数,在运行脚本的时候,只有当前调用的函数被解密,其他函数都没有解密。而一旦函数执行完成,就又会重新加密。这种方式相对于混淆来说,效果明显要好的多。 

加密为 pye 文件

pyconcrete 是另一个 python 的文件加密库,安装它需要提供一个密钥,用于之后对源码文件进行加密,同时由于过程中涉及 .c 文件的编译,因此 Windows 下需要安装 VC++ build tools,Linux 下需要安装 GCC。

解压出 pyconcrete 库源码后,使用 setup 进行安装。

python setup.py install

Python 源码混淆与加密

安装成功后复制 pyconcrete-admin.py 文件到项目文件夹就可以使用了。 

pyconcrete 可以将源码文件夹下所有 py/pyc 文件通过 AES128 加密为 pye 文件,该文件无法被正常的 Pyhon 解释器解释,需要使用 pyconcrete 程序加载运行。当然也可以将函数定义部分提出来作为库文件单独加密,函数调用部分独立出来作为一个入口,如下,将 malicious.py 文件拆分为 malicious_func.py 和 malicious_enter.py。

Python 源码混淆与加密

对 malicious_func.py 文件单独加密。

python pyconcrete-admin.py compile --source=malicious_func.py --pye

Python 源码混淆与加密

加密后在只有 malicious_enter.py 和 malicious_func.pye 两个文件的情况下运行 malicious_enter.py 文件,脚本是可以在本地正常运行的,因为解释器在导入 pye 文件时会自动调用环境变量中的 pyconcrete 进行解密。 

Python 源码混淆与加密

如果想将其打包为 exe 在其他机器上运行,还需要进行一些修改:

  1. 修改 malicious_enter.py 文件,在首部导入 pyconcrete,以及加密脚本中需要用到的库,这是为了在调用 Pyinstaller 时,将 pyconcrete 解密程序和脚本依赖的库同时打包进 exe。pyconcrete 库需要在其他库之前导入,它会自动和其他模块挂钩,在其目录寻找 pye 文件,然后通过 _pyconcrete.pyd 对 pye 文件进行解密。

  2. Pyinstaller 不会将 pye 文件主动打包进 exe,需要在打包时通过 –add-data 添加。

Python 源码混淆与加密

这样打包出的 exe 就可以执行了。

Python 源码混淆与加密

使用 pyconcrete 加密的源码在运行时会调用 _pyconcrete.pyd 文件进行解密,该文件内存储了用于解密源码的密钥。由于其密钥隐藏在二进制数据中,无法通过十六进制编辑器直接看到,因此想要解密源码,就必须对 _pyconcrete.pyd 文件进行逆向分析,提取密钥。

编译为 pyd 文件

上面提到的 pyd 文件是 Python 的动态链接库,类似 Windows 下的 DLL 和 Linux 下的 SO,它是 Cython 结合 C 的编译器编译而来,涉及 C 的编译, 因此同样需要 VC++ build tools 或 GCC。

实际上,Cython 是一门单独的语言,专门用来写 Python 的 C 扩展。原本是为了解决 Python 语言的效率问题,但由于其有专门的转换器可以将 .py 文件转换为 .c 文件 (自动加入大量 C-Python API ) 后编译为 pyd,因此也可以利用这个特点来保护 Python 源码,下面为编译方法:

pyd 的文件为库文件,所以也需要一个 py 文件进行调用,这里还是使用 malicious_enter.py 和 malicious_func.py 作为示例。

创建一个 py 文件,用于将 malicious_func.py 编译为 pyd。

# -*- coding: utf-8 -*- from distutils.core import setup from Cython.Build import cythonize setup(     ext_modules = cythonize(['malicious_func.py',]),     )

cythonize 方法会将 malicious_func.py 的 Python 代码转换为 Cython 代码,之后调用 setup 将 .c 文件编译为 pyd。

python build_pyd.py build_ext --inplace

Python 源码混淆与加密

可以直接运行。

Python 源码混淆与加密

也可以打包为 exe,Pyinstaller 会自动将 pyd 文件作为依赖导入。 

Python 源码混淆与加密

编译为 pyd 后,想要了解源码的逻辑就必须通过逆向来分析,相较于从 _pyconcrete.pyd 中提取密钥解密 pye,这种直接将完整逻辑代码编译为二进制文件的方式更不容易被逆向出来,逻辑写的越复杂,逆向分析的代价就越高。 

最后, 上面说的这些 Python 源码保护方法其实正常情况下很少会用得到,既然使用了 Python,一般也不会有人刻意去隐藏自己的代码。不过对于安全领域,这些方法还是有一定价值的。拿免杀来说,复杂的加解密流程,配合上面某些方法,说不定就能很好的隐藏自己的特征,养出一匹低调的马儿。

未完待续… 

360BugCloud开源漏洞响应平台,国内自主议价漏洞收录模式开拓者! 聚焦收录未被披露的开源以及通用组件高危漏洞,致力于维护开源软件和供应链安全。平台采用入驻邀请制,只面向成功提交未被披露漏洞的安全研究员开放。 360BugCloud开源漏洞响应平台首创“自主议价”模式及“第三方专家评审”机制,先议价后交洞,仅需提交漏洞影响力描述即可进行议价,让安全研究员完全掌握漏洞提交主动权,高额奖金上不封顶,让漏洞价值得到充分保障与肯定。

步轻松实现在360BugCloud提交漏洞

Python 源码混淆与加密

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/172365.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 2022年化工自动化控制仪表考试模拟100题及答案详解_化工仪表及自动化答案

    2022年化工自动化控制仪表考试模拟100题及答案详解_化工仪表及自动化答案题库来源:安全生产模拟考试一点通公众号小程序2022化工自动化控制仪表上岗证题目系化工自动化控制仪表培训试题上机考试练习题!2022年化工自动化控制仪表考试模拟100题及答案根据化工自动化控制仪表考试大纲。化工自动化控制仪表判断题通过安全生产模拟考试一点通准确把握考试要点。1、【单选题】“硬水”是指水中所溶的()离子较多的水。(B)A、钙和钠B、钙和镁C、镁和铁2、【单选题】串级控制系统具有一定的自适应能力可用于负荷和操作条件有较大变化的场合,是由于增加了()。(B…

  • c++和java的前景谁更好?

    c++和java的前景谁更好?两门语言都学到能写App的程度是不难。汉小哲觉得但是精通哪怕一门语言都是非常有挑战的。1、C语言是继机器编码、汇编语言之后第一个和计算机语言最为接近的语言,所以它做底层主流语言地位是不可动摇的,java的市场份额比c语言要大,但是在性能上面,C语言要比java快,但是c语言学习没有java简单,在工资方面很多公司c语言的待遇要比java的好。2、一般的C语言,不仅仅说的是c,而是c和c++,c/c++学习难度要大,应用面没有java广,java学习简单写,应用广,比如web开发、手机应有软件开

  • 数据集成之主数据管理(一)基础概念篇

    数据集成之主数据管理(一)基础概念篇

    2021年11月14日
  • js算法初窥02(排序算法02-归并、快速以及堆排序)

    上一篇,我们讲述了一些简单的排序算法,其实说到底,在前端的职业生涯中,不涉及node、不涉及后台的情况下,我目前还真的没想到有哪些地方可以用到这些数据结构和算法,但是我在前面的文章也说过了。或许你用不

  • 使用DbUtils实现CRUD

    使用DbUtils实现CRUD

  • 面试问题spring cloud和dubbo的区别[通俗易懂]

    面试问题spring cloud和dubbo的区别[通俗易懂]最近一段时间不论互联网还是传统行业,凡是涉及信息技术范畴的圈子几乎都在讨论微服务架构 。近期也看到各大技术社区开始组织一些沙龙和论坛来分享spring Cloud的相关实施经验,这对于最近正在整理SpringCloud相关套件内容与实例应用的我而言,还是有不少激励的。目前,SpringCloud在国内的知名度并不高,在前阵子的求职过程中,与一些互联网公司的架构师、技术VP或者CT

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号