Python decompiles executable files packaged by Pyinstaller

Background : Recently, I am helping a friend to write a script similar to grabbing tickets. My friend has several scripts, but the effect is not ideal. He wants me to help. Because this requires a detailed understanding of the interface, some events have no conditions to capture packets. Then I moved my mind to a few scripts that my friend already had. First of all, small reptile software like this are almost inseparable, and they are all written in python. Then, when one of the software with better performance was packaged, even the application icon was not changed. The big Python Logo, refer to the article on the Internet. It was decompiled, the source code was obtained, and then modified on the basis of other people's code, which greatly reduced the difficulty of development.
Reference article: Talk about Pyinstaller compilation and decompilation, how to protect your code
First, simply write a piece of Python code. To output even numbers from 0-49, I know that the range can be realized by step size, but it is not too simple to add a judgment statement.

# 这是一段极为简单的测试代码
def foo():
	for i in range(50):
		if not i%2:
			print(i)

if __name__ == '__main__':
	foo()

Code running results

PS Python反编译测试> python .\main.py
0
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
44
46
48
PS Python反编译测试>

This time, the new environment created by conda is used for convenience, and there are no redundant packages. Install pyinstaller

pip install pyinstaller

Use pyinstaller for packaging

(blogTest) PS C:\Users\lkt\Desktop\Python反编译测试> pyinstaller.exe -F .\main.py
674 INFO: PyInstaller: 5.2
674 INFO: Python: 3.8.13 (conda)
690 INFO: Platform: Windows-10-10.0.22000-SP0
692 INFO: wrote C:\Users\lkt\Desktop\Python反编译测试\main.spec
695 INFO: UPX is not available.
705 INFO: Extending PYTHONPATH with paths
['C:\\Users\\lkt\\Desktop\\Python反编译测试']
1101 INFO: checking Analysis
1102 INFO: Building Analysis because Analysis-00.toc is non existent
1102 INFO: Initializing module dependency graph...
1104 INFO: Caching module graph hooks...
1136 INFO: Analyzing base_library.zip ...
5874 INFO: Processing pre-find module path hook distutils from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks\\pre_find_module_path\\hook-distutils.py'.
5875 INFO: distutils: retargeting to non-venv dir 'C:\\ide\\anaconda3\\envs\\blogTest\\lib'
10915 INFO: Caching module dependency graph...
11135 INFO: running Analysis Analysis-00.toc
11159 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
  required by C:\ide\anaconda3\envs\blogTest\python.exe
12028 INFO: Analyzing C:\Users\lkt\Desktop\Python反编译测试\main.py
12031 INFO: Processing module hooks...
12033 INFO: Loading module hook 'hook-difflib.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12035 INFO: Loading module hook 'hook-distutils.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12036 INFO: Loading module hook 'hook-distutils.util.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12038 INFO: Loading module hook 'hook-encodings.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12552 INFO: Loading module hook 'hook-heapq.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12555 INFO: Loading module hook 'hook-lib2to3.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12587 INFO: Loading module hook 'hook-multiprocessing.util.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12589 INFO: Loading module hook 'hook-pickle.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12592 INFO: Loading module hook 'hook-platform.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12594 INFO: Loading module hook 'hook-sysconfig.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12597 INFO: Loading module hook 'hook-xml.etree.cElementTree.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12598 INFO: Loading module hook 'hook-xml.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12718 INFO: Loading module hook 'hook-_tkinter.py' from 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks'...
12952 INFO: checking Tree
12952 INFO: Building Tree because Tree-00.toc is non existent
12952 INFO: Building Tree Tree-00.toc
13013 INFO: checking Tree
13013 INFO: Building Tree because Tree-01.toc is non existent
13014 INFO: Building Tree Tree-01.toc
13107 INFO: checking Tree
13108 INFO: Building Tree because Tree-02.toc is non existent
13108 INFO: Building Tree Tree-02.toc
13147 INFO: Looking for ctypes DLLs
13163 INFO: Analyzing run-time hooks ...
13166 INFO: Including run-time hook 'C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\hooks\\rthooks\\pyi_rth_subprocess.py'
13171 INFO: Looking for dynamic libraries
14067 INFO: Looking for eggs
14068 INFO: Using Python library C:\ide\anaconda3\envs\blogTest\python38.dll
14068 INFO: Found binding redirects:
[]
14072 INFO: Warnings written to C:\Users\lkt\Desktop\Python反编译测试\build\main\warn-main.txt
14113 INFO: Graph cross-reference written to C:\Users\lkt\Desktop\Python反编译测试\build\main\xref-main.html
14130 INFO: checking PYZ
14130 INFO: Building PYZ because PYZ-00.toc is non existent
14131 INFO: Building PYZ (ZlibArchive) C:\Users\lkt\Desktop\Python反编译测试\build\main\PYZ-00.pyz
14419 INFO: Building PYZ (ZlibArchive) C:\Users\lkt\Desktop\Python反编译测试\build\main\PYZ-00.pyz completed successfully.
14434 INFO: checking PKG
14434 INFO: Building PKG because PKG-00.toc is non existent
14435 INFO: Building PKG (CArchive) main.pkg
16921 INFO: Building PKG (CArchive) main.pkg completed successfully.
16924 INFO: Bootloader C:\ide\anaconda3\envs\blogTest\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
16924 INFO: checking EXE
16925 INFO: Building EXE because EXE-00.toc is non existent
16925 INFO: Building EXE from EXE-00.toc
16925 INFO: Copying bootloader EXE to C:\Users\lkt\Desktop\Python反编译测试\dist\main.exe.notanexecutable
17084 INFO: Copying icon to EXE
17091 INFO: Copying icons from ['C:\\ide\\anaconda3\\envs\\blogTest\\lib\\site-packages\\PyInstaller\\bootloader\\images\\icon-console.ico']
17157 INFO: Writing RT_GROUP_ICON 0 resource with 104 bytes
17158 INFO: Writing RT_ICON 1 resource with 3752 bytes
17158 INFO: Writing RT_ICON 2 resource with 2216 bytes
17158 INFO: Writing RT_ICON 3 resource with 1384 bytes
17159 INFO: Writing RT_ICON 4 resource with 37019 bytes
17159 INFO: Writing RT_ICON 5 resource with 9640 bytes
17159 INFO: Writing RT_ICON 6 resource with 4264 bytes
17159 INFO: Writing RT_ICON 7 resource with 1128 bytes
17164 INFO: Copying 0 resources to EXE
17164 INFO: Embedding manifest in EXE
17165 INFO: Updating manifest in C:\Users\lkt\Desktop\Python反编译测试\dist\main.exe.notanexecutable
17231 INFO: Updating resource type 24 name 1 language 0
17237 INFO: Appending PKG archive to EXE
17248 INFO: Fixing EXE headers
18957 INFO: Building EXE from EXE-00.toc completed successfully.

For example, the form of single-file packaging is used. The packaged file is in the dist directory, and the executable file is run.

(blogTest) PS C:\Users\lkt\Desktop\Python反编译测试> cd .\dist\
(blogTest) PS C:\Users\lkt\Desktop\Python反编译测试\dist> .\main.exe
0
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
32
34
36
38
40
42
44
46
48
(blogTest) PS C:\Users\lkt\Desktop\Python反编译测试\dist>

After running successfully, the executable is decompiled next. To decompile, I use the api packaged by this library
https://github.com/countercept/python-exe-unpacker Of course, there is another recommended in the Zhihu link, which I have not used. Maybe it will be better to use. After all, this library has been around for some years, and I encountered some problems with decompiled codes during use (the logic of if else and related indentation are wrong, I changed it back step by step through debug )

clone the warehouse

git clone [email protected]:countercept/python-exe-unpacker.git

Enter the warehouse folder, download the corresponding dependencies, there will be some errors, you can not care

pip install -r .\requirements.txt

Then decompile the executable

(blogTest) PS C:\Users\lkt\Desktop\Python反编译测试\python-exe-unpacker> python .\pyinstxtractor.py ..\dist\main.exe
.\pyinstxtractor.py:95: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
[*] Processing ..\dist\main.exe
[*] Pyinstaller version: 2.1+
[*] Python version: 308
[*] Length of package: 5714476 bytes
[*] Found 58 files in CArchive
[*] Beginning extraction...please standby
[*] Found 78 files in PYZ archive
[*] Successfully extracted pyinstaller archive: ..\dist\main.exe

You can now use a python decompiler on the pyc files within the extracted directory

In this way, the main.exe_extracted decompiled file is obtained.
insert image description here
It should be noted that the one in my frame is the code file. Of course, if the project is relatively large, there will be others, so pay attention to it yourself. In fact, this file is a pyc file. The pyc file can be easily converted into a py file, but the trouble is that it lacks a magic number. The solution is that the struct file has a magic number, and the user can edit the binary Open main and struct of the file, copy and paste the first line of struct to main
insert image description here
insert image description here
insert image description here
Rename main to main.pyc, use the command

(blogTest) PS C:\Users\lkt\Desktop\Python反编译测试\python-exe-unpacker> uncompyle6 -o main.py .\main.exe_extracted\main.pyc
.\main.exe_extracted\main.pyc --
# Successfully decompiled file
(blogTest) PS C:\Users\lkt\Desktop\Python反编译测试\python-exe-unpacker>

decompiled result

# uncompyle6 version 3.8.0
# Python bytecode 3.8.0 (3413)
# Decompiled from: Python 3.8.13 (default, Mar 28 2022, 06:59:08) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: main.py
# Compiled at: 2022-03-16 20:22:54
# Size of source mod 2**32: 257 bytes


def foo():
    for i in range(50):
        if not i % 2:
            print(i)


if __name__ == '__main__':
    foo()

The comments are gone, and only the comments of the entry file will disappear when I actually use it. The other files are still there.

The script I decompiled can be modified at will. The script itself is set with a key that will expire after a certain period of time. After getting the source code, I got the encryption key of the key. I can generate the key at will, and the other can also Modify the program and change it to your own key, just like unlocking it.

Finally, if you want to encrypt and package, you can add –key to specify the key when pyinstaller packages, but it is understood that it can still be decompiled. Or use Cython to package, in general, it is more difficult to decompile, otherwise the program written by myself will be in vain~

==================================================== ======
Supplement: Later, it was found that this decompilation library can directly add magic numbers, and it will be more useful if you don’t need to add them yourself.
https://github.com/extremecoders-re/pyinstxttractor

Guess you like

Origin blog.csdn.net/rglkt/article/details/125733343