循环是高级语言中可以进行反向引用的一种语言形式,其他类型的分支语句(比如IF-THEN-ELSE等)都是由低向高地址区域走的.因此,通过这点可以较方便的将循环语句识别出来.如果确定某段代码是循环,就可以分析其计数器,一般是用ecx寄存器做计数器,也有用其他方法来控制循环的,如/"test eax,eax/"等.
看一个简单的循环代码:
- xoreax,eax;eax清零
- @@:
- incecx;计数
- ....
- cmpecx,0A;循环10次
- ;重复
如果上面的代码用C来表示的话:
- while(i<10)
- {
- ....
- }
或者:
- for(i=0;i<10;i++)
- {
- ....
- }
用C写一段比较复杂的循环:
- #include /"stdio.h/"
- #include /"windows.h/"
- int main(void)
- {
- int i,sum=0;
- for(i=0;i<=100;i++)
- sum=sum+i;
- printf(/"%d/",sum);
- Sleep(100000);
- return 0;
- }
反汇编的结果如下
- 00401028|.C745 F8 00000>MOV DWORD PTR SS:[EBP-8],0 ;变量清零
- 0040102F|.C745 FC 00000>MOV DWORD PTR SS:[EBP-4],0 ;变量清零
- 00401036|.EB 09 JMP SHORT 循环.00401041;先跳到比较处
- 00401038|>8B45 FC /MOV EAX,DWORD PTR SS:[EBP-4];i赋值给eax
- 0040103B|.83C0 01 |ADD EAX,1 ;eax+1->i+1
- 0040103E|.8945 FC |MOV DWORD PTR SS:[EBP-4],EAX;eax+1后的值再送还给i
- 00401041|>837D FC 64|CMP DWORD PTR SS:[EBP-4],64 ;i+1后的值和64h(100)比较
- 00401045|.7F 0B |JG SHORT 循环.00401052;大于就往下跳
- 00401047|.8B4D F8 |MOV ECX,DWORD PTR SS:[EBP-8]
- 0040104A|.034D FC |ADD ECX,DWORD PTR SS:[EBP-4];[ebp-4]是变量i
- 0040104D|.894D F8 |MOV DWORD PTR SS:[EBP-8],ECX;变量sum
- 00401050|.^ EB E6 SHORT 循环.00401038
- 00401052|>8B55 F8 MOV EDX,DWORD PTR SS:[EBP-8]
- 00401055|.52PUSH EDX ; /Arg2
- 00401056|.68 1C004200 PUSH 循环.0042001C ; |Arg1 = 0042001C ASCII /"%d/"
- 0040105B|.E8 50000000 CALL 循环.004010B0 ; //循环.004010B0
- 00401060|.83C4 08 ADD ESP,8
- 00401063|.8BF4MOV ESI,ESP
- 00401065|.68 A0860100 PUSH 186A0 ; /Timeout = 100000. ms
- 0040106A|.FF15 3C514200 CALL DWORD PTR DS:[<&KERNEL32.Sleep>];
另一种反汇编出来的情况是
- xorecx,ecx;变量初始化,即sum=0
- xoreax,eax;变量初始化,即i=0
- @@:
- addecx,eax;相当于sum=sum+i
- inceax;eax+1,即i++
- cmpeax,64h;将变量i与100比较
- ;如果eax<100就往上跳
- xoreax,eax