티스토리 뷰

글 맨 밑에 요약이 있습니다. 긴 글 읽기 힘드신 분들은 요약 먼저 보세요

 

준비물

  • C++ 빌드 툴
  • Python (with pip)
  • HxD
  • 인터넷 연결

1. 준비물 설치

Python 언팩 스크립트: python-exe-unpacker

git clone https://github.com/countercept/python-exe-unpacker
cd python-exe-unpacker

python3 -m pip install -r requirements.txt
또는
pip3 install -r requirements.txt
또는 자신의 컴퓨터에 맞게 패키지 설치

C++ 빌드 오류 나면 리눅스나 WSL에서 시도해보세요. 전 WSL에서 작업했습니다.

2. 언패킹

python3 python_exe_unpack.py -i <언패킹 할 exe>

[*] On Python 3.6
[*] Processing tcas.exe
[*] Pyinstaller version: 2.1+
[*] This exe is packed using pyinstaller
[*] Unpacking the binary now
[*] Python version: 38
[*] Length of package: 7155088 bytes
[*] Found 35 files in CArchive
[*] Beginning extraction...please standby
[!] Warning: The script is running in a different python version than the one used to build the executable
    Run this script in Python38 to prevent extraction errors(if any) during unmarshalling
[*] Found 341 files in PYZ archive
[*] Successfully extracted pyinstaller exe.

바이너리의 파이썬 버전과 사용하는 파이썬 버전이 다르다면 저렇게 Warning이 뜹니다. 버전이 다르면 디컴파일도 제대로 안되므로 꼭! 바이너리에 맞는 파이썬 버전을 다운로드하여 주세요. 제 경우에는 Python 3.8을 사용하라네요.

2.1 만약 바이너리의 파이썬 버전이 3.7 이상일 경우

3.7 부터는 컴파일한 파일의 헤더 크기가 12바이트에서 16바이트로 늘어납니다. 이 부분은 현재 우리가 받은 스크립트에선 대응을 하지 못하기 때문에, 따로 수정해줘야 합니다.

 

출처: StackExchange: Decompiling Python Files: ValueError

 

Decompiling Python Files: ValueError

So I have this python file and I successfully unpacked its content inside of it we have our file.pyc I appended the magic bytes to it so it went from: E3 00 00 00 00 00 00 00 00 00 00 00 00 to

reverseengineering.stackexchange.com

pyinstxtractor.py의 321번 줄의 다음 코드를 찾아주세요:

with open(destName + '.pyc', 'wb') as pycFile:
    pycFile.write(pycHeader)      # Write pyc magic
    pycFile.write(b'\0' * 4)      # Write timestamp
    if self.pyver >= 33:
        pycFile.write(b'\0' * 4)  # Size parameter added in Python 3.3
    pycFile.write(data)

다음과 같이 수정해주세요:

with open(destName + '.pyc', 'wb') as pycFile:
    pycFile.write(pycHeader)      # Write pyc magic
    pycFile.write(b'\0' * 12)
    pycFile.write(data)

주의!! 들여 쓰기를 꼭 맞춰주세요!!

이렇게 수정하고 다시 언패킹 하시면 됩니다.

 

 

**3.28일 수정**

스크립트에서 저 부분의 코드가 이제 없습니다. 대신 3.7 버전 이상일 경우에는 매직 코드를 삽입할 때 00 00 00 00을 뒤에 추가해주세요.

3. 디컴파일

python3.8 python_exe_unpack.py -i <exe파일>
[*] On Python 3.8
[*] Processing tcas.exe
[*] Pyinstaller version: 2.1+
[*] This exe is packed using pyinstaller
[*] Unpacking the binary now
[*] Python version: 38
[*] Length of package: 7155088 bytes
[*] Found 35 files in CArchive
[*] Beginning extraction...please standby
[*] Found 341 files in PYZ archive
[*] Successfully extracted pyinstaller exe.

이렇게 성공적으로 아무 에러 없이 unpacked/<exe이름> 폴더 안에 언패킹이 되었습니다. 이제 메인 스크립트를 디컴파일해야겠죠?

주로 메인 스크립트는 우리가 원하는 파이썬 스크립트의 .py 확장자 없이 그냥 이름만 있는 파일입니다. 저의 경우는 run이었습니다.

열어보면 아래처럼 일부 문자열 빼고는 알아볼 수 없게 컴파일이 되어있습니다.

?                  @   s0  d dl Z d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl    m    Z     d dl
Z
dd?Zdd?Zda
ddname?r   ?run.py?get_path   s    r   c                 C   sf   t ??D ]X}z2|??}d|kr<d|  d?|???kr<|?? W q t jt jt jfk
r^   Y qX qd S )N_? )    ?psutil?process_iterr   ?join?cmdline?kill?NoSuchProcess?AccessDenied?ZombieProcess)?

컴파일된 파이썬 파일은 일반적으론 사람이 읽을 수 없습니다. 하지만 uncompyle6라는 패키지를 이용해 이것을 디컴파일 할 수 있습니다.

각자 바이너리 파이썬 버전에 맞는 python pip으로 uncompyle6을 설치해주세요.

 

 

 

이제 다 된 것 같지만 선 작업이 필요합니다. 메인 스크립트 파일에는 매직 넘버가 없어서 아래처럼 프로그램이 인식하지 못하고 디컴파일이 불가능하기 때문입니다.

> uncompyle6 unpacked/<exe파일>/run.pyc
Unknown magic number 227 in unpacked/<exe파일>/run.pyc

Q: 원래 파일 이름은 확장자가 없지 않나요? 저는 막 run 이라고만 뜨던데 왜 여기선 run.pyc인가요?

A: 파일 이름이 run.pyc인 이유는 uncompyle6는 파일 확장자가. pyc나. pyo로 끝나지 않으면 아예 작업을 수행하지 않습니다. pyc 확장자를 붙여서 스크립트를 복제해주세요.

 

매직 넘버를 추출하기 위해선 unpacked/exe이름/PYZ-00.pyz_extracted (사람마다 디렉터리 이름 다를 수 있음)에는 컴파일된 파이썬 모듈 파일들이 있습니다. 다행히도 이 모듈 파일들에는 매직 넘버가 없어지지 않고 잘 살아있습니다.

 

HxD로 컴파일된 아무 파이썬 모듈 파일을 두 개 가져와봤습니다. 맨 마지막 사진은 run.pyc 파일인데요. 보다시피 run.pyc 파일에는 다른 모듈에 있는 첫 한 줄이 없습니다. 저 처음 한줄이 매직 넘버입니다. 제 경우에는 55 0D 0D 0A 00 00 00 00 00 00 00 00 00 00 00 00인 거죠. 이 매직 넘버를 run.pyc의 맨 앞에 붙여줍니다.

3.6 이하 버전은 한 줄 (16바이트)가 아닌 12바이트입니다. (오프셋 00부터 0B까지)

다른 모듈처럼 헤더를 수정을 했습니다.

이렇게 수정하면 디컴파일이 잘 되는 걸 볼 수 있습니다.

> uncompyle6 unpacked-bak/<exe이름>/run.pyc
# uncompyle6 version 3.8.0
# Python bytecode 3.8.0 (3413)
# Decompiled from: Python 3.8.0 (default, Dec  9 2021, 17:53:27)
# [GCC 8.4.0]
# Embedded file name: run.py
import os, sys, pathlib, psutil, atexit, signal, argparse, requests, time
from datetime import datetime
import hashlib

def get_path(cur, name):
    return (cur / name).absolute()
.. 생략

이걸 파일로 저장하려면 -o 저장하려는 파일명 옵션을 주거나, 파이프라인으로 저장하시면 됩니다.

uncompyle6 unpacked-bak/<exe이름./run.pyc -o run.py
또는
uncompyle6 unpacked-bak/<exe이름./run.pyc > run.py

4. 요약

  1. 스크립트 사용해서 언패킹
  2. 바이너리 파이썬 버전과 자기가 사용하는 파이썬 버전이 다르다면 맞는 버전 설치.
  3. uncompyle6 설치
  4. PYZ-00.pyz_extracted 폴더에서 아무 모듈 파일과 메인 스크립트를 대조해 매직 넘버 추출하기.
  5. 메인 스크립트에 매직 넘버 넣기.
  6. 디컴파일
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함