Decompile compiled python binaries (exe, elf) - Retreive from .pyc

htARTE (HackTricks AWS Red Team Expert)에서 **제로부터 영웅이 되는 AWS 해킹 배우기**

HackTricks를 지원하는 다른 방법:

버그 바운티 팁: 해커들에 의해 만들어진 프리미엄 버그 바운티 플랫폼Intigriti에 가입하세요! 오늘 https://go.intigriti.com/hacktricks에서 참여하여 최대 $100,000의 바운티를 벌어보세요!

컴파일된 이진 파일에서 .pyc로

ELF로 컴파일된 이진 파일에서는 다음을 사용하여 .pyc를 얻을 수 있습니다:

pyi-archive_viewer <binary>
# The list of python modules will be given here:
[(0, 230, 311, 1, 'm', 'struct'),
(230, 1061, 1792, 1, 'm', 'pyimod01_os_path'),
(1291, 4071, 8907, 1, 'm', 'pyimod02_archive'),
(5362, 5609, 13152, 1, 'm', 'pyimod03_importers'),
(10971, 1473, 3468, 1, 'm', 'pyimod04_ctypes'),
(12444, 816, 1372, 1, 's', 'pyiboot01_bootstrap'),
(13260, 696, 1053, 1, 's', 'pyi_rth_pkgutil'),
(13956, 1134, 2075, 1, 's', 'pyi_rth_multiprocessing'),
(15090, 445, 672, 1, 's', 'pyi_rth_inspect'),
(15535, 2514, 4421, 1, 's', 'binary_name'),
...

? X binary_name
to filename? /tmp/binary.pyc

파이썬 exe 이진 파일에서는 다음을 실행하여 .pyc 파일을 얻을 수 있습니다:

python pyinstxtractor.py executable.exe

.pyc에서 python 코드로

.pyc 데이터("컴파일된" 파이썬)에서는 원본 파이썬 코드추출하기 시작해야합니다:

uncompyle6 binary.pyc  > decompiled.py

확실하게 이진 파일이 ".pyc" 확장자를 가지고 있는지 확인하십시오 (그렇지 않으면, uncompyle6가 작동하지 않을 것입니다)

uncompyle6를 실행하는 동안 다음과 같은 오류를 발견할 수 있습니다:

오류: 알 수 없는 매직 넘버 227

/kali/.local/bin/uncompyle6 /tmp/binary.pyc
Unknown magic number 227 in /tmp/binary.pyc

이를 해결하려면 생성된 파일의 시작 부분에 올바른 매직 넘버를 추가해야합니다.

매직 넘버는 파이썬 버전에 따라 다릅니다. 파이썬 3.8의 매직 넘버를 얻으려면 파이썬 3.8 터미널을 열고 다음을 실행해야합니다:

>> import imp
>> imp.get_magic().hex()
'550d0d0a'

마법 숫자는 이 경우 파이썬 3.8의 **0x550d0d0a**입니다. 그런 다음, 이 오류를 수정하려면 .pyc 파일처음에 다음 바이트를 추가해야 합니다: 0x0d550a0d000000000000000000000000

마법 헤더를 추가한 후에는 오류가 수정될 것입니다.

다음은 올바르게 추가된 .pyc python3.8 마법 헤더의 모습입니다:

hexdump 'binary.pyc' | head
0000000 0d55 0a0d 0000 0000 0000 0000 0000 0000
0000010 00e3 0000 0000 0000 0000 0000 0000 0000
0000020 0700 0000 4000 0000 7300 0132 0000 0064
0000030 0164 006c 005a 0064 0164 016c 015a 0064

오류: 일반 오류의 디컴파일

class 'AssertionError'>; co_code should be one of the types (<class 'str'>, <class 'bytes'>, <class 'list'>, <class 'tuple'>); is type <class 'NoneType'>와 같은 다른 오류가 발생할 수 있습니다.

이는 아마도 매직 넘버를 올바르게 추가하지 않았거나 올바른 매직 넘버를 사용하지 않았다는 것을 의미합니다. 따라서 올바른 것을 사용했는지 확인하십시오 (또는 새로운 것을 시도하십시오).

이전 오류 문서를 확인하십시오.

자동 도구

python-exe-unpacker 도구는 py2exe 및 pyinstaller로 작성된 실행 파일을 언패킹하고 디컴파일하는 데 도움이 되도록 설계된 여러 커뮤니티에서 제공하는 도구의 조합으로 작동합니다. 이는 실행 파일이 Python 기반인지 식별하기 위한 YARA 규칙을 포함하고 생성 도구를 확인합니다.

ImportError: 파일 이름: 'unpacked/malware_3.exe/pycache/archive.cpython-35.pyc'이(가) 존재하지 않음

일반적으로 발생하는 문제는 unpy2exe 또는 pyinstxtractor를 사용하여 언패킹 프로세스 중에 발생하는 불완전한 Python 바이트 코드 파일로 인해, 이후 uncompyle6에서 Python 바이트 코드 버전 번호가 누락되어 인식되지 않는 것입니다. 이를 해결하기 위해 필요한 Python 바이트 코드 버전 번호를 추가하는 prepend 옵션이 추가되었으며, 이는 디컴파일 프로세스를 용이하게 합니다.

문제의 예시:

# Error when attempting to decompile without the prepend option
test@test: uncompyle6 unpacked/malware_3.exe/archive.py
Traceback (most recent call last):
...
ImportError: File name: 'unpacked/malware_3.exe/__pycache__/archive.cpython-35.pyc' doesn't exist
# Successful decompilation after using the prepend option
test@test:python python_exe_unpack.py -p unpacked/malware_3.exe/archive
[*] On Python 2.7
[+] Magic bytes are already appended.

# Successfully decompiled file
[+] Successfully decompiled.

Python 어셈블리 분석

이전 단계를 따라서 파이썬 "원본" 코드를 추출할 수 없었다면 어셈블리를 추출해 볼 수 있습니다(하지만 그렇게 구체적이지 않으므로 다시 원본 코드를 추출해 보세요). 여기에서 .pyc 바이너리를 분해하는 매우 간단한 코드를 찾았습니다(코드 흐름을 이해하는 데 행운을 빕니다). 만약 _.pyc_가 python2에서 생성된 것이라면, python2를 사용하세요:

>>> import dis
>>> import marshal
>>> import struct
>>> import imp
>>>
>>> with open('hello.pyc', 'r') as f:  # Read the binary file
...     magic = f.read(4)
...     timestamp = f.read(4)
...     code = f.read()
...
>>>
>>> # Unpack the structured content and un-marshal the code
>>> magic = struct.unpack('<H', magic[:2])
>>> timestamp = struct.unpack('<I', timestamp)
>>> code = marshal.loads(code)
>>> magic, timestamp, code
((62211,), (1425911959,), <code object <module> at 0x7fd54f90d5b0, file "hello.py", line 1>)
>>>
>>> # Verify if the magic number corresponds with the current python version
>>> struct.unpack('<H', imp.get_magic()[:2]) == magic
True
>>>
>>> # Disassemble the code object
>>> dis.disassemble(code)
1           0 LOAD_CONST               0 (<code object hello_world at 0x7f31b7240eb0, file "hello.py", line 1>)
3 MAKE_FUNCTION            0
6 STORE_NAME               0 (hello_world)
9 LOAD_CONST               1 (None)
12 RETURN_VALUE
>>>
>>> # Also disassemble that const being loaded (our function)
>>> dis.disassemble(code.co_consts[0])
2           0 LOAD_CONST               1 ('Hello  {0}')
3 LOAD_ATTR                0 (format)
6 LOAD_FAST                0 (name)
9 CALL_FUNCTION            1
12 PRINT_ITEM
13 PRINT_NEWLINE
14 LOAD_CONST               0 (None)
17 RETURN_VALUE

파이썬을 실행 파일로 변환하기

먼저, 페이로드가 py2exe 및 PyInstaller에서 컴파일될 수 있는 방법을 보여드리겠습니다.

py2exe를 사용하여 페이로드 생성하기:

  1. http://www.py2exe.org/에서 py2exe 패키지를 설치합니다.

  2. 페이로드를 생성하기 위해 (이 경우 hello.py로 이름을 지정할 것입니다), Figure 1에 있는 스크립트와 같은 스크립트를 사용합니다. 값이 1인 "bundle_files" 옵션은 Python 인터프리터를 포함한 모든 것을 하나의 exe로 번들링합니다.

  3. 스크립트가 준비되면 "python setup.py py2exe" 명령을 실행합니다. 이렇게 하면 Figure 2와 같이 실행 파일이 생성됩니다.

from distutils.core import setup
import py2exe, sys, os

sys.argv.append('py2exe')

setup(
options = {'py2exe': {'bundle_files': 1}},
#windows = [{'script': "hello.py"}],
console = [{'script': "hello.py"}],
zipfile = None,
)
C:\Users\test\Desktop\test>python setup.py py2exe
running py2exe
*** searching for required modules ***
*** parsing results ***
*** finding dlls needed ***
*** create binaries ***
*** byte compile python files ***
*** copy extensions ***
*** copy dlls ***
copying C:\Python27\lib\site-packages\py2exe\run.exe -> C:\Users\test\Desktop\test\dist\hello.exe
Adding python27.dll as resource to C:\Users\test\Desktop\test\dist\hello.exe

PyInstaller를 사용하여 페이로드를 생성하는 방법:

  1. pip를 사용하여 PyInstaller를 설치합니다 (pip install pyinstaller).

  2. 그 후에는 "pyinstaller --onefile hello.py" 명령을 실행합니다 ('hello.py'가 페이로드임을 상기해 주세요). 이 명령은 모든 것을 하나의 실행 파일로 번들링합니다.

C:\Users\test\Desktop\test>pyinstaller --onefile hello.py
108 INFO: PyInstaller: 3.3.1
108 INFO: Python: 2.7.14
108 INFO: Platform: Windows-10-10.0.16299
………………………………
5967 INFO: checking EXE
5967 INFO: Building EXE because out00-EXE.toc is non existent
5982 INFO: Building EXE from out00-EXE.toc
5982 INFO: Appending archive to EXE C:\Users\test\Desktop\test\dist\hello.exe
6325 INFO: Building EXE from out00-EXE.toc completed successfully.

참고 자료

버그 바운티 팁: Intigriti에 가입하여 해커들이 만든 프리미엄 버그 바운티 플랫폼에 참여하세요! https://go.intigriti.com/hacktricks에서 오늘 가입하고 최대 $100,000의 바운티를 받아보세요!

htARTE (HackTricks AWS Red Team Expert)로부터 AWS 해킹을 제로부터 전문가까지 배우세요 htARTE (HackTricks AWS Red Team Expert)!

HackTricks를 지원하는 다른 방법:

Last updated