逆向之KMP算法 ;逆向之hanoi塔

来源:互联网 发布:上海民族乐器一厂 淘宝 编辑:程序博客网 时间:2024/06/04 18:28

逆向之KMP算法 

版本:Release
优化选项:O2
调试工具:OD
源码:
[cpp] view plaincopyprint?
  1. #include <stdio.h>   
  2. #include <stdlib.h>   
  3. #include <string.h>   
  4.   
  5. #define MAX_SIZE 100     
  6. char fail[MAX_SIZE];  
  7.   
  8. void failure(char* pat)  
  9. {  
  10.     int n=strlen(pat);  
  11.     int i,j;  
  12.     fail[0]=-1;  
  13.     for(j=1;j<n;j++)  
  14.     {  
  15.         i=fail[j-1];  
  16.         while((pat[i+1]!=pat[j])&&(i>=0))  
  17.             i=fail[i];  
  18.         if(pat[i+1]==pat[j])  
  19.             fail[j]=i+1;  
  20.         else  
  21.             fail[j]=-1;  
  22.     }  
  23. }  
  24.   
  25. int match(char *string,char *pat)  
  26. {  
  27.     int lenp,lens,i,j;  
  28.     failure(pat);  
  29.     i=j=0;  
  30.     lens=strlen(string);  
  31.     lenp=strlen(pat);  
  32.     while(i<lens&&j<lenp)  
  33.     {  
  34.         if(string[i]==pat[j])  
  35.         {  
  36.             i++;j++;  
  37.         }  
  38.         else  
  39.             if(j==0) i++;  
  40.             else  
  41.                 j=fail[j-1]+1;  
  42.     }  
  43.     return j==lenp?i-lenp:-1;  
  44. }  
  45.   
  46. int main()  
  47. {  
  48.     char s[100]="abcdsdfsdfassdfwefjkjfelkf";  
  49.     char a[10]="dsdf";  
  50.     int q=match(s,a);  
  51.     printf("%d",q);  
  52.     system("pause");  
  53.     return 0;  
  54. }  
  55.   
  56.   
  57. match函数的反汇编  
  58. 00211060 >/$  53            push    ebx  
  59. 00211061  |.  55            push    ebp  
  60. 00211062  |.  8B6C24 10     mov     ebp, dword ptr [esp+10]               ;  第二个参数  
  61. 00211066  |.  56            push    esi  
  62. 00211067  |.  57            push    edi  
  63. 00211068  |.  8BF5          mov     esi, ebp  
  64. 0021106A  |.  E8 91FFFFFF   call    failure                               ;  这个函数只有一个参数且存在esi中  
  65. 0021106F  |.  8B4424 14     mov     eax, dword ptr [esp+14]               ;  第一个参数  
  66. 00211073  |.  33D2          xor     edx, edx  
  67. 00211075  |.  33FF          xor     edi, edi  
  68. 00211077  |.  8D58 01       lea     ebx, dword ptr [eax+1]  
  69. 0021107A  |.  8D9B 00000000 lea     ebx, dword ptr [ebx]  
  70. 00211080  |>  8A08          /mov     cl, byte ptr [eax]  
  71. 00211082  |.  40            |inc     eax  
  72. 00211083  |.  84C9          |test    cl, cl  
  73. 00211085  |.^ 75 F9         \jnz     short 00211080  
  74. 00211087  |.  8BCD          mov     ecx, ebp                              ;  第二个参数传到ecx  
  75. 00211089  |.  2BC3          sub     eax, ebx                              ;  获得字符串长度  
  76. 0021108B  |.  8D71 01       lea     esi, dword ptr [ecx+1]  
  77. 0021108E  |.  8BFF          mov     edi, edi  
  78. 00211090  |>  8A19          /mov     bl, byte ptr [ecx]  
  79. 00211092  |.  41            |inc     ecx  
  80. 00211093  |.  84DB          |test    bl, bl  
  81. 00211095  |.^ 75 F9         \jnz     short 00211090  
  82. 00211097  |.  2BCE          sub     ecx, esi                              ;  获得第二个字符串长度  
  83. 00211099  |.  85C0          test    eax, eax                              ;  设第一个参数长度len1,第二个参数len2,则这里就是判定len1>0  
  84. 0021109B  |.  7E 29         jle     short 002110C6  
  85. 0021109D  |.  8D49 00       lea     ecx, dword ptr [ecx]  
  86. 002110A0  |>  3BD1          /cmp     edx, ecx                             ;  edx随着内部循环而改变,底部的cmp中edi随着内部循环改变,所以特别关注这2个寄存器  
  87. 002110A2  |.  7D 24         |jge     short 002110C8  
  88. 002110A4  |.  8B7424 14     |mov     esi, dword ptr [esp+14]              ;  esi=第1个参数  
  89. 002110A8  |.  8A1C37        |mov     bl, byte ptr [edi+esi]               ;  取第1个数组下标为edi的值  
  90. 002110AB  |.  3A1C2A        |cmp     bl, byte ptr [edx+ebp]               ;  与第2个数组下标为edx的值比较  
  91. 002110AE  |.  75 03         |jnz     short 002110B3  
  92. 002110B0  |.  47            |inc     edi                                  ;  下标自增  
  93. 002110B1  |.  EB 0E         |jmp     short 002110C1  
  94. 002110B3  |>  85D2          |test    edx, edx  
  95. 002110B5  |.  75 03         |jnz     short 002110BA  
  96. 002110B7  |.  47            |inc     edi  
  97. 002110B8  |.  EB 08         |jmp     short 002110C2  
  98. 002110BA  |>  0FBE92 6F3321>|movsx   edx, byte ptr [edx+21336F]           ;  edx=faile[edx]  
  99. 002110C1  |>  42            |inc     edx                                  ;  下标自增  
  100. 002110C2  |>  3BF8          |cmp     edi, eax  
  101. 002110C4  |.^ 7C DA         \jl      short 002110A0  
  102. 002110C6  |>  3BD1          cmp     edx, ecx  
  103. 002110C8  |>  75 09         jnz     short 002110D3                        ;  这里2种返回情况其实就是len2==edx?edi-len2:-1;  
  104. 002110CA  |.  2BF9          sub     edi, ecx  
  105. 002110CC  |.  8BC7          mov     eax, edi  
  106. 002110CE  |.  5F            pop     edi  
  107. 002110CF  |.  5E            pop     esi  
  108. 002110D0  |.  5D            pop     ebp  
  109. 002110D1  |.  5B            pop     ebx  
  110. 002110D2  |.  C3            retn  
  111. 002110D3  |>  5F            pop     edi  
  112. 002110D4  |.  5E            pop     esi  
  113. 002110D5  |.  5D            pop     ebp  
  114. 002110D6  |.  83C8 FF       or      eax, FFFFFFFF  
  115. 002110D9  |.  5B            pop     ebx  
  116. 002110DA  \.  C3            retn  
  117.   
  118. 失配数组获得函数failure  
  119. 00211000 >/$  8BC6          mov     eax, esi                              ;  esi中存储模式串地址  
  120. 00211002  |.  8D50 01       lea     edx, dword ptr [eax+1]  
  121. 00211005  |>  8A08          /mov     cl, byte ptr [eax]  
  122. 00211007  |.  40            |inc     eax  
  123. 00211008  |.  84C9          |test    cl, cl  
  124. 0021100A  |.^ 75 F9         \jnz     short 00211005  
  125. 0021100C  |.  2BC2          sub     eax, edx                              ;  上面几个指令到这里获得字符串长度  
  126. 0021100E  |.  57            push    edi  
  127. 0021100F  |.  8BF8          mov     edi, eax  
  128. 00211011  |.  B9 01000000   mov     ecx, 1  
  129. 00211016  |.  3BF9          cmp     edi, ecx                              ;  if (len>1)  
  130. 00211018  |.  C605 70332100>mov     byte ptr [fail], 0FF                  ;  fail[0]=-1  
  131. 0021101F  |.  7E 3D         jle     short 0021105E  
  132. 00211021  |>  0FBE81 6F3321>/movsx   eax, byte ptr [ecx+21336F]           ;  eax=fail[ecx-1]  
  133. 00211028  |.  8A1431        |mov     dl, byte ptr [ecx+esi]  
  134. 0021102B  |.  385406 01     |cmp     byte ptr [esi+eax+1], dl             ;  if a[eax+1]!=a[ecx]  
  135. 0021102F  |.  74 17         |je      short 00211048  
  136. 00211031  |>  85C0          |/test    eax, eax  
  137. 00211033  |.  7C 0D         ||jl      short 00211042  
  138. 00211035  |.  0FBE80 703321>||movsx   eax, byte ptr [eax+fail]  
  139. 0021103C  |.  385406 01     ||cmp     byte ptr [esi+eax+1], dl  
  140. 00211040  |.^ 75 EF         |\jnz     short 00211031                      ;  while(eax>0) eax=fail[eax];if(a[eax+1]==a[ecx]) break;  
  141. 00211042  |>  385406 01     |cmp     byte ptr [esi+eax+1], dl  
  142. 00211046  |.  75 0A         |jnz     short 00211052  
  143. 00211048  |>  FEC0          |inc     al  
  144. 0021104A  |.  8881 70332100 |mov     byte ptr [ecx+fail], al              ;  fail[ecx]=eax+1  
  145. 00211050  |.  EB 07         |jmp     short 00211059  
  146. 00211052  |>  C681 70332100>|mov     byte ptr [ecx+fail], 0FF             ;  fail[ecx]=-1  
  147. 00211059  |>  41            |inc     ecx  
  148. 0021105A  |.  3BCF          |cmp     ecx, edi  
  149. 0021105C  |.^ 7C C3         \jl      short 00211021                       ;  for(ecx=1;ecx<len;ecx++)  
  150. 0021105E  |>  5F            pop     edi  
  151. 0021105F  \.  C3            retn  


逆向之hanoi塔 

没耐心逆复杂的了,就搞搞这个递归的
版本:Release
优化选项:O2
调试工具:OD
源码:
[cpp] view plaincopyprint?
  1. //Hanoi塔(递归版本)   
  2. #include <stdio.h>   
  3. #include <stdlib.h>   
  4. #define Tower1 1   
  5. #define Tower2 2   
  6. #define Tower3 3   
  7. void towers_of_hanoi(intintintint);  
  8.   
  9. int main(){  
  10.     int n_disks;  
  11.     printf("Number of disks: ");   
  12.     scanf("%d", &n_disks);  
  13.     printf("Disk, source, and destination towers listed below\n");  
  14.     printf("%12s%10s%15s\n""Disk No""Source","Destination");  
  15.     towers_of_hanoi(n_disks,Tower1,Tower3,Tower2);  
  16.     system("pause");  
  17.     return 0;  
  18. }  
  19.   
  20. void towers_of_hanoi(int n_disks, int source, int dest, int spare){  
  21.   if (n_disks == 1 )   
  22.     printf("%10d%10d%10d\n", n_disks, source, dest);  
  23.    else {  
  24.       /*move a disk from source to spare*/  
  25.       towers_of_hanoi(n_disks-1,source,spare,dest);  
  26.       printf("%10d%10d%10d\n", n_disks, source, dest);  
  27.       /*move a disk from spare to destination tower*/  
  28.       towers_of_hanoi(n_disks-1,spare,dest,source);  
  29.   }  
  30. }  
  31.   
  32. towers_of_hanoi函数,这里的递归经过优化后不太清楚。。。  
  33. 01211061  |.  8B7424 08     mov     esi, dword ptr [esp+8]            ;  第一个参数,即盘子数  
  34. 01211065  |.  57            push    edi  
  35. 01211066  |.  8B7C24 10     mov     edi, dword ptr [esp+10]           ;  第2个参数  
  36. 0121106A  |.  83FE 01       cmp     esi, 1  
  37. 0121106D  |.  74 3A         je      short 012110A9                    ;  盘子数等于1  
  38. 0121106F  |.  53            push    ebx  
  39. 01211070  |.  55            push    ebp  
  40. 01211071  |.  8B6C24 20     mov     ebp, dword ptr [esp+20]           ;  第4个参数  
  41. 01211075  |>  8B4424 1C     /mov     eax, dword ptr [esp+1C]          ;  第3个参数  
  42. 01211079  |.  50            |push    eax                              ;  假设原函数f(a,b,c,d),那么这里的调用就是f(a,b,d,c)  
  43. 0121107A  |.  55            |push    ebp  
  44. 0121107B  |.  8D5E FF       |lea     ebx, dword ptr [esi-1]  
  45. 0121107E  |.  57            |push    edi  
  46. 0121107F  |.  53            |push    ebx                              ;  ebx=esi-1  
  47. 01211080  |.  E8 DBFFFFFF   |call    towers_of_hanoi                  ;  代码中只递归一次,另外一次被优化掉了,优化成这个循环  
  48. 01211085  |.  8B4C24 2C     |mov     ecx, dword ptr [esp+2C]  
  49. 01211089  |.  51            |push    ecx                              ; /<%10d>  
  50. 0121108A  |.  57            |push    edi                              ; |<%10d>  
  51. 0121108B  |.  56            |push    esi                              ; |<%10d>  
  52. 0121108C  |.  68 74212101   |push    01212174                         ; |format = "%10d%10d%10d",LF,""  
  53. 01211091  |.  FF15 9C202101 |call    dword ptr [<&MSVCR90.printf>]    ; \printf  
  54. 01211097  |.  8BC7          |mov     eax, edi                         ;  这里交换参数准备下一次调用也就是f(a,d,c,b)  
  55. 01211099  |.  8BF3          |mov     esi, ebx                         ;  esi=esi-1作为下一次判断条件  
  56. 0121109B  |.  83C4 20       |add     esp, 20  
  57. 0121109E  |.  8BFD          |mov     edi, ebp  
  58. 012110A0  |.  8BE8          |mov     ebp, eax  
  59. 012110A2  |.  83FE 01       |cmp     esi, 1  
  60. 012110A5  |.^ 75 CE         \jnz     short 01211075  
  61. 012110A7  |.  5D            pop     ebp  
  62. 012110A8  |.  5B            pop     ebx  
  63. 012110A9  |>  8B5424 14     mov     edx, dword ptr [esp+14]           ;  第3个参数  
  64. 012110AD  |.  52            push    edx                               ; /<%10d>  
  65. 012110AE  |.  57            push    edi                               ; |<%10d>  
  66. 012110AF  |.  56            push    esi                               ; |<%10d>  
  67. 012110B0  |.  68 74212101   push    01212174                          ; |format = "%10d%10d%10d",LF,""  
  68. 012110B5  |.  FF15 9C202101 call    dword ptr [<&MSVCR90.printf>]     ; \printf  
  69. 012110BB  |.  83C4 10       add     esp, 10  
  70. 012110BE  |.  5F            pop     edi  
  71. 012110BF  |.  5E            pop     esi  
  72. 012110C0  \.  C3            retn  

经过反复反复反复观察观察实例实例。。。比如第一次参数f(a,b,c,d);   那么循环处调用的其实是第一次f(a,b,d,c),下一次循环就是f(a,d,b,c)
而这个f(a,d,b,c)其实就是源码的第二次递归调用后的第一次递归调用,也就是f(a,d,c,b),进入这个后第一次就是f(a,d,b,c)其实就跟优化后的循环调用一样了,使得所有的第二次递归都变成了第一次递归的样子,语言比较难描述。。。
贴完了。。。

原创粉丝点击