Problem: [SWPUCTF 2025 秋季新生赛]Ultimate Packer for eXecutables
思路
[SWPUCTF 2025 秋季新生赛]Ultimate Packer for eXecutables

先使用exeinfo对程序进行分析获取信息
Sign.4399 : [ x64 - UPX exe - NRV2E/7 compression ]
Don't try : upx.exe -d option ( min. 3.91 UPX required !!! )
[ Tampared file ] x64 UPX v3.9 - 5.0 - [ 5.02 ] - exe signature - 2013-2025 - http://upx.github.io ,
Overlay : 2E6669… Nothing detected
分析之后得知存在upx加壳,但是发现不能直接进行脱壳,推测有以下可能性
- 文件中的 UPX header 被作者刻意修改
- 文件被“篡改 / 破坏部分头部”
- UPX 版本号伪造
- 校验字段损坏,导致 upx -d 失败
之后对程序进行分析采用读结构 + 快速检索的方式
- 魔数偏移
- 先简单搜索文件里类似 UPX/XPU 的 4 字节序列,发现只有 XPU1,位置在十进制 517(0x205)。
- 进一步确认:这是常见的 UPX 头部标记被反转写了,于是锁定这里就是需要改回 UPX! 的地方。
- 节表位置
- 读取 DOS 头 0x3C 处的 4 字节,得到 PE 头偏移 0x80。
- 在 PE 头中,Optional Header 大小字段(PE+0x14 处的 2 字节)是 0xF0。
- 节表起始 = PE 偏移 + 24(标准 PE 头大小)+ Optional Header 大小 = 0x80 + 0x18 + 0xF0 = 0x188。每个节表项 40 字节。
- 节名定位
- 节表起始 0x188 处的前 8 字节是第 1 节名,0x188 + 40 是第 2 节名,0x188 + 80 是第 3 节名。
- 看到它们被改成 SAUY / YSYY / C4RP,确认是原本的 UPX0/UPX1/.rsrc 被替换。
- RawPointer 定位
在每个节条目内部,偏移布局:name(0..7) -> VirtualSize(+8) -> VirtualAddress(+12) -> SizeOfRawData(+16) -> PointerToRawData(+20)。
因此第 1 个节的 RawPointer 是节表起始 + 20(即 0x188 + 20 = 0x19C)。看到这里被篡改成非零,按 UPX 习惯改回 0。
之后保存为新文件,再重新使用3.91 UPX进行脱壳

脱壳后解题流程:
- 先在脱壳后的 PE 里找提示字符串(“please input flag:”“You get flag!”等),跟踪交叉引用,定位到校验函数(0x1400017xx 附近)。
- 观察循环逻辑:逐字节处理输入,计算 enc_byte = (ch * 0x7A - 0x17) & 0xFF,然后与 .data 里的 27 字节常量比对,全匹配则输出成功。
- 提取那段常量:十六进制为 15 77 77 d7 f1 45 87 6b 49 19 ef 93 b7 93 93 a3 b7 23 ab 93 a3 17 b1 3d 49 a3 7b,长度正好 27,对应 flag 长度。
- 逆变换:对常量逐字节求解 (x*0x7A - 0x17) mod 256 = enc[i] 的 x,选可打印字符即可还原明文。
- 结果得到 NSSCTF{Upx?ysyy!sauy!c4rp!},再正向代入公式可完全还原出原始常量,验证无误。
总结
- upx魔改 upx脱壳 静态分析
