索引
I – python 如何深入工作
– Ia – OpCodes
– Ib – PYC 文件
– Ic – Python 对象
II – 逆向和解压 PyInstaller
III – 逆向和解压 CxFreeze
IV – Python
V代码注入- 逆向和解压 PyArmor
VI – 如何保护
IIX – 一些额外的文档
Python 是如何深入工作的
在本章中,我将重点关注 Python 的低级方面,即。IE。解释器、python 堆栈和 python 线程。
我们将专注于每个人都拥有的解释器 CPython。
解释器从调用函数开始对比:
Py_Initialize();
这将初始化解释器和线程。
如果解释器初始化成功,那么我们就可以访问 Python 对象,并且解释器已准备好而且被解释为你好
OpCodes
OpCodes 或Operation Code 是python 解释器的汇编语言。
通常,当用本地语言编译程序时,代码由编译器直接翻译成汇编语言,再翻译成二进制文件供计算机执行。
![逆向分析之破解和解压Python打包工具插图1 逆向分析之破解和解压Python打包工具插图1](https://static.esw.eswlnk.com/2021/12/2021120908002643.png)
(在 c ++ 中打印 hello world 代码并使用 Visual Studio 2019 编译的程序)
但是对于 python,它是不同的,这里是相同的程序(大致)在 python 中编码并使用dis反汇编
![逆向分析之破解和解压Python打包工具插图2 逆向分析之破解和解压Python打包工具插图2](https://static.esw.eswlnk.com/2021/12/2021120908015445.png)
如果有人想要将这些字节码转换为十六进制并在 asm 中编码,甚至修改文件,应用程序就会出错并崩溃。因为计算机无法识别它必须询问的指令。
在 python 中的每个应用程序/脚本后面都有操作码,因为您还可以看到操作码相当精确,即使不一定知道它,您也可以轻松猜测应用程序的作用,甚至重新编码应用程序。
PYC 文件 pyc
文件只是 python 编译器文件,所以我们在上面讨论了操作码。
![逆向分析之破解和解压Python打包工具插图3 逆向分析之破解和解压Python打包工具插图3](https://static.esw.eswlnk.com/2021/12/2021120908024855.png)
这就是我们在十六进制编辑器中打开 pyc 文件时的样子
最重要的部分是模块的标题和结尾(实际上它们都是,但有时由于某些部分有缺陷,您可能会遇到问题) .
ps:头文件取决于生成脚本的python版本所以想一想
有人说这会提高执行速度,但我们今天知道这是错误的,它只是提高了初始化速度解释器。
Python 对象
早些时候我谈到了 Python 对象,但没有解释它是什么,现在我将解释它,所以请睁大你的耳朵。
为了避免过多的细节,你可以在 python 中做所有的 Python 对象,即。IE。变量、字符串、模块、查询,但在 c 中重新定义。
例如,python 中的字符串,将是 c 中的 struct PythonObject。
Reverse & Unpack PyInstaller
现在我们将进入问题的核心。
我将向您介绍两种技术,一种是手动的,另一种是自动化的,还有另一种方法,但我稍后会讨论。
手动方法
对于手动方法,如果软件是 64 位,您将需要 x32dbg 或 x64dbg,并且知道 CPython 是如何工作的。
启动您的 x32dbg 并使用 PyInstaller 运行脚本“compile”,然后转到 Breakpoints 窗口,右键单击 -> Add DLL BreakPoints,然后添加脚本为我使用的 python dll 将是python38.dll
.
不仅仅是启动软件并等待它加载。
![逆向分析之破解和解压Python打包工具插图4 逆向分析之破解和解压Python打包工具插图4](https://static.esw.eswlnk.com/2021/12/2021120908060215-1024x522.png)
这是 dll 的入口点,现在我们将使用命令断点PyEval_EvalCode函数bp PyEval_EvalCode
。
该函数用于执行python操作码。
但在继续之前,我有需要解释一下 pyinstaller
是如何工作的
当您输入命令时pyinstaller script.py
,pyinstaller 将编译您导入脚本的所有模块,复制您的脚本并在 python 操作码中编译它,并复制您的 dll python 版本,例如 python38.dll
之后它会“压缩”用 zlib 编译的脚本,这就是为什么当你在 Detect It Easy 中使用 pyinstaller 传递打包脚本时,它会输出为 zlib 存档。
所以,一旦断点设置,让我们回到我们的小脚本,您将启动它,直到您在堆栈中看到脚本的名称,如下所示
![逆向分析之破解和解压Python打包工具插图5 逆向分析之破解和解压Python打包工具插图5](https://static.esw.eswlnk.com/2021/12/2021120908063589.png)
如果你看到了,你是在右边的人看到它缺少更多的情况检查 ebp 寄存器,看看它是否有你的软件的字符串如果是,复制十六进制代码并修复模块的头部和结尾,如果不重申手术。
要复制脚本,您只需右键单击 -> 二进制 -> 复制并将其放入十六进制编辑器。
要修复标头,只需从另一个 base_library.zip 文件复制标头,如果模块的末尾损坏,则相同。
现在要转录操作码,建议使用uncompyle6,其他的工具也可以,不过个人认为没有这个好。
要安装它,没有什么比这更简单的了,您只需要输入pip install uncompyle6
,然后转录您只需输入的操作码uncompyle6 script-unpacked.pyc
如果一切正常,我们将会看到以下结果:
![逆向分析之破解和解压Python打包工具插图6 逆向分析之破解和解压Python打包工具插图6](https://static.esw.eswlnk.com/2021/12/2021120908074217.png)
自动方法
自动化技术更为人所知,您只需要安装pyinstxtractor脚本即可从 exe 中提取 pyc 文件,然后将操作码转换为我上面做的。
这种方法有几个缺点,使用这种方法的人已经大多数对python和reverse一无所知,所以他们是skid,那么很容易欺骗脚本,我将向您展示。
Python:
MAGIC = b'MEI\014\013\012\013\016' # Magic number which identifies pyinstaller
# in hex is 4D 45 49 0C 0B 0A 0B 0E
def checkFile(self):
print(self.MAGIC)
print('[+] Processing {0}'.format(self.filePath))
# Check if it is a 2.0 archive
self.fPtr.seek(self.fileSize - self.PYINST20_COOKIE_SIZE, os.SEEK_SET)
magicFromFile = self.fPtr.read(len(self.MAGIC))
if magicFromFile == self.MAGIC:
self.pyinstVer = 20 # pyinstaller 2.0
print('[+] Pyinstaller version: 2.0')
return True
# Check for pyinstaller 2.1+ before bailing out
self.fPtr.seek(self.fileSize - self.PYINST21_COOKIE_SIZE, os.SEEK_SET)
magicFromFile = self.fPtr.read(len(self.MAGIC))
if magicFromFile == self.MAGIC:
print('[+] Pyinstaller version: 2.1+')
self.pyinstVer = 21 # pyinstaller 2.1+
return True
print('[!] Error : Unsupported pyinstaller version or not a pyinstaller archive')
return False
这是 pyinsxtractor 脚本的功能,它检查脚本是否确实是 pyinstaller 存档,为此它检查是否存在幻数,聪明的人已经理解了。您只需要更改幻数,以便脚本无法提取存档。绕过这个小技巧很容易,但看到大多数使用这个脚本的人是skid。
Reverse & Unpack CxFreeze
类似于 PyInstaller一样将向您展示两种技术,一个是手动的,另一个是自动化的,还有另一种方法,但我稍后会讨论。
手动方法
要手动解压缩 cx_Freeze 下的脚本,只需转到 lib 文件,然后转到 library.zip。
打开 library.zip 后,查找名为“lenomduscript__main __.Pyc”的文件
![逆向分析之破解和解压Python打包工具插图7 逆向分析之破解和解压Python打包工具插图7](https://static.esw.eswlnk.com/2021/12/2021120908095827.png)
一旦你发现提取文件就足够了,主要是反编译字节码,这 要归功于 uncompyle6
自动方法
要自动解压 cx_Freeze 下的脚本,只需安装我的 python 脚本,您可以在这里找到:cxFreezextractor。下载完毕后,将它放在与解压脚本相同的文件中想要并将 exe 拖到我很棒的 h4x0r 脚本上,然后让它发挥作用。接着你就可以使用 uncompyle6 反编译所有东西
Python 代码注入
现在对我来说最有趣的部分
是 CPython API,我们可以与 python 交互,甚至可以使用 c++ 与 python 中的代码交互,
这是一个例子:https://docs.python.org/3/extending/embedding.html
所以只需制作一个 dll 并使用 APIPyRun_SimpleString
就可以调用函数、重新定义它们、注入 webhook 等……因此非常好使用。
PS:它也适用于不是用python制作的本机应用程序,您可以轻松地使窃取者几乎无法检测到
但是您需要为大多数应用程序提供一个特殊的注入器,以便在python的dll加载或pyarmor的dll时注入。
DWORD WINAPI MainThread(HMODULE hModule)
{
Py_SetProgramName(L"pyinject");
bool init = Py_IsInitialized();
if (init)
{
PyEval_InitThreads();
PyGILState_STATE s = PyGILState_Ensure();
PyRun_SimpleString("def auth():\n return True");
PyGILState_Release(s);
}
CloseHandle(hModule);
FreeLibraryAndExitThread(hModule, 0);
return 0;
}
因此,用这个“解压” pyarmor也是一个不错的选择
逆向与解压PyArmor
此外,我正在谈论解包,但我们将比其他任何事情都更要反汇编字节码函数。
因此,对于“解包”pyarmor,我们将采用顶级 dll 并使用允许您反汇编 Python 函数的 dis 模块。
由于这行代码,您只需要找到函数import dis,os,inspect,sys\nscriptMem = inspect.getmembers(sys.modules[__name__])\nfor name in scriptMem:\n print(name)
或进行猜解,然后您只需使用此代码注入 dllimport dis\nprint(dis.dis(auth))
ps:您要反汇编的函数必须正在运行,因为 pyarmor 在运行时加密和解密字节码,因此如果函数未加载,因此未使用字节码,它将不会解密它们。
ps:在某些版本的pyarmor
ps2上使用此方法:您也可以将此方法用于pyinstaller或cx_Freeze
如何保护自己的python程序
要保护它没有3000个解决方案,您只需要使用像pyarmor这样强大的obfu或从阻止 LoadLibrary API,编写好您的身份验证系统,然后祈祷不会有人破解您的软件,不过攻防是相对的,没有绝对的安全。对于开发人员,您应该查阅有关文档的章节,特别是 defcon 的视频,该视频解释了除此线程之外的许多内容。
有了这个,大多数人 (skids) 将无法破解您的软件。
📮评论 (1)