python exe 反编译_原创干货 | 【恶意代码分析技巧】02exe_python

5a5654e4e4c821a94e3a5446f283d4ac.png

a5c2bd5813b1b2911ebd428b5b49d9f4.png 由于恶意代码分析系列第一篇发出后,被粉丝强烈催更,小编不得不加急为大家更新了第二篇,作者大大还在持续编写中,这次的系列会非常的丰满哦,请大家持续关注公众号,第一时间收到系列更新哦!

a519bcbf86a63acaf850e344c384771d.png

1、python虚拟机

    计算机发展至今已经有了机器语言、汇编语言和高级语言三种。计算机能够直接识别的是机器语言,不同的CPU使用的机器语言不是完全相同的;汇编语言本质上是和机器语言是一样的,只不过汇编指令采用了英文标识符,它和机器语言一一对应;高级语言是对人类友好的语言,但计算机是不能直接识别高级语言的,高级语言需要翻译成机器语言,然后才被计算机识别。

    高级语言被翻译成机器语言的过程分为两类,第一种是编译,第二种是解释。编译执行的程序在执行前,会先通过编译器进行编译,把高级语言转变为机器语言,然后再执行;解释执行的程序在执行时,由解释器对程序逐行解释成机器语言,一边解释一边执行。编译类的程序一旦修改,必须修改源代码,然后重新编译执行;解释类的程序进行修改,只需要修改相应行代码即可运行,即使代码出错也不会影响前面代码的执行。

    python是一种脚本语言,但python“翻译”的过程中,不仅需要解释还需要编译,这是因为python是一门基于虚拟机的语言。

    一般我们都是说python通过python解释器解释执行,但实际上python是利用字节码虚拟机解释执行的。python先把代码(.py文件)编译成字节码,字节码存放在内存中PyCodeObject对象中,然后将交给字节码虚拟机,然后虚拟机会从编译得到的PyCodeObject对象中一条一条执行字节码指令。当Python程序运行结束时,Python解释器则将PyCodeObject写入到.pyc文件中,.pyc文件在磁盘中保存。当python程序第二次运行时,首先程序会在硬盘中寻找.pyc文件,如果找到,则直接载入,不需要编译就能载入python虚拟机执行,否则就重复上面的过程。

    所以,python是先编译然后再解释执行的。

157105185d8dee791f50395d13008f4a.png

    再补充一点,PyCodeObject对象的创建时机是模块加载的时候,即import。Python test.py会对test.py进行编译成字节码并解释执行,但是不会生成test.pyc。如果test.py加载了其他模块,如import util,Python会对util.py进行编译成字节码,生成util.pyc,然后对字节码解释执行。如果想生成test.pyc,我们可以使用Python内置模块py_compile来编译。加载模块时,如果同时存在.py和.pyc,Python会尝试使用.pyc,如果.pyc的编译时间早于.py的修改时间,则重新编译.py并更新.pyc。

2.pyInstaller

    想要运行python程序(.py),必须安装python环境,因为python程序(.py)需要借助python解释器才能正确执行。如果我们将.py和python解释器放到同一个程序中,那么岂不是就不需要外部的python解释器?python程序(.py)就能像exe程序一样独立运行了?

    事实上pyinstaller就是这么做的,它做的更彻底,它将.py直接变为了.exe或.elf。pyInstaller把python解释器和py脚本打包成一个可执行的文件,虽然降低了运行效率,但拓宽了程序的应用场景。

    打包的时候,pyInstaller输入你指定的的脚本,首先分析脚本所依赖的其他脚本,然后去查找,复制,把所有相关的脚本收集起来,包括Python解释器,然后把这些文件打包进一个可执行文件里面。

    pyInstaller打包的可执行程序核心是一个bootloader,执行的时候,会在临时文件夹下面创建一个_MEIXXXXX的文件夹,然后 bootloader 会把 python 脚本中用到的一些文件解压扔进去,大部分是库文件(dll或so)。接下来就是执行 python 脚本了,当程序结束之后会删除这个文件夹。

3、py to exe

首先安装pyinstaller模块:

3137c1cdb1718ada11d9d3a055054211.png

pyinstaller基本用法,常用的可选参数如下:

--onefile 将结果打包成一个可执行文件
--onedir 将所有结果打包到一个文件夹中,该文件夹包括一个可执行文件和可执行文件执行时需要的依赖文件(默认)
--paths=DIR 设置导入路径
--distpath=DIR 设置将打包的结果文件放置的路径
--specpath=DIR 设置将spec文件放置的路径
--windowed 使用windows子系统执行,不会打开命令行(只对windows有效)
--nowindowed 使用控制台子系统执行(默认)(只对windows有效)
--icon= 将file.ico添加为可执行文件的资源(只对windows有效)

接下来,用一个实例进行演示。

①.py程序非常简单,就是打印"helloworld":

9ca4589d249fb407cd3360be8c5e731e.png

②使用pyinstaller打包

f05c08d07227923ca81f3a116f7d8aa9.png

③在当前文件下生成了build文件夹、dist文件夹和.spec文件。

bd81603f6ad319fe3d18ff360e405d64.png

.spec文件是配置规范文件,它说明了软件包怎样被配置,安装哪些文件,被安装到哪里,在安装该包之前或之后需要运行那些系统级别的活动(感兴趣的同学可以学习.spec的语法)。

build里存放将被打包的文件:

d0890cf7309a0957345267c7eb0a8f0e.png

exe文件就存放在dist文件夹下。

31725439f2d0669db9b4172e485d55ab.png

3d56906939e3c1923bf6b47588426ff0.png

4.py to exe的二进制特征

py生成的可执行程序核心是一个bootloader,这个bootloader具有如下核心代码:

deff52dd145e36175a237f501b2bfca2.png

81302783e98b83ac7adefc49876f4f57.png

字符串”_MEIPASS2”是pyinstaller使用的库,而pkg类型是安装文件类型。

我们也可以直接从strings中判断,可以发现py生成的可执行程序中含有大量”Py”开头的字符串:

815312cd0487a9255a48551ba9ac443e.png

5.exe to python

    python是解释型语言,故python编译打包成的可执行文件很容易被反编译,而像C,C++这样的编译型语言得到的可执行文件,则较难被反编译。

    反编译pyinstaller 产生的可执行文件有很多种方式,大体上可以分为两个步骤,一是由可执行文件获取pyc(pyo)文件,二是由pyc(pyo)文件得到py文件。

    反编译python生成的exe需要用到pyinstaller库里的archive_viewer.py脚本。archive_viewer.py一共有四个可用命令:

    U: go Up one level
    O : open embedded archive name
    X : extract name
    Q: quit

014b28f44e0574e236a1ca8719ef9c4e.png

archive_viewer.py对可执行程序进行解包分析,这里涉及到了好几个类型的文件,简单说明一下:

    py是源文件,

    pyc是源文件编译后的文件

    pyo是源文件优化编译后的文件

    pyz是一个压缩包,包含程序运行需要的所有依赖

    pyd是其他语言写的python库

    我们需要关注的是”helloworld”和”PYZ-00.pyz”这两个文件。一般来说*.pyz,其中包含主程序引用到的所有库,可以提取.pyz文件然后继续使用archive_viewer.py解包分析;另一个是主程序对应的文件名的文件,其中会包含主程序。

    使用x命令提取主程序,另存为helloworld.pyc:

d4ff696f947abd5a0e7dfd95775cc8e0.png

b7ea4d7d6610a6a50a524790043466aa.png

在helloworld.pyc文件头,补充8个字节:

eced177f0ff871615ade6159a8b1e025.png

    需要补充8个字节是因为pyinstaller编译成pyc时,会把pyc的magic value去掉。magic value一共8个字节,前四个对应于编译时所用python的版本,后四个对应于编译时间,比如python2.7 的03 f3 0d 0a 01 23 45 67,python3.4 的ee 0c 0d 0a 01 23 45 67。

    最后使用easy python decompiler从pyc(pyo)文件得到py文件,直接将pyc文件拖拽进程序:

356fe4db452064bfd7cd386e74ebcbea.png

生成.pyc_dis文件,里面就是最初我们写的python语句:

22e98ec0a5bedb6af73b9972f1dccbdf.png

参考资料

https://pyinstaller.readthedocs.io/en/stable/operating-mode.html

https://ctf-wiki.github.io/ctf-wiki/misc/other/pyc/

https://pyinstaller.readthedocs.io/en/stable/operating-mode.html#

https://lightless.me/archives/get-python-code-from-pyinstaller.html

不知不觉本周又要过去了

大家可以趁着周末好好消化一下

本系列文章的下一章将在下一周推送哦!

时刻关注我们

第一时间了解干货动态!

8d62b57c6ce6b0ee27f05d260eabb25f.png

下方查看 历史文章云众可信征稿进行时
原创干货 | 【恶意代码分析技巧】01- 介绍
原创干货 | 反射XSS和CORS漏洞的组合拳引发的血案

6581cbfa35b8d8ffa809fb7d0d71c7b6.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值