首页
社区
课程
招聘
[原创]Python逆向——Pyinstaller逆向
发表于: 2022-1-23 02:04 16948

[原创]Python逆向——Pyinstaller逆向

2022-1-23 02:04
16948

最常见的打包库,打包后可以通过Extractor工具或者pyinstaller内置的achieve_viewer.py直接解包,使用—key参数可以使其具有一定程度的反逆向能力,但由于其本身是个开源的库,也能找到其加密的原理,所以不是很难逆向

得到可执行文件,使用Extractor工具进行解包

将会得到一个文件夹,里面包含主程序所引用的所有库以及代码的pyc文件

pyinstaller有一个奇怪的地方,它会把主函数pyc文件的文件头进行更改,这里我们就可以用到上面那个文件夹里面一定会有的struct.pyc文件,这个文件的文件头一般是不会更改的,将这个文件的文件头进行复制然后更改主函数pyc文件头就可以了。

由于Pyinstaller是个开源的包,这也给我们逆向提供了便利

在官方给出的用法中,有给出-key这个参数,说是可以将文件pyc进行一定的压缩加密,以防止被逆向

Pyinstaller这个库本身的打包原理大概就是先将py编译成pyc,然后部分压缩成pyz,程序再通过对pyc和pyz的调用

这个是pyinstaller的打包过程语句

可以看到对ctypes的调用,pyz的生成等等

生成之后的build文件夹如下

那个Base_Library.zip里面都是库文件的pyc

然后我们在pyinstaller库中找到archieve这么一个文件夹,里面有一个pyz_crypto.py文件,是对pyz文件的加密代码

可以看出,他是使用的tinyAES库对pyc文件进行块加密,块大小为16byte

这个方法的灵感来源于github上大佬extremecoders-re

链接:https://github.com/extremecoders-re/pyinstxtractor/wiki/Frequently-Asked-Questions

因为我们已经根据源码知道了pyz加密方式和加密算法,所以根据解包后pyc文件提供的一系列参数,很容易就能编写出对应的解密脚本。

首先用pyinstxtractor工具对文件进行解包(需软件对应相同的python大版本,否则无法得到pyz文件),得到未被加密的部分pyc文件和加密的pyz文件,其中之一就有archive.pyc,我们可以通过archive.pyc文件得到加密过程,crypto_key文件得到具体key参数

然后根据主函数pyc反编译内容我们又找到了需要找的包

这个时候就只需要按照加密的方式进行解密就可以了,加密部分为Cipher(脚本来源于archive.pyc的反编译)

解密脚本

这个方法是跟某大师傅学的,先是之前就在翻找源码的时候看到了pyinstaller自己提供了内置的archieve_view.py这个东东,而且能用来解包,也曾经尝试过用一下,具体如图:

我们将baby.exe放进这里然后用内置文件解包试试

然后我们就能看到神奇的一幕了,exe文件内容被展示出来了

看一下archieve_view.py的源码,其实就能理解了

这里只放一下操作相关的代码

总共三个操作

那我们找到系统主函数的位置(从上文得知在pyz中)

找到了,直接解压是行不通的,有密码

这里直接解压python报错提示头文件检查错误

当然了,因为文件被AES加密了

所以得从解AES入手,恰好我们有加密函数,甚至还有其解密函数

那就好办了

回头再看一下archieve_view.py的源码,找到get_data函数

很明显,里面调用的decompass就是解包的过程,里面调用的是read方法,如果我们read之后再来个decrypt,再用archieve_view.py不就跑出来了吗

将上面那个Cipher类加入archieve_view.py文件中

然后将get_data函数下的zlib.decompress(arch.lib.read(length))改为zlib.decompress(cipher.decrypt(arch.lib.read(length))),使其读取完直接解密再decompass,不就不会头文件错误了嘛

(别忘了将key导入,还有blocksize的宏定义)

运行,正常导出

最后,插入16字节的头文件,反编译就出来源码了

python pyinstxtractor.py xx.exe
python pyinstxtractor.py xx.exe
 
 
 
 
 
➜ pyinstaller.exe -F test.py
150 INFO: PyInstaller: 4.3
150 INFO: Python: 3.8.9
150 INFO: Platform: Windows-10-10.0.22000-SP0
152 INFO: wrote H:\My_CTF_Tools\Python_Reverse\pyinstaller\test.spec
158 INFO: UPX is not available.
205 INFO: Extending PYTHONPATH with paths
['H:\\My_CTF_Tools\\Python_Reverse\\pyinstaller',
 'H:\\My_CTF_Tools\\Python_Reverse\\pyinstaller']
300 INFO: checking Analysis
300 INFO: Building Analysis because Analysis-00.toc is non existent
300 INFO: Initializing module dependency graph...
304 INFO: Caching module graph hooks...
314 WARNING: Several hooks defined for module 'win32ctypes.core'. Please take care they do not conflict.
335 INFO: Analyzing base_library.zip ...
2867 INFO: Processing pre-find module path hook distutils from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path\\hook-distutils.py'.
2869 INFO: distutils: retargeting to non-venv dir 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib'
6284 INFO: Caching module dependency graph...
6460 INFO: running Analysis Analysis-00.toc
6464 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
  required by c:\users\lenovo\appdata\local\programs\python\python38\python.exe
7015 INFO: Analyzing H:\My_CTF_Tools\Python_Reverse\pyinstaller\test.py
7022 INFO: Processing module hooks...
7022 INFO: Loading module hook 'hook-difflib.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7025 INFO: Loading module hook 'hook-distutils.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7027 INFO: Loading module hook 'hook-distutils.util.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7028 INFO: Loading module hook 'hook-encodings.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7113 INFO: Loading module hook 'hook-heapq.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7115 INFO: Loading module hook 'hook-lib2to3.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7189 INFO: Loading module hook 'hook-multiprocessing.util.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7191 INFO: Loading module hook 'hook-pickle.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7193 INFO: Loading module hook 'hook-sysconfig.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7195 INFO: Loading module hook 'hook-xml.etree.cElementTree.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7197 INFO: Loading module hook 'hook-xml.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7275 INFO: Loading module hook 'hook-_tkinter.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7564 INFO: checking Tree
7574 INFO: Building Tree because Tree-00.toc is non existent
7576 INFO: Building Tree Tree-00.toc
7747 INFO: checking Tree
7747 INFO: Building Tree because Tree-01.toc is non existent
7747 INFO: Building Tree Tree-01.toc
7857 INFO: checking Tree
7857 INFO: Building Tree because Tree-02.toc is non existent
7857 INFO: Building Tree Tree-02.toc
7875 INFO: Looking for ctypes DLLs
7895 INFO: Analyzing run-time hooks ...
7896 INFO: Including run-time hook 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py'
7902 INFO: Looking for dynamic libraries
8061 INFO: Looking for eggs
8062 INFO: Using Python library c:\users\lenovo\appdata\local\programs\python\python38\python38.dll
8062 INFO: Found binding redirects:
[]
8066 INFO: Warnings written to H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\warn-test.txt
8099 INFO: Graph cross-reference written to H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\xref-test.html
8114 INFO: checking PYZ
8115 INFO: Building PYZ because PYZ-00.toc is non existent
8115 INFO: Building PYZ (ZlibArchive) H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\PYZ-00.pyz
8658 INFO: Building PYZ (ZlibArchive) H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\PYZ-00.pyz completed successfully.
8673 INFO: checking PKG
8673 INFO: Building PKG because PKG-00.toc is non existent
8673 INFO: Building PKG (CArchive) PKG-00.pkg
10402 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
10406 INFO: Bootloader c:\users\lenovo\appdata\local\programs\python\python38\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
10407 INFO: checking EXE
10407 INFO: Building EXE because EXE-00.toc is non existent
10407 INFO: Building EXE from EXE-00.toc
10473 INFO: Copying icons from ['c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\bootloader\\images\\icon-console.ico']
10522 INFO: Writing RT_GROUP_ICON 0 resource with 104 bytes
10522 INFO: Writing RT_ICON 1 resource with 3752 bytes
10522 INFO: Writing RT_ICON 2 resource with 2216 bytes
10523 INFO: Writing RT_ICON 3 resource with 1384 bytes
10523 INFO: Writing RT_ICON 4 resource with 37019 bytes
10524 INFO: Writing RT_ICON 5 resource with 9640 bytes
10524 INFO: Writing RT_ICON 6 resource with 4264 bytes
10524 INFO: Writing RT_ICON 7 resource with 1128 bytes
10531 INFO: Updating manifest in H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\run.exe.7_01cl0t
10592 INFO: Updating resource type 24 name 1 language 0
10599 INFO: Appending archive to EXE H:\My_CTF_Tools\Python_Reverse\pyinstaller\dist\test.exe
12711 INFO: Building EXE from EXE-00.toc completed successfully.
➜ pyinstaller.exe -F test.py
150 INFO: PyInstaller: 4.3
150 INFO: Python: 3.8.9
150 INFO: Platform: Windows-10-10.0.22000-SP0
152 INFO: wrote H:\My_CTF_Tools\Python_Reverse\pyinstaller\test.spec
158 INFO: UPX is not available.
205 INFO: Extending PYTHONPATH with paths
['H:\\My_CTF_Tools\\Python_Reverse\\pyinstaller',
 'H:\\My_CTF_Tools\\Python_Reverse\\pyinstaller']
300 INFO: checking Analysis
300 INFO: Building Analysis because Analysis-00.toc is non existent
300 INFO: Initializing module dependency graph...
304 INFO: Caching module graph hooks...
314 WARNING: Several hooks defined for module 'win32ctypes.core'. Please take care they do not conflict.
335 INFO: Analyzing base_library.zip ...
2867 INFO: Processing pre-find module path hook distutils from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path\\hook-distutils.py'.
2869 INFO: distutils: retargeting to non-venv dir 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib'
6284 INFO: Caching module dependency graph...
6460 INFO: running Analysis Analysis-00.toc
6464 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
  required by c:\users\lenovo\appdata\local\programs\python\python38\python.exe
7015 INFO: Analyzing H:\My_CTF_Tools\Python_Reverse\pyinstaller\test.py
7022 INFO: Processing module hooks...
7022 INFO: Loading module hook 'hook-difflib.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7025 INFO: Loading module hook 'hook-distutils.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7027 INFO: Loading module hook 'hook-distutils.util.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7028 INFO: Loading module hook 'hook-encodings.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7113 INFO: Loading module hook 'hook-heapq.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7115 INFO: Loading module hook 'hook-lib2to3.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7189 INFO: Loading module hook 'hook-multiprocessing.util.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7191 INFO: Loading module hook 'hook-pickle.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7193 INFO: Loading module hook 'hook-sysconfig.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7195 INFO: Loading module hook 'hook-xml.etree.cElementTree.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7197 INFO: Loading module hook 'hook-xml.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7275 INFO: Loading module hook 'hook-_tkinter.py' from 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks'...
7564 INFO: checking Tree
7574 INFO: Building Tree because Tree-00.toc is non existent
7576 INFO: Building Tree Tree-00.toc
7747 INFO: checking Tree
7747 INFO: Building Tree because Tree-01.toc is non existent
7747 INFO: Building Tree Tree-01.toc
7857 INFO: checking Tree
7857 INFO: Building Tree because Tree-02.toc is non existent
7857 INFO: Building Tree Tree-02.toc
7875 INFO: Looking for ctypes DLLs
7895 INFO: Analyzing run-time hooks ...
7896 INFO: Including run-time hook 'c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_multiprocessing.py'
7902 INFO: Looking for dynamic libraries
8061 INFO: Looking for eggs
8062 INFO: Using Python library c:\users\lenovo\appdata\local\programs\python\python38\python38.dll
8062 INFO: Found binding redirects:
[]
8066 INFO: Warnings written to H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\warn-test.txt
8099 INFO: Graph cross-reference written to H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\xref-test.html
8114 INFO: checking PYZ
8115 INFO: Building PYZ because PYZ-00.toc is non existent
8115 INFO: Building PYZ (ZlibArchive) H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\PYZ-00.pyz
8658 INFO: Building PYZ (ZlibArchive) H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\PYZ-00.pyz completed successfully.
8673 INFO: checking PKG
8673 INFO: Building PKG because PKG-00.toc is non existent
8673 INFO: Building PKG (CArchive) PKG-00.pkg
10402 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
10406 INFO: Bootloader c:\users\lenovo\appdata\local\programs\python\python38\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
10407 INFO: checking EXE
10407 INFO: Building EXE because EXE-00.toc is non existent
10407 INFO: Building EXE from EXE-00.toc
10473 INFO: Copying icons from ['c:\\users\\lenovo\\appdata\\local\\programs\\python\\python38\\lib\\site-packages\\PyInstaller\\bootloader\\images\\icon-console.ico']
10522 INFO: Writing RT_GROUP_ICON 0 resource with 104 bytes
10522 INFO: Writing RT_ICON 1 resource with 3752 bytes
10522 INFO: Writing RT_ICON 2 resource with 2216 bytes
10523 INFO: Writing RT_ICON 3 resource with 1384 bytes
10523 INFO: Writing RT_ICON 4 resource with 37019 bytes
10524 INFO: Writing RT_ICON 5 resource with 9640 bytes
10524 INFO: Writing RT_ICON 6 resource with 4264 bytes
10524 INFO: Writing RT_ICON 7 resource with 1128 bytes
10531 INFO: Updating manifest in H:\My_CTF_Tools\Python_Reverse\pyinstaller\build\test\run.exe.7_01cl0t
10592 INFO: Updating resource type 24 name 1 language 0
10599 INFO: Appending archive to EXE H:\My_CTF_Tools\Python_Reverse\pyinstaller\dist\test.exe
12711 INFO: Building EXE from EXE-00.toc completed successfully.
 
 
 
 
#-----------------------------------------------------------------------------
# Copyright (c) 2005-2021, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License (version 2
# or later) with exception for distributing the bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------
 
import os
 
BLOCK_SIZE = 16
 
class PyiBlockCipher(object):
    """
    This class is used only to encrypt Python modules.
    """
    def __init__(self, key=None):
        assert type(key) is str
        if len(key) > BLOCK_SIZE:
            self.key = key[0:BLOCK_SIZE]
        else:
            self.key = key.zfill(BLOCK_SIZE)
        assert len(self.key) == BLOCK_SIZE
 
        import tinyaes
        self._aesmod = tinyaes
 
    def encrypt(self, data):
        iv = os.urandom(BLOCK_SIZE)
        return iv + self.__create_cipher(iv).CTR_xcrypt_buffer(data)
 
    def __create_cipher(self, iv):
        # The 'AES' class is stateful, this factory method is used to
        # re-initialize the block cipher class with each call to xcrypt().
        return self._aesmod.AES(self.key.encode(), iv)
#-----------------------------------------------------------------------------
# Copyright (c) 2005-2021, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License (version 2
# or later) with exception for distributing the bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#
# SPDX-License-Identifier: (GPL-2.0-or-later WITH Bootloader-exception)
#-----------------------------------------------------------------------------
 
import os
 
BLOCK_SIZE = 16
 
class PyiBlockCipher(object):
    """
    This class is used only to encrypt Python modules.
    """
    def __init__(self, key=None):
        assert type(key) is str
        if len(key) > BLOCK_SIZE:
            self.key = key[0:BLOCK_SIZE]
        else:
            self.key = key.zfill(BLOCK_SIZE)
        assert len(self.key) == BLOCK_SIZE
 
        import tinyaes
        self._aesmod = tinyaes
 
    def encrypt(self, data):
        iv = os.urandom(BLOCK_SIZE)
        return iv + self.__create_cipher(iv).CTR_xcrypt_buffer(data)
 
    def __create_cipher(self, iv):
        # The 'AES' class is stateful, this factory method is used to
        # re-initialize the block cipher class with each call to xcrypt().
        return self._aesmod.AES(self.key.encode(), iv)

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 9
支持
分享
最新回复 (2)
雪    币: 3416
活跃值: (2104)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
感谢大神讲解原理
2022-1-23 03:18
0
雪    币: 886
活跃值: (2310)
能力值: ( LV4,RANK:52 )
在线值:
发帖
回帖
粉丝
3
是东方众师傅
2022-8-4 18:09
0
游客
登录 | 注册 方可回帖
返回
//