花指令笔记
花指令是逆向工程中常见的对抗手法,这篇笔记整理了一些常见的花指令样本供参考,随机更新中
基于call-return修改rip的花指令
call指令是一种复合指令,它会在跳转至目标地址前将下一条指令对应的地址压栈,然后在return是弹栈恢复rip,如果在return前修改栈上的数据,就可以达到修改rip的效果
这是一个经典的样本,通过call跳转后把esp(栈顶)对应的值加上一定偏移,经过计算可以知道return后rip会被修改为0x413A6A+0x8=0x413A72,也就是说从0x413A65到0x413A71的这一段都是垃圾数据
所以直接nop这一段
可以看到nop完后线性扫描自动分析出了下面的代码
基于jz,jnz的花指令
利用两个连续的jz,jnz指令可以构造出必定执行的跳转,然后中间塞垃圾数据,但是静态分析工具无法分析这种跳转,而且线性扫描扫到垃圾数据反汇编就直接炸了,修复方式也很简单,直接吧jz/jnz到跳转地址前的所有指令nop掉就行了,因为肯定不会执行到
基于 xor,cmp,jz的花指令
同样是构造必定执行的跳转,以下是一种示例
先保存ebx寄存器,然后把ebx寄存器置0,这样jz就必然执行,跳过垃圾数据后再恢复ebx的值
如何编写花指令
编写花指令可以通过内联汇编的形式,以下是一种示例(g++)
1 |
|
其中 volatile 参数可以防止编译器把花指令优化掉
同时在编译时要加上
-fno-asynchronous-unwind-tables
-fno-exceptions
-fno-rtti
等编译参数去除调试信息,否则反编译工具可以借助这些信息提供的控制流信息绕过花指令