反编译Python打包的可执行程序

近期工作中需要逆向分析一个神奇的木马,文件看起来是一个linux下面的elf文件,但是通过常规手段用ida或者ghidra分析完全没有头绪(主要是因为菜>_<),但是通过ida的分析可以看出明显的python痕迹,后来通过万能的谷歌学习到,还有另一种途径可以完美的逆向python打包的可执行程序。本文简要记录一下逆向python打包的elf/exe程序的逆向分析方法。

python打包的可执行程序

将python脚本打包成可执行程序可以更方便的在目标平台上执行,打包工具有很多,其中最常用的当数pyinstaller了,在Linux/Windows平台上可以通过pip安装:

pip install pyinstaller

打包方法很简单,直接对写好的python程序demo.py执行:

pyinstaller -F demo.py

打包好的exe程序会在dist目录中,elf需要在Linux下打包,方法是一样的

pyinstaller打包可执行程序的特征

接下来分析一下用ida打开打包好的elf/exe有什么特征,将exe拖到ida中分析。

  1. main函数特征

首先在函数窗口可以找到main方法,双击打开然后上F5大法

下图中标注了几条main中比较明显的特征,猜测应该是pyinstaller打包的一种固定模式代码

image-20210225223221890.png
  1. 字符串特征

shift+F12查看变量(本例中,想在这里找到程序中的密码是不可能的),可以看到很多Py开头的文件,这也是为什么我开始猜测这个elf文件是由python打包的

image-20210225223510030.png

反编译可执行文件

从ida的内容分析似乎很难找到真正的程序逻辑入口在哪里,后来在谷歌一番搜索终于找到的正确方向。反编译首先要用python(我用python3.7)自带的archive_viewer.py将elf/exe程序提取出pyc文件,然后再从pyc反编译成py

  1. 提取pyc文件

windows下的archive_viewer.py文件目录在{Python_Home}\Lib\site-packages\PyInstaller\utils\cliutils,将这个文件复制到工作目录下,执行如下命令:

python archive_viewer.py demo
image-20210225224909857.png

这里看到分析出目标程序的模块,其中唯一一个不带前缀后缀的就是我们要找的模块

接下来提取该模块x client-update,提取后的文件如下图所示:

image-20210225225419108.png
  1. 修改文件头

使用pyinstaller打包的文件,文件头的数据会被抹消掉。再还原的过程中,我们需要手动进行修补。文件头的格式为:magic(4字节,编译器标志) + 时间戳(4字节)。在实际修补时,需要添加的数据可能不止是8个字节。(笔者python版本为3.7,需要填充16个字节)以下为修补的步骤

承接上面的步骤,除了要提取目标文件.pyc以外,还需要再提一个struct文件:

image-20210225225734159.png

使用二进制编辑工具打开这两个文件,对比发现,提取出的目标文件头部比struct.pyc少了8个字节

[图片上传失败...(image-bb5cab-1626878121733)]

接下来需要将缺失的部分补全,将struct.pyc头部的8个字节内容拷贝到目标文件头部,然后保存文件

image-20210225230130177.png
  1. 反编译pyc文件

    这里需要安装uncompyle6

    pip install uncompyle6
    

    安装后的可执行程序在{Python_Home}/Scripts}下,可以直接执行:

    uncompyle6.exe client-update.pyc > client-update.py
    

可以看到最后反编译的结果非常清晰可读

image-20210225231522152.png

原文链接: 反编译Python打包的可执行程序

推荐阅读更多精彩内容