花指令
原理
反汇编器通常有两种主要策略:
线性扫描:顺序解析每条指令,遇到干扰字节就会错位
递归下降:根据控制流跳转来反汇编,更智能但依然可能被误导
花指令正是利用反汇编器的缺陷——让它把数据当成代码,或者把代码的一部分拆解成错误指令
最终反汇编出来的结果是混乱、错误、不连续的,分析者需要手动修复或动态调试才能看清真实逻辑
实战案例

使用 Exeinfo PE 发现有 UPX 壳

脱壳后用 IDA 分析,有花指令

关键点:jnz +1 的跳转目标
jnz short指令本身长 2 字节(75 操作码 + 01 偏移量)偏移量是相对下一指令地址的位移。当前
jnz位于0x40102C,下一指令地址是0x40102E加上
+1,目标地址 =0x40102E + 1=0x40102F因此,无论标志位如何,CPU 下一步必然从
0x40102F开始执行
所以,call 0EC85D78Bh 这条 5 字节指令的唯一目的就是干扰 IDA 反编译
CPU 实际会执行的部分是从 0x40102F 开始的每一个字节,所以这些字节一个都不能动
唯一需要填掉的是 IDA 会顺序解析,但 CPU 永不执行的部分,即:
75 01这 2 字节的jnz(它虽然会执行,但它的存在让 IDA 沿着0x40102E往下分析。如果我们NOP掉它,IDA 就不会进入那条错误的分支了)E8这 1 字节的call操作码
因此,我们只需把 0x40102C 开始的 3 个字节 改为 90:
1 | 原始: 75 01 E8 58 C7 45 EC ... |
保存后再次反编译可以看到伪代码,接受用户输入的 awsd 推测为迷宫类题目

Shift + F12 打开字符串列表

正好是 70 个字符,对应一个 7 行 × 10 列 的迷宫
1 | *******+** |
s s a a a s a a s s d d d w → 刚好能走到 F 的位置,所以 flag 就是 flag{ssaaasaassdddw}