逆向之KMP算法 ;逆向之hanoi塔
来源:互联网 发布:上海民族乐器一厂 淘宝 编辑:程序博客网 时间:2024/06/04 18:28
逆向之KMP算法
版本:Release
优化选项:O2
调试工具:OD
源码:
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define MAX_SIZE 100
- char fail[MAX_SIZE];
- void failure(char* pat)
- {
- int n=strlen(pat);
- int i,j;
- fail[0]=-1;
- for(j=1;j<n;j++)
- {
- i=fail[j-1];
- while((pat[i+1]!=pat[j])&&(i>=0))
- i=fail[i];
- if(pat[i+1]==pat[j])
- fail[j]=i+1;
- else
- fail[j]=-1;
- }
- }
- int match(char *string,char *pat)
- {
- int lenp,lens,i,j;
- failure(pat);
- i=j=0;
- lens=strlen(string);
- lenp=strlen(pat);
- while(i<lens&&j<lenp)
- {
- if(string[i]==pat[j])
- {
- i++;j++;
- }
- else
- if(j==0) i++;
- else
- j=fail[j-1]+1;
- }
- return j==lenp?i-lenp:-1;
- }
- int main()
- {
- char s[100]="abcdsdfsdfassdfwefjkjfelkf";
- char a[10]="dsdf";
- int q=match(s,a);
- printf("%d",q);
- system("pause");
- return 0;
- }
- match函数的反汇编
- 00211060 >/$ 53 push ebx
- 00211061 |. 55 push ebp
- 00211062 |. 8B6C24 10 mov ebp, dword ptr [esp+10] ; 第二个参数
- 00211066 |. 56 push esi
- 00211067 |. 57 push edi
- 00211068 |. 8BF5 mov esi, ebp
- 0021106A |. E8 91FFFFFF call failure ; 这个函数只有一个参数且存在esi中
- 0021106F |. 8B4424 14 mov eax, dword ptr [esp+14] ; 第一个参数
- 00211073 |. 33D2 xor edx, edx
- 00211075 |. 33FF xor edi, edi
- 00211077 |. 8D58 01 lea ebx, dword ptr [eax+1]
- 0021107A |. 8D9B 00000000 lea ebx, dword ptr [ebx]
- 00211080 |> 8A08 /mov cl, byte ptr [eax]
- 00211082 |. 40 |inc eax
- 00211083 |. 84C9 |test cl, cl
- 00211085 |.^ 75 F9 \jnz short 00211080
- 00211087 |. 8BCD mov ecx, ebp ; 第二个参数传到ecx
- 00211089 |. 2BC3 sub eax, ebx ; 获得字符串长度
- 0021108B |. 8D71 01 lea esi, dword ptr [ecx+1]
- 0021108E |. 8BFF mov edi, edi
- 00211090 |> 8A19 /mov bl, byte ptr [ecx]
- 00211092 |. 41 |inc ecx
- 00211093 |. 84DB |test bl, bl
- 00211095 |.^ 75 F9 \jnz short 00211090
- 00211097 |. 2BCE sub ecx, esi ; 获得第二个字符串长度
- 00211099 |. 85C0 test eax, eax ; 设第一个参数长度len1,第二个参数len2,则这里就是判定len1>0
- 0021109B |. 7E 29 jle short 002110C6
- 0021109D |. 8D49 00 lea ecx, dword ptr [ecx]
- 002110A0 |> 3BD1 /cmp edx, ecx ; edx随着内部循环而改变,底部的cmp中edi随着内部循环改变,所以特别关注这2个寄存器
- 002110A2 |. 7D 24 |jge short 002110C8
- 002110A4 |. 8B7424 14 |mov esi, dword ptr [esp+14] ; esi=第1个参数
- 002110A8 |. 8A1C37 |mov bl, byte ptr [edi+esi] ; 取第1个数组下标为edi的值
- 002110AB |. 3A1C2A |cmp bl, byte ptr [edx+ebp] ; 与第2个数组下标为edx的值比较
- 002110AE |. 75 03 |jnz short 002110B3
- 002110B0 |. 47 |inc edi ; 下标自增
- 002110B1 |. EB 0E |jmp short 002110C1
- 002110B3 |> 85D2 |test edx, edx
- 002110B5 |. 75 03 |jnz short 002110BA
- 002110B7 |. 47 |inc edi
- 002110B8 |. EB 08 |jmp short 002110C2
- 002110BA |> 0FBE92 6F3321>|movsx edx, byte ptr [edx+21336F] ; edx=faile[edx]
- 002110C1 |> 42 |inc edx ; 下标自增
- 002110C2 |> 3BF8 |cmp edi, eax
- 002110C4 |.^ 7C DA \jl short 002110A0
- 002110C6 |> 3BD1 cmp edx, ecx
- 002110C8 |> 75 09 jnz short 002110D3 ; 这里2种返回情况其实就是len2==edx?edi-len2:-1;
- 002110CA |. 2BF9 sub edi, ecx
- 002110CC |. 8BC7 mov eax, edi
- 002110CE |. 5F pop edi
- 002110CF |. 5E pop esi
- 002110D0 |. 5D pop ebp
- 002110D1 |. 5B pop ebx
- 002110D2 |. C3 retn
- 002110D3 |> 5F pop edi
- 002110D4 |. 5E pop esi
- 002110D5 |. 5D pop ebp
- 002110D6 |. 83C8 FF or eax, FFFFFFFF
- 002110D9 |. 5B pop ebx
- 002110DA \. C3 retn
- 失配数组获得函数failure
- 00211000 >/$ 8BC6 mov eax, esi ; esi中存储模式串地址
- 00211002 |. 8D50 01 lea edx, dword ptr [eax+1]
- 00211005 |> 8A08 /mov cl, byte ptr [eax]
- 00211007 |. 40 |inc eax
- 00211008 |. 84C9 |test cl, cl
- 0021100A |.^ 75 F9 \jnz short 00211005
- 0021100C |. 2BC2 sub eax, edx ; 上面几个指令到这里获得字符串长度
- 0021100E |. 57 push edi
- 0021100F |. 8BF8 mov edi, eax
- 00211011 |. B9 01000000 mov ecx, 1
- 00211016 |. 3BF9 cmp edi, ecx ; if (len>1)
- 00211018 |. C605 70332100>mov byte ptr [fail], 0FF ; fail[0]=-1
- 0021101F |. 7E 3D jle short 0021105E
- 00211021 |> 0FBE81 6F3321>/movsx eax, byte ptr [ecx+21336F] ; eax=fail[ecx-1]
- 00211028 |. 8A1431 |mov dl, byte ptr [ecx+esi]
- 0021102B |. 385406 01 |cmp byte ptr [esi+eax+1], dl ; if a[eax+1]!=a[ecx]
- 0021102F |. 74 17 |je short 00211048
- 00211031 |> 85C0 |/test eax, eax
- 00211033 |. 7C 0D ||jl short 00211042
- 00211035 |. 0FBE80 703321>||movsx eax, byte ptr [eax+fail]
- 0021103C |. 385406 01 ||cmp byte ptr [esi+eax+1], dl
- 00211040 |.^ 75 EF |\jnz short 00211031 ; while(eax>0) eax=fail[eax];if(a[eax+1]==a[ecx]) break;
- 00211042 |> 385406 01 |cmp byte ptr [esi+eax+1], dl
- 00211046 |. 75 0A |jnz short 00211052
- 00211048 |> FEC0 |inc al
- 0021104A |. 8881 70332100 |mov byte ptr [ecx+fail], al ; fail[ecx]=eax+1
- 00211050 |. EB 07 |jmp short 00211059
- 00211052 |> C681 70332100>|mov byte ptr [ecx+fail], 0FF ; fail[ecx]=-1
- 00211059 |> 41 |inc ecx
- 0021105A |. 3BCF |cmp ecx, edi
- 0021105C |.^ 7C C3 \jl short 00211021 ; for(ecx=1;ecx<len;ecx++)
- 0021105E |> 5F pop edi
- 0021105F \. C3 retn
逆向之hanoi塔
没耐心逆复杂的了,就搞搞这个递归的
版本:Release优化选项:O2
调试工具:OD
源码:
- //Hanoi塔(递归版本)
- #include <stdio.h>
- #include <stdlib.h>
- #define Tower1 1
- #define Tower2 2
- #define Tower3 3
- void towers_of_hanoi(int, int, int, int);
- int main(){
- int n_disks;
- printf("Number of disks: ");
- scanf("%d", &n_disks);
- printf("Disk, source, and destination towers listed below\n");
- printf("%12s%10s%15s\n", "Disk No", "Source","Destination");
- towers_of_hanoi(n_disks,Tower1,Tower3,Tower2);
- system("pause");
- return 0;
- }
- void towers_of_hanoi(int n_disks, int source, int dest, int spare){
- if (n_disks == 1 )
- printf("%10d%10d%10d\n", n_disks, source, dest);
- else {
- /*move a disk from source to spare*/
- towers_of_hanoi(n_disks-1,source,spare,dest);
- printf("%10d%10d%10d\n", n_disks, source, dest);
- /*move a disk from spare to destination tower*/
- towers_of_hanoi(n_disks-1,spare,dest,source);
- }
- }
- towers_of_hanoi函数,这里的递归经过优化后不太清楚。。。
- 01211061 |. 8B7424 08 mov esi, dword ptr [esp+8] ; 第一个参数,即盘子数
- 01211065 |. 57 push edi
- 01211066 |. 8B7C24 10 mov edi, dword ptr [esp+10] ; 第2个参数
- 0121106A |. 83FE 01 cmp esi, 1
- 0121106D |. 74 3A je short 012110A9 ; 盘子数等于1
- 0121106F |. 53 push ebx
- 01211070 |. 55 push ebp
- 01211071 |. 8B6C24 20 mov ebp, dword ptr [esp+20] ; 第4个参数
- 01211075 |> 8B4424 1C /mov eax, dword ptr [esp+1C] ; 第3个参数
- 01211079 |. 50 |push eax ; 假设原函数f(a,b,c,d),那么这里的调用就是f(a,b,d,c)
- 0121107A |. 55 |push ebp
- 0121107B |. 8D5E FF |lea ebx, dword ptr [esi-1]
- 0121107E |. 57 |push edi
- 0121107F |. 53 |push ebx ; ebx=esi-1
- 01211080 |. E8 DBFFFFFF |call towers_of_hanoi ; 代码中只递归一次,另外一次被优化掉了,优化成这个循环
- 01211085 |. 8B4C24 2C |mov ecx, dword ptr [esp+2C]
- 01211089 |. 51 |push ecx ; /<%10d>
- 0121108A |. 57 |push edi ; |<%10d>
- 0121108B |. 56 |push esi ; |<%10d>
- 0121108C |. 68 74212101 |push 01212174 ; |format = "%10d%10d%10d",LF,""
- 01211091 |. FF15 9C202101 |call dword ptr [<&MSVCR90.printf>] ; \printf
- 01211097 |. 8BC7 |mov eax, edi ; 这里交换参数准备下一次调用也就是f(a,d,c,b)
- 01211099 |. 8BF3 |mov esi, ebx ; esi=esi-1作为下一次判断条件
- 0121109B |. 83C4 20 |add esp, 20
- 0121109E |. 8BFD |mov edi, ebp
- 012110A0 |. 8BE8 |mov ebp, eax
- 012110A2 |. 83FE 01 |cmp esi, 1
- 012110A5 |.^ 75 CE \jnz short 01211075
- 012110A7 |. 5D pop ebp
- 012110A8 |. 5B pop ebx
- 012110A9 |> 8B5424 14 mov edx, dword ptr [esp+14] ; 第3个参数
- 012110AD |. 52 push edx ; /<%10d>
- 012110AE |. 57 push edi ; |<%10d>
- 012110AF |. 56 push esi ; |<%10d>
- 012110B0 |. 68 74212101 push 01212174 ; |format = "%10d%10d%10d",LF,""
- 012110B5 |. FF15 9C202101 call dword ptr [<&MSVCR90.printf>] ; \printf
- 012110BB |. 83C4 10 add esp, 10
- 012110BE |. 5F pop edi
- 012110BF |. 5E pop esi
- 012110C0 \. C3 retn
//Hanoi塔(递归版本)#include <stdio.h>#include <stdlib.h>#define Tower1 1#define Tower2 2#define Tower3 3void towers_of_hanoi(int, int, int, int);int main(){int n_disks;printf("Number of disks: "); scanf("%d", &n_disks);printf("Disk, source, and destination towers listed below\n"); printf("%12s%10s%15s\n", "Disk No", "Source","Destination"); towers_of_hanoi(n_disks,Tower1,Tower3,Tower2);system("pause");return 0;}void towers_of_hanoi(int n_disks, int source, int dest, int spare){ if (n_disks == 1 ) printf("%10d%10d%10d\n", n_disks, source, dest); else { /*move a disk from source to spare*/ towers_of_hanoi(n_disks-1,source,spare,dest); printf("%10d%10d%10d\n", n_disks, source, dest); /*move a disk from spare to destination tower*/ towers_of_hanoi(n_disks-1,spare,dest,source); }}towers_of_hanoi函数,这里的递归经过优化后不太清楚。。。01211061 |. 8B7424 08 mov esi, dword ptr [esp+8] ; 第一个参数,即盘子数01211065 |. 57 push edi01211066 |. 8B7C24 10 mov edi, dword ptr [esp+10] ; 第2个参数0121106A |. 83FE 01 cmp esi, 10121106D |. 74 3A je short 012110A9 ; 盘子数等于10121106F |. 53 push ebx01211070 |. 55 push ebp01211071 |. 8B6C24 20 mov ebp, dword ptr [esp+20] ; 第4个参数01211075 |> 8B4424 1C /mov eax, dword ptr [esp+1C] ; 第3个参数01211079 |. 50 |push eax ; 假设原函数f(a,b,c,d),那么这里的调用就是f(a,b,d,c)0121107A |. 55 |push ebp0121107B |. 8D5E FF |lea ebx, dword ptr [esi-1]0121107E |. 57 |push edi0121107F |. 53 |push ebx ; ebx=esi-101211080 |. E8 DBFFFFFF |call towers_of_hanoi ; 代码中只递归一次,另外一次被优化掉了,优化成这个循环01211085 |. 8B4C24 2C |mov ecx, dword ptr [esp+2C]01211089 |. 51 |push ecx ; /<%10d>0121108A |. 57 |push edi ; |<%10d>0121108B |. 56 |push esi ; |<%10d>0121108C |. 68 74212101 |push 01212174 ; |format = "%10d%10d%10d",LF,""01211091 |. FF15 9C202101 |call dword ptr [<&MSVCR90.printf>] ; \printf01211097 |. 8BC7 |mov eax, edi ; 这里交换参数准备下一次调用也就是f(a,d,c,b)01211099 |. 8BF3 |mov esi, ebx ; esi=esi-1作为下一次判断条件0121109B |. 83C4 20 |add esp, 200121109E |. 8BFD |mov edi, ebp012110A0 |. 8BE8 |mov ebp, eax012110A2 |. 83FE 01 |cmp esi, 1012110A5 |.^ 75 CE \jnz short 01211075012110A7 |. 5D pop ebp012110A8 |. 5B pop ebx012110A9 |> 8B5424 14 mov edx, dword ptr [esp+14] ; 第3个参数012110AD |. 52 push edx ; /<%10d>012110AE |. 57 push edi ; |<%10d>012110AF |. 56 push esi ; |<%10d>012110B0 |. 68 74212101 push 01212174 ; |format = "%10d%10d%10d",LF,""012110B5 |. FF15 9C202101 call dword ptr [<&MSVCR90.printf>] ; \printf012110BB |. 83C4 10 add esp, 10012110BE |. 5F pop edi012110BF |. 5E pop esi012110C0 \. 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)其实就跟优化后的循环调用一样了,使得所有的第二次递归都变成了第一次递归的样子,语言比较难描述。。。
贴完了。。。
- 逆向之KMP算法 ;逆向之hanoi塔
- 第九篇:逆向之hanoi塔
- 第八篇:逆向之KMP算法
- 逆向之hash算法 ,逆向之选择排序 ,逆向之快速排序
- 第一篇:逆向之hash算法
- {软件工程}之逆向工程
- IOS逆向之旅
- Mybaits之逆向工程
- Mybatis之逆向工程
- Mybatis之逆向工程
- Mybatis之逆向工程
- 中文分词算法之最大逆向匹配法
- 逆向分析之定位算法的一些经验
- 链表操作法则之逆向遍历与倒置算法
- 算法练习之(任意长度字符串逆向输出)
- NLP之逆向最大匹配算法(BMM)
- 网站逆向分析js之RSA算法原理
- 逆向之堆排序 ,逆向之二路归并排序
- Linux TCP 连接数修改
- 12/9/16 成都网赛 总结
- 标准输入,标准输出和标准出错的缓冲
- 文件大小
- 青蛙又回到了井里
- 逆向之KMP算法 ;逆向之hanoi塔
- lesson1_02
- H264 常见问题(zz from chinavideo)
- Win平台高级编程:完成端口 (IOCP) serial functions
- 数据库: 左连接/右连接/全连接(详细) --复习一下
- OSIP协议栈使用入门(续一:纯协议栈逻辑分析)(转)
- lesson1_03 adapter
- Java编程中写出好代码的建议
- 螺旋打印数组