티스토리 뷰
글 맨 밑에 요약이 있습니다. 긴 글 읽기 힘드신 분들은 요약 먼저 보세요
준비물
- 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
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?Zda
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. 요약
- 스크립트 사용해서 언패킹
- 바이너리 파이썬 버전과 자기가 사용하는 파이썬 버전이 다르다면 맞는 버전 설치.
- uncompyle6 설치
PYZ-00.pyz_extracted
폴더에서 아무 모듈 파일과 메인 스크립트를 대조해 매직 넘버 추출하기.- 메인 스크립트에 매직 넘버 넣기.
- 디컴파일
'개발 > TIL' 카테고리의 다른 글
backdrop-filter가 사파리에서 작동 안해요!! (0) | 2022.09.18 |
---|---|
Parallax Scrolling 패럴럭스 스크롤링 혹은 비디오 스크롤링 하면서 생기는 영상의 렉을 없애보자 (0) | 2022.08.12 |
Node.js의 대체자? Bun을 알아보자 (0) | 2022.07.27 |
CSS로 폰트 안티앨리어싱 넣기 (0) | 2022.05.25 |
Vite에서 HTML Injecting 하는 법 (0) | 2022.04.11 |
- Total
- Today
- Yesterday
- NUXT
- date-fns
- CSS
- pinia
- e2e
- vite
- uncompyle6
- nuxt.js
- vitejs
- Safari
- SCE-TTS
- 브라우저
- useFetch
- BFrame
- 4kdownload
- backdrop
- yt-dlp
- Bun.js
- Nuxt 3
- 사파리
- DENO
- font-smooth
- decompyle3
- 프론트엔드
- vue
- pyinstaller
- moment.js
- ytdlp
- 웹킷
- vuex
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |