花指令(junk code)是一种专门用来迷惑反编译器的指令片段,这些指令片段不会影响程序的原有功能,但会使得反汇编器的结果出现偏差,从而使破解者分析失败。比较经典的花指令技巧有利用
jmp
、call
、ret
指令改变执行流,从而使得反汇编器解析出与运行时不相符的错误代码。—CTF Wiki
简单来讲花指令分为两大类,一种是会被执行的花指令,另一种是不会被执行的花指令。
花指令出现的意义就是干扰机器进行反汇编,迫使人工进行分析。
不会被执行的花指令
1 |
|
内联汇编的语法,语句放在()内,每条指令被””包裹,以分号结尾,如果要使用寄存器则要在寄存器前加上**%,如果使用立即数则在前面加上$**。
可以看到上方爆红。在汇编界面,直接将红框里的内容nop掉
修复后如下
可以执行的花指令
破坏栈
1 |
|
内联汇编的内容实际上就是使用call进行跳转,实现的效果就是跳转到continue打印hello,junkcodes。这样为什么能使ida异常呢?我的理解是:call可以看作是push ip + jmp 指令,ret可以看作是pop ip指令,第一个call next在我们看来相当于一个简单的jmp跳转到了下一条指令,而ida肯定会将它当作函数进行分析,函数内执行了**movl $continue,(%esp);**这样一个操作,将continue的地址放入了esp寄存器中,然后ret指令将IP设为continue的地址,于是顺利执行printf指令。
也就是在ret指令执行过后,esp并没有复原,但是不影响程序运行,这就导致ida认为堆栈不平衡,导致不能反汇编。我们直接将这样的垃圾指令nop掉即可
然后f5一下即可
代码从之前的
变为了
参考:https://nnnewb.github.io/blog/p/learning-packer-07/
插入数据
在vs上,选择x86,编译
1 |
|
这个emit相当于汇编中的db,作用是在当前位置直接插入数据,而我们插入的0xE8是call指令的机器码,于是紧挨着的几个字节会被当作地址处处理,这会导致反汇编的失败。
这段代码的逻辑:调用sub7,执行add dword ptr[esp], 1,给[esp]+1,而【esp】保存的是call下面一条指令也就是_emit 0xE8的地址,经过这样的操作,在执行retn语句的时候,不会返回_emit 0xE8而是直接执行下面的jmp label7,于是程序正常运行。
直接把红框部分nop掉,然后在这个位置按下U也就是undefine
然后再按下c,将数据解析为代码,按下p创建函数,最后F5即可。
赏心悦目
话有一种方法是将E8后面的数据给还原,源代码我们知道,E8后面是一条跳转指令,而不应该像现在这样被解析为数据,在此处按下U
光标放在这个位置按下C
得到
woc,又不行了(刚才不知道为什么阴差阳错这种办法也行),无语了。。。