逆向第一篇,两年前写的,欢迎大家吐槽!
转载请注明出处。
1.流程控制语句的识别
If…else…语句比较简单,这里就不做详细说明。这里对switch语句和循环语句进行判断。
1.1 switch语句
1.1.1 case语句块不大于3条(模拟if…else…结构,也有可能不止3条,表示比较少)
此时,switch语句块反汇编的代码与if…else…的相差无几,只是switch语句将所有条件跳转都放到了一起并与case语句块分开,而if…else…则是每一条跳转语句后都跟着语句块,反汇编都比较简单,这里不再赘述。下面举出一个例子:
8: switch(i){
0042B3F6 mov eax,dword ptr [i]
0042B3F9 mov dword ptr[ebp-0D0h],eax
//取出i的值
0042B3FF cmp dword ptr [ebp-0D0h],1 //和1比较
0042B406 je test_switch_if+5Ch (42B41Ch) //条件成立跳转到case1
0042B408 cmp dword ptr [ebp-0D0h],3 //和3比较
0042B40F je test_switch_if+6Bh(42B42Bh) //条件成立跳转到case3
0042B411 cmp dword ptr [ebp-0D0h],64h //和100比较
0042B418 je test_switch_if+7Ah (42B43Ah) //条件成立跳转到case100
0042B41A jmp test_switch_if+87h(42B447h) //否则跳转至switch结束处
9: case 1:
10: printf("i == 1");
0042B41C push offset string "i== 1" (47DC80h)
0042B421 call @ILT+4100(_printf) (42A009h)
0042B426 add esp,4
//调用printf函数
11: break;
//跳转至switch结束处,下面两个结构相同
0042B429 jmp test_switch_if+87h (42B447h)
12: case 3:
13: printf("i == 3");
0042B42B push offset string "i == 3" (47DC78h)
0042B430 call @ILT+4100(_printf) (42A009h)
0042B435 add esp,4
14: break;
0042B438 jmp test_switch_if+87h (42B447h)
15: case 100:
16: printf("i == 100");
0042B43A push offset string "i== 100" (47DC6Ch)
0042B43F call @ILT+4100(_printf) (42A009h)
0042B444 add esp,4
17: break;
18: }
1.1.2 有序线性表的switch
当case的最大值和最小值之间差距较小时使用这种方法优化,一半差距不会大于10(VC++6.0似乎是不大于7,下面会看到和VS2010编译器的区别)。
直接看例子:
26: switch(nIndex)
0042B4C6 mov eax,dword ptr[nIndex]
0042B4C9 mov dword ptr[ebp-0D0h],eax
0042B4CF mov ecx,dword ptr [ebp-0D0h]
//到此为止的三行是取出i的值
0042B4D5 sub ecx,1
//这里的减1则是为了与线性表的对齐,线性表第一个为0
0042B4D8 mov dword ptr [ebp-0D0h],ecx
0042B4DE cmp dword ptr [ebp-0D0h],6
//这里和6比较是因为case最大值为7,减1后为6,若超过最大值则直接跳出语句或跳向default
0042B4E5 ja $LN1+0Dh (42B54Ch)
0042B4E7 mov edx,dword ptr [ebp-0D0h]
0042B4ED jmp dword ptr (42B59Ch)[edx*4]
//决定跳向哪个case
27: {
28: case 1:
29: printf("nIndex == 1");
0042B4F4 push offset string"nIndex == 1" (47DCECh)
0042B4F9 call @ILT+4100(_printf) (42A009h) </