逆向随机生成100个数

来源:互联网 发布:jumpsoles 淘宝 编辑:程序博客网 时间:2024/06/14 05:13

这次笔记难度加大一点了!有比较多的跳转和循环,还包含数组寻址~~~

笔记还是整理漂亮一点吧,以后可能要拿来做教程。

C源代码,,VC编译无压力过:

 #include <stdio.h>#include <stdlib.h>void main() {      int a[101],x[11],i,p;  for(i=0;i<=10;i++)  x[i]=0;   for(i=1;i<=100;i++)  {      a[i]=rand() % 100;    printf("%4d",a[i]);    if(i%10==0)   printf("\n");  }   for(i=1;i<=100;i++)   {               p=a[i]%10;      if(p==0) p=10;      x[p]=x[p]+1;   }   for(i=1;i<=10;i++)   {       p=i;     if(i==10) p=0;     printf("%d,%d\n",p,x[i]);   }   printf("\n");  system("pause");}

照样F8到程序跑飞,断下Call F7跟进代码如下

00401000       81EC C0010000      sub esp,1C0                              ; 1c0=448,448=101*4+11*4
00401006       B9 0B000000        mov ecx,0B                               ; ecx=11
0040100B       33C0               xor eax,eax                              ; eax=0
0040100D       56                 push esi
0040100E       57                 push edi
0040100F       8D7C24 08          lea edi,dword ptr ss:[esp+8]             ; 访问缓冲区的地址
00401013       BE 01000000        mov esi,1                                ; esi=1
00401018       F3:AB              rep stos dword ptr es:[edi]              ; 将eax往es:[edi]放11次
0040101A       8D7C24 38          lea edi,dword ptr ss:[esp+38]            ; 访问数组x的末尾+1也就是数组a的起始
0040101E       E8 74010000        call asm.00401197                        ; rand
00401023       99                 cdq                                      ; edx变成eax的符号位
00401024       B9 64000000        mov ecx,64                               ; ecx=100
00401029       F7F9               idiv ecx                                 ; eax除以ecx,商在eax 余数在edx
0040102B       52                 push edx
0040102C       68 44804000        push asm.00408044                        ; ASCII "%4d"
00401031       8917               mov dword ptr ds:[edi],edx               ; 把余数转存到ds:[edi]??噢噢.. ds:[edi]就是相当于a[i]了
00401033       E8 2E010000        call asm.00401166
00401038       8BC6               mov eax,esi
0040103A       B9 0A000000        mov ecx,0A
0040103F       99                 cdq
00401040       F7F9               idiv ecx                                 ; eax除以10
00401042       83C4 08            add esp,8                                ; 我靠,401033call的堆栈平衡的语句还跑那么远来执行
00401045       85D2               test edx,edx
00401047       75 0D              jnz short asm.00401056
00401049       68 40804000        push asm.00408040
0040104E       E8 13010000        call asm.00401166
00401053       83C4 04            add esp,4                                ; 还是堆栈平衡,这次像样点。
00401056       46                 inc esi
00401057       83C7 04            add edi,4
0040105A       83FE 64            cmp esi,64
0040105D     ^ 7E BF              jle short asm.0040101E
0040105F       8D4C24 38          lea ecx,dword ptr ss:[esp+38]            ; 数组a的地址放到ecx
00401063       BE 64000000        mov esi,64                               ; esi=100
00401068       8B01               mov eax,dword ptr ds:[ecx]               ; 循环起始
0040106A       BF 0A000000        mov edi,0A                               ; edi=10
0040106F       99                 cdq
00401070       F7FF               idiv edi
00401072       85D2               test edx,edx
00401074       75 02              jnz short asm.00401078                   ; if eax/10没有余数则跳转
00401076       8BD7               mov edx,edi
00401078       8B7C94 08          mov edi,dword ptr ss:[esp+edx*4+8]       ; 这两条啊 +了8,是因为之前还push了两个寄存器 还记得吗?就是最前面的那两个push
0040107C       8D4494 08          lea eax,dword ptr ss:[esp+edx*4+8]       ; 从上面三句看出 edx是作为变量p了
00401080       47                 inc edi
00401081       83C1 04            add ecx,4                                ; 把a数组的下标往后挪
00401084       4E                 dec esi
00401085       8938               mov dword ptr ds:[eax],edi
00401087     ^ 75 DF              jnz short asm.00401068                   ; 循环结束
00401089       BE 01000000        mov esi,1                                ; esi是循环变量咯
0040108E       83FE 0A            cmp esi,0A
00401091       8BC6               mov eax,esi
00401093       75 02              jnz short asm.00401097
00401095       33C0               xor eax,eax
00401097       8B54B4 08          mov edx,dword ptr ss:[esp+esi*4+8]
0040109B       52                 push edx
0040109C       50                 push eax
0040109D       68 38804000        push asm.00408038                        ; ASCII "%d,%d
"
004010A2       E8 BF000000        call asm.00401166
004010A7       83C4 0C            add esp,0C
004010AA       46                 inc esi
004010AB       83FE 0A            cmp esi,0A
004010AE     ^ 7E DE              jle short asm.0040108E
004010B0       68 40804000        push asm.00408040
004010B5       E8 AC000000        call asm.00401166
004010BA       68 30804000        push asm.00408030                        ; ASCII "pause"
004010BF       E8 0C000000        call asm.004010D0
004010C4       83C4 08            add esp,8
004010C7       5F                 pop edi
004010C8       5E                 pop esi
004010C9       81C4 C0010000      add esp,1C0
004010CF       C3                 retn

 

这次逆向的这个算法总结了一些经验 分享一下

1  遇到跳转跨度较大的,例如跨了20条语句左右的,那大概就是一个C语言里的for while do这些循环了。

2  认清循环之后要找准循环变量再进行后续分析

3 很多时候程序会以ecx作为循环变量,如果ecx用作其他用途的话 也会选择其他寄存器做循环变量

4 在程序里面有些局部变量编译器会直接用寄存器把他替换掉,所以要认清哪个寄存器把这个变量替换掉了

5

00401000       81EC C0010000      sub esp,1C0                              ; 1c0=448,448=101*4+11*4
00401006       B9 0B000000        mov ecx,0B                               ; ecx=11
0040100B       33C0               xor eax,eax                              ; eax=0
0040100D       56                 push esi
0040100E       57                 push edi
0040100F       8D7C24 08          lea edi,dword ptr ss:[esp+8]             ; 访问缓冲区的地址
这里的最后一条语句的意思我开始以为是访问CALL语句的下一条指令的地址呢,原来是因为在程序开头用sub esp,1c0开辟了一段缓冲区,

然后push了两个寄存器,所以访问这段缓冲区自然就是esp+8了

6

程序开始时分配的这一段缓冲区是一下子分配给了一个或者一个以上的数组和变量了,这里的缓冲区包含数组a和数组x

原来后声明的变量还排在缓冲区的前面。。也就是,这里的缓冲区数组x的11个元素排前面 接着才是数组a

从这里可以看出:0040101A       8D7C24 38          lea edi,dword ptr ss:[esp+38]            ; 访问数组x的末尾+1也就是数组a的起始

esp+38,38h也就是56D,就是56了,56减去之前的两个寄存器占的8个字节,也就是48了,每个int变量占4个字节,那么这里就是有12个变量了,什么?12???,x不是11个元素吗?怎么成12了,呵呵因为第12已经是接下来的数组的第一个元素了!!


原创粉丝点击