#少女前線 416とM16A1のあの頃 - 反骨MAX
510 字
3 分钟
33.exe 逆向分析报告
题型:Reverse(babyRe) 技术点:UPX 脱壳 → PyInstaller 拆包 → Python 字节码反汇编 → base64 解码
结论
Flag: flag{4b14a257-4336-4152-9f06-48c7b1}
还原出的题目源码等价于:
import base64
encoded_flag = "ZmxhZ3s0YjE0YTI1Ny00MzM2LTQxNTItOWYwNi00OGM3YjF9"flag = base64.b64decode(encoded_flag).decode("utf-8")print(flag)也就是:程序运行时直接打印 flag,flag 本体只是做了一层 base64 编码藏起来。
文件结构(从外到内)
| 层 | 是什么 | 怎么拆 |
|---|---|---|
| 1 | PE32+ x86-64 控制台程序,5.9MB | file / DIE 识别 |
| 2 | UPX 壳(节区 UPX0/UPX1,入口是 UPX 解压 stub) | upx -d 或内存转储 |
| 3 | PyInstaller 打包的 Python 程序(bootloader + 内嵌 PKG 归档) | pyinstxtractor-ng 提取 |
| 4 | 入口脚本 33.pyc(Python 3.9 头,251 字节) | 反汇编(xdis) |
分析链路(做题人视角)
# 1. 识别file 33.exe # PE32+ executable (console) x86-64# 或 DIE / Exeinfo PE:发现 UPX
# 2. 脱壳upx -d 33.exe -o 33_unpacked.exe
# 3. 识别为 PyInstaller:字符串里出现 [PYI-...]、_pyi_main_co 等strings 33_unpacked.exe | grep -i pyi
# 4. 提取内嵌归档python pyinstxtractor_ng.py 33_unpacked.exe# 得到 33_unpacked.exe_extracted/,入口为 33.pyc
# 5. 反汇编字节码(uncompyle6 不支持 3.9,用 xdis 反汇编最稳)python - <<'EOF'from xdis import load_module, disassemble_filefrom xdis.std import disassembleversion, _, _, co, *_ = load_module("33_unpacked.exe_extracted/33.pyc")print(co.co_consts) # 直接看到 base64 字符串disassemble(co)EOF
# 6. 解码python -c "import base64;print(base64.b64decode('ZmxhZ3s0YjE0YTI1Ny00MzM2LTQxNTItOWYwNi00OGM3YjF9').decode())"# flag{4b14a257-4336-4152-9f06-48c7b1}本题设计要点(出题人视角)
- 难度定位:babyRe —— 两层”包装防护”(UPX 壳 + PyInstaller),但核心逻辑零加密零混淆,只要会拆包就能秒解。
- 防的不是分析,是”手残”:UPX 挡住直接
strings找 flag;PyInstaller 挡住把 exe 当普通 C 程序逆。真正的考点是”认得出壳、会脱壳、会提取 Python 字节码”。 - 注意点:pyc 头写的是 Python 3.9(pyinstxtractor 识别为 3.9),但反汇编出来的部分指令序列更接近 3.11+ 风格,常规反编译器(uncompyle6/decompyle3)会拒绝或报错——所以本题反汇编比反编译更可靠,这也是作者留的一个小坑/小技巧。
- 诚实性:flag 的 base64 串藏在字节码常量表里,脱壳+提取后直接可见,属于”一眼题”;没有做反调试、字符串加密、多段校验。