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 编码藏起来。

文件结构(从外到内)#

是什么怎么拆
1PE32+ x86-64 控制台程序,5.9MBfile / DIE 识别
2UPX 壳(节区 UPX0/UPX1,入口是 UPX 解压 stub)upx -d 或内存转储
3PyInstaller 打包的 Python 程序(bootloader + 内嵌 PKG 归档)pyinstxtractor-ng 提取
4入口脚本 33.pyc(Python 3.9 头,251 字节)反汇编(xdis)

分析链路(做题人视角)#

Terminal window
# 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_file
from xdis.std import disassemble
version, _, _, 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 串藏在字节码常量表里,脱壳+提取后直接可见,属于”一眼题”;没有做反调试、字符串加密、多段校验。