python编译后的pyd爆破

本文为看雪论坛优秀文章

看雪论坛作者ID:rushmaster

‍‍
最近接触一个国外某app的协议软件,是python3.8写的,它把关键模块都编译成了pyd,然后使用pyinstaller打包发布给用户。软件启动后检查机器码,然后需要输入授权码才可使用,看着很是恼火,所以想尝试破解。其中关键应该是需要爆破pyd里的逻辑,修改汇编代码来实现绕过授权。

前提知识

1. py、pyc、pyo、pyd
py: python 脚本文件(source code)
pyc: 脚本文件编译得到的字节码, 二进制文件,python文件经过编译器编译之后的文件。可以提高文件加载速度。
pyo: 脚本文件开启优化编译选项(-O)编译得到的字节码,二进制文件,优化编译后的文件。可以通过python -O file.py生成。
pyd: 基本的Windows DLL文件,python的动态链接库。
2. 编译pyd
要编译的脚本:uitl1.py
def fun_hello(s): if s == 1: return 'hello world' elif s == 2: return '222222222'
提供编译脚本:setup.py
from setuptools import setupfrom Cython.Build import cythonize setup(    name='test',    ext_modules=cythonize('util1.py'))
在setup.py文件所在目录下进行如下命令:
python setup.py build_ext --inplace
这样就能看到同级目录下生成pyd文件了。32位的python生成pyd文件是32位的,64位的python生成的是64位的。
3. 使用pyd  
test.py
import util1 if __name__ == '__main__':    print(util1.fun_hello(2))
4. pyinstaller打包py到exe
pip install pyinstaller
pyinstaller test.py
5. 解包pyinstaller打包的exe
pyinstxtractor.py即可。这个代码不长,可以调试看看,熟悉下打包的exe组成。需要注意的是,被打包的文件都是zlib.compress压缩过后,再按照固定格式组成exe的,所以直接修改打包后的exe的16进制码来爆破貌似不好操作。只能解包后修改pyd,然后找齐依赖的库,重新pyinstaller打包,实现爆破。
https://github.com/countercept/python-exe-unpacker
6. pyc反编译
uncompyle6支持python3.8的pyc的反编译。
需要注意的是,如果是pyinstaller解包后取到的pyc文件,文件头部的magic被抹除过了,所以需要把对应版本python的magic加上来,可以装对应版本python,然后到安装目录下随便找个pyc文件,看一下头部,然后用010Editor复制到解包后的pyc,就可以正常反编译了。
下图是python3.8_32位的magic头:
https://github.com/rocky/python-uncompyle6

pyd文件汇编代码和python脚本的对应关系分析

前面的前提知识,随便搜搜都能找到。但是如何才能直接修改pyd的汇编代码,实现python脚本流程的更改呢?
我百度谷歌搜了半天也没找到合适的资料,也许很少有人破解python编译打包的exe吧。
那么下面就是我做的工作了,也是本帖的价值所在了。
我自己写了一个python小脚本,然后编译成了pyd,它会生成一个中间的util1.c文件,代码大概有3000多行。只要花时间精力熟悉这个c文件,然后对照着ida就可以了解python脚本转成C然后编译成汇编指令,它们3者之间大概对应关系了。
下面略过大概1天的工作量,直接给出我们拿到一个pyd后,怎么快速找到我们要找的关键python代码。然后直接爆破。
把要分析的pyd文件拖到对应32位或64位的IDA:
大概所有的pyd都只有这个一个导出函数,当这个pyd模块被其他py脚本import时会调用这个导出函数进行模块初始化。
跳转到dword_1000634C可以看到一个结构体,里面有一个关键的成员__pyx_moduledef_slots。
这个成员是一个结构体数组。
里面有个关键函数__pyx_pymod_exec_util1负责初始化python脚本里的所有变量,函数,常量等等,把他们都对应到pyobject,然后就只使用这些pyobject了。所以汇编里看流程就很难,因为没有明显的明文了。
定位到 __pyx_pymod_exec_util1后,我们主要的目的是找常量和pyobject的对照表,python脚本里的函数名和汇编函数的对照表,有这2个表,python脚本和汇编的对应关系就明朗了。这里就只能手动往下翻了。
翻到类似调用 PyUnicode_InternFromString 的地方,大概就是我们要找的常量对照表了。
也就是C文件里的这个表。
其中offset dword_10006DFC就是代表字符串'222222222'的pyobject,直接找它的交叉引用就可以定位一些关键代码了。
我们继续在 __pyx_pymod_exec_util1 里找python脚本函数对应汇编函数的那个表。
跳过去:
aFunHello指向python脚本里的函数名。
__pyx_pf_5util1_fun_hello就是对应的汇编函数。
可以看到,只要找到这个表,就很容易定位我们要找的python脚本函数对应的汇编实现了。
其实我们也可以不必如上这么麻烦。只要在.data段里翻一翻。或者string窗口找到感兴趣的字符串交叉引用也能很快找到这个表。
需要知道的就是, aFunHello下面就是对应的汇编实现函数。
现在终于可以去分析fun_hello这个python脚本函数对应的汇编函数了。
可以看到脚本里的 s == 1 对应的汇编就是  __Pyx_PyInt_EqObjC 然后下面会使用PyObject_IsTrue判断这个函数的返回值。
那么爆破点就找到了。把 jz short loc_10004753 改成jnz short loc_10004753即可。
IDA-》edit-》Patch program-》Assemble修改,然后 IDA-》edit-》Patch program-》Apply patches to input file即可得到修改后的pyd文件。
这样就实现了修改python脚本的执行逻辑了。
正常脚本应该是输出22222222才对,因为我们的爆破,输出了hello world!
这里我只是简单分析了if语句的修改,可以多写几个例子。实现修改其他流程。
在此只是抛转引玉,给大家一点点参考。省一点点时间。
另:大家看了半天以为我是分析那个国外app协议软件,其实我还没有搞定那个破解,所以只把自己这段时间的分析工作贴了上来,仅供参考。
(0)

相关推荐

  • Python如何发布程序的详细教程

    如何发布一个Python程序: 1.安装一个pyInstaller 在pycharm里点 file -–>setting-–>Project workspace-->Interpre ...

  • python新手用pyinstaller -F - w test.py打包后的exe无法运行

    python新手用pyinstaller -F - w test.py打包后的exe无法运行 置顶 风很大很大 2020-03-15 09:46:46  1662  收藏 3 分类专栏: 笔记 版权 ...

  • python代码如何打包为.exe文件

    我使用的python版本为3.6,现在最新的python版本是3.7,但是pyinstaller现在还不支持最新的3.7,所以大家不要用最新版本的python,最新版本的兼容性不好.下面我们正式开始吧 ...

  • 如何加密你的 Python 代码

    前言 本文将首先介绍下现有源码加密方案的思路.方法.优点与不足,进而介绍如何通过定制 Python 解释器来达到更好地加解密源码的目的. 现有加密方案 由于 Python 的动态特性和开源特点,导致 ...

  • (6条消息) python文件编译与pyc反编译

    pyc是编译py之后生成的二进制文件.当我们发布系统的时候不想让别人看到源代码,就需要将py文件编译生成pyc文件,对外只提供pyc文件.同样,如果拿到一个python程序,只有pyc文件,我们就无法 ...

  • QT Creator 使用 design 修改 ui界面编译后界面未更新问题的解决 From EricQu

    今日遇到一个奇怪的问题,描述如题. 网上搜索了一些解决方案,说的不是很清楚,经过一些时间的摸索,这里总结一下解决方法. ui源文件到界面显示的原理可以网上搜索,这里不再描述.简单讲就是先要从*.ui生 ...

  • 程序编译后运行时的内存分配

    一.编译时与运行时的内存情况 1.编译时不分配内存 编译时是不分配内存的.此时只是根据声明时的类型进行占位,到以后程序执行时分配内存才会正确.所以声明是给编译器看的,聪明的编译器能根据声明帮你识别错误 ...

  • 如何找到 SAP Spartacus 里某个 Component TypeScript 编译后生成的 JavaScript 位置

    需求 如何找到触发该网络请求的准确代码位置? 从 initiator 里查看调用栈上下文,一点头绪也没有. 找到触发该网络请求的控件的 selector:cx-register 在 Storefron ...

  • python考后感悟

    原来自己与成功只有一步之遥. 只要有可以挽回的机会一定要争取. 不要妒忌别人的成功 ,因为你没有看到别人背后的努力. 做自己该做的事情,不必东张西望,不必踌躇满志,什么年龄段该做什么就去做什么?例如知 ...

  • 闲鱼上哪些商品抢手?Python 分析后告诉你

    第一时间获取 Python 技术干货! 阅读文本大概需要 10 分钟. 1 目 标 场 景 经常看到有朋友在闲鱼卖些小东西又或是自己擅长的一些技能,都能为他们带来不错的 睡后收入. 闲鱼上大量的商品, ...

  • 专家鉴定大桥是危桥,380公斤炸药爆破后,却炸出一群“伪专家”

    贾岛<题李凝幽居>:"过桥分野色,移石动云根." 不知从何时开始,现代的人总是抱有一种刻板的印象,那就是对于从前那个科技不算先进的时代所创造出来的产物,总是第一时间去否 ...

  • 运行 Java、Python、Go 等 25 种代码后,发现性能最强的竟然是它!

    本文通过一道程序面试题,使用不同的编程语言来实现,检验每种语言的简单版本与优化后版本的运行速度分别是多少,横向对比 Python.Go.C .C.Rust 等编程语言的性能, 作者 | Ben Hoy ...

  • 江西工地炸出一千年古墓,专家勘察后下令:必须爆破,将墓全搬走

    我们现在博物馆中看到各种各样的古代文物,是不是真心体会到了古人的那种超强的智慧和创造力,我们除了要感谢古人的劳动成果之外,还必须要感谢一种人,他们就是中国的考古队,没有他们的辛勤付出,我们根本是欣赏不 ...

  • Selenium2+python自动化60-异常后截图(screenshot)

    前言 在执行用例过程中由于是无人值守的,用例运行报错的时候,我们希望能对当前屏幕截图,留下证据. 在写用例的时候,最后一步是断言,可以把截图的动作放在断言这里,那么如何在断言失败后截图呢? 一.截图方 ...