反汇编——逆向初步(4)

来源:互联网 发布:中国移动有什么软件 编辑:程序博客网 时间:2024/06/08 09:43

   此次主要讲的是for循环的反汇编。还是和以前一样,先看看一个简单的for循环的代码,如下:
#include
void main()
{
       int i = 0;
       for (i = 0; i < 10; i )
       {
              printf("i=%d\n",i);
       }
       printf("\n");
}
  这是一个很简单的程序,我们来看看它的反汇编代码,如下:
4:       int i =0;
00401028   mov       dword ptr[ebp-4],0
5:       for (i = 0; i< 10; i )
0040102F   mov       dword ptr[ebp-4],0
00401036   jmp       main 31h(00401041)
00401038   mov       eax,dwordptr [ebp-4]
0040103B   add       eax,1
0040103E   mov       dword ptr[ebp-4],eax
00401041   cmp       dword ptr[ebp-4],0Ah
00401045   jge       main 4Ah(0040105a)
6:       {
7:         printf("i=%d\n",i);
00401047   mov       ecx,dwordptr [ebp-4]
0040104A   push      ecx
0040104B   push      offset string"i=%d " (0042201c)
00401050   call      printf(004010b0)
00401055   add       esp,8
8:       }
00401058   jmp       main 28h(00401038)
    仔细一看,发觉这个反汇编与while循环有点类似,开始先是将i的值存入堆栈中,然后跳去执行00401041  cmp       dword ptr[ebp-4],0Ah这句代码,也就是检测i的值是否超出了循环的界限,如果不超出,则执行循环体重的代码,否则跳出循环。
   我们来看执行完循环体的代码后程序又干嘛了。从上面的反汇编代码我们可以看到,执行完循环体的代码后,程序执行这一条指令00401058  jmp       main 28h(00401038),这是跳转去执行这一句代码00401038  mov       eax,dwordptr[ebp-4],这句代码的意思就是从堆栈中取出i的值,将其存入eax寄存器中,接下来就是0040103B  add       eax,1,也就是i,然后再将i存入堆栈中,再用i与循环界限作比较。

   从上面的反汇编中我们可以看出,在佛如循环中,程序一开始会先执行循环体中的代码,然后再是i,接下来才是用i来和循环的上限做比较。有很多同学可能不理解for循环,不知道进入for循环后,程序先干嘛,再干嘛,通过上面的反汇编代码,相信大家对for循环有进一步的了解。

接下来,我们来看看C语言中的数组的反汇编长啥样。我们也是先来看看源代码,如下:
#include
void main()
{
       int j = 0;
       int a[5];
       for (j = 0; j < 5; j )
       {
              a[j] = j;
             printf("a[%d]=%d\n",j,a[j]);
       }
       printf("\n");
}
源代码比较单间,就不解释了,我们直接来看其反汇编代码。如下:
4:       int j =0;
00401028   mov       dword ptr[ebp-4],0
5:       inta[5];
6:       for (j = 0; j< 5; j )
0040102F   mov       dword ptr[ebp-4],0
00401036   jmp       main 31h(00401041)
00401038   mov       eax,dwordptr [ebp-4]
0040103B   add       eax,1
0040103E   mov       dword ptr[ebp-4],eax
00401041   cmp       dword ptr[ebp-4],5
00401045   jge       main 5Ch(0040106c)
7:       {
8:          a[j] =j;
00401047   mov       ecx,dwordptr [ebp-4]
0040104A   mov       edx,dwordptr [ebp-4]
0040104D   mov       dword ptr[ebp ecx*4-18h],edx
9:         printf("a[%d]=%d\n",j,a[j]);
00401051   mov       eax,dwordptr [ebp-4]
00401054   mov       ecx,dwordptr [ebp eax*4-18h]
00401058   push      ecx
00401059   mov       edx,dwordptr [ebp-4]
0040105C   push      edx
0040105D   push      offset string"j=%d\n" (0042201c)
00401062   call      printf(004010b0)
00401067   add      esp,0Ch
10:      }
0040106A   jmp       main 28h(00401038)
   其他的不管,我们直接来看与数组a[]相关的代码。0040104D  mov       dword ptr[ebp ecx*4-18h],edx这一句就是对数组a中的元素进行赋值,主要来解释中括号里的东西,也就是这一串ebpecx*4-18h。可能很多同学都不明白这串是干啥用的,下面我们来看看。
   首先,ebp是堆栈指针,通过用它指向堆栈中相应位置的方式来获取堆栈的数据,由00401047  mov       ecx,dwordptr[ebp-4]可知,ecx里存放的是i的值。为什么ecx要乘以4呢?因为我们给数组a定义的是int型,在32位操作系统中,int型变量占4个字节,也就是说如果i自加1,那么数组a的地址要加4,因为每个int型要占4个字节的空间。然后再减18h,这个可能会让很多人感到疑惑,为什么要减这个数。其实我们将18h转换成十进制后发现这个值为24,这就好理解了。前面我们看到,j的值在堆栈中是[ebp-4],那么[ebp-18h],也就是要减去6个j。我们看一下,前面提到数组a的类型为int型,长度为5,每个元素占4个字节,那么数组a就要占20个字节的空间,再加上j,就是24个字节的空间。所以减去18h就相当于从数组a的首地址开始,将其元素一个一个的取出来。
   这样理解起来就简单的多了,以后大家要是在汇编或反汇编中看到类似于dword ptr [ebpeax*4-18h]这种表达式的,一般情况下都是计算数组的地址,只要好好分析就能将其弄明白。

0 0
原创粉丝点击