常见反汇编技术
一. 相同目标的跳转指令
当jz与jnz的目地地址相同时,此时相当于jmp,但是IDA会将jnz后面的指令(实际上不会执行的指令)进行反汇编,这个时候如果加上比如call(E8),jmp(E9)等字节指令,那么势必会导致反汇编出现问题。
这个时候我们需要将jnz后面的代码转化为数据,然后使正常跳转的位置转化为代码段。
例如:74 03 75 01 E8 58(4011c5) C3 90 90
对应汇编指令为:
jz loc_4011c4+1;
jnz loc_4011c4+1;
call near ptr 90D0D521h;
这里显然就是出现了问题,jz和jnz都是跳转至loc_4011c5,即至58 c3 90 90。
实际的汇编代码为:
pop eax;
retn;
nop;
nop;
也就是说这个E8(call)实际上应该是无用的数据,但是却被反汇编,我们的解决方法就是将这个字节改为数据类型。
二.固定条件的跳转指令
当条件一定满足时说明这条判断语句指令后面的代码一定处于可执行状态,那么false对应的指令一定不会执行,这个时候倘若出现反汇编错误就可以对false对应的指令进行修改。
例如:33 C0 74 01 E9(jmp) 58(4011c5) C3 68 94
汇编指令为:
xor eax,eax;
jz loc_4011c4+1;
jmp near ptr 94A8D521h;
这里jz是一定会跳转的所以E9是不会执行应该是从4011c5开始反汇编。
正确反汇编代码为:
xor eax,eax;
jz loc_4011c4+1;
pop eax;
retn;
三.无效的反汇编指令
流氓字节作为合法指令的一部分时,需要对字节码进行详细的分析,甚至是到底层分析。
例如:66 B8 EB(4011c2) 05 31 C0 74 FA E8(call) real code
汇编指令为:
mov ax, 05EBh;
xor eax,eax;
jz sub_4011c0+2;
call ;
这里实际上就是跳转之后为可执行代码的部分。
实际汇编代码流程:
mov ax, 05EBh;
xor eax,eax;
jz sub_4011c0+2;
jmp sub_4011c2+4;
这里就需要对这一段代码进行详细分析,判断这段代码实际产生的效果,然后使用脚本用nop指令替换无效指令。
四.混淆控制流图
1.函数指针问题:将函数指针放入寄存器或者堆栈当中,然后使用call调用对应函数,这样的话就没办法直接通过ctrl+x查看函数调用,但是这里可以通过查看对offset sub_4011c0的调用来进行分析。
mov [ebp+var_4], offset sub_4011c0;
push 2Ah;
call [ebp+var_4];
2.滥用返回指针
使用retn指令来实现函数调用
var_4 =byte ptr -4;
4011c0 call $+5;//将4011c5压入栈中
4011c5 add [esp+4+var_4],5;//将栈转化为4011CA
4011c9 retn;//调用4011CA函数
4011ca push ebp;
...
...
这样的话就无法正常定位有关的函数调用