逆向分析之LSD基数排序 ;逆向之循环数组队列
来源:互联网 发布:阻抗匹配网络 编辑:程序博客网 时间:2024/04/30 04:57
逆向分析之LSD基数排序
版本:Release
优化选项:O2
调试工具:OD
源码:
- //LSD基数排序(桶排序,模拟队列实现)
- #include <stdio.h>
- #include <stdlib.h>
- #include <time.h>
- #define MAX_SIZE 11 //PS:set nodes number
- void listsort(int a[],int link[],int n,int first);
- int digit(int a,int i,int r)
- {
- int n=2-i;
- while(n>0&&(a/=r))
- n--;
- a%=10;
- return a;
- }
- int radixsort(int a[],int link[],int d,int r,int n)
- {
- int i,last,first=1,bin,current;
- int front[10],rear[10];//10个桶
- for(i=1;i<n;i++)
- link[i]=i+1;
- link[n]=0;
- for(i=d-1;i>=0;i--)//对相应位排序入桶
- {
- for(bin=0;bin<r;bin++)
- {
- front[bin]=0;
- rear[bin]=0;
- }
- for(current=first;current;current=link[current])
- {
- bin=digit(a[current],i,r);//取相应位的数字
- if(front[bin]==0)
- front[bin]=current;
- else
- link[rear[bin]]=current;
- rear[bin]=current;
- }
- for(bin=0;!front[bin];bin++)
- ;
- first=front[bin];
- last=rear[bin];
- for(bin++;bin<r;bin++)//将各桶连接
- if(front[bin])
- {
- link[last]=front[bin];
- last=rear[bin];
- }
- link[last]=0;
- }
- return first;
- }
- int main()
- {
- int i,first,current;
- int a[MAX_SIZE];
- int link[MAX_SIZE];
- srand((unsigned)time(0));
- for(i=1;i<MAX_SIZE;i++)
- a[i]=rand()%1000;
- for(i=1;i<MAX_SIZE;i++)
- printf("%4d",a[i]);
- putchar('\n');
- first=radixsort(a,link,3,10,10);
- for(current=first;current;current=link[current])
- printf("%4d",a[current]);
- /*
- listsort(a,link,MAX_SIZE,first);
- for(i=1;i<MAX_SIZE;i++)
- printf("%4d",a[i]);
- 链表记录重放*/
- system("pause");
- return 0;
- }
- /*
- void listsort(int a[],int link[],int n,int first)//链表记录重放
- {
- int q,i,temp;
- for(i=1;i<n;i++)
- {
- while(first<i) first=link[first];
- q=link[first];
- if(first!=n)
- {
- SWAP(a[i],a[first],temp);
- link[first]=link[i];
- link[i]=first;
- }
- first=q;
- }
- }
- */
- 主函数就不贴了,很简单
- 这里贴上主要的排序函数,在下面的代码中假设不知道源码的情况下,我假设了4个int [10]大小的数组,其中2个是参数a[10],b[10],2个是函数内的局部变量c[10],d[10]
- 01231000 >/$ 83EC 50 sub esp, 50 ; 此时eax中存放着待排序数组a[10],ebx存放另一个数组b[10]
- 01231003 |. 55 push ebp
- 01231004 |. 56 push esi
- 01231005 |. 33ED xor ebp, ebp
- 01231007 |. C743 04 02000>mov dword ptr [ebx+4], 2 ; 初始化第二个数组
- 0123100E |. C743 08 03000>mov dword ptr [ebx+8], 3
- 01231015 |. C743 0C 04000>mov dword ptr [ebx+C], 4
- 0123101C |. C743 10 05000>mov dword ptr [ebx+10], 5
- 01231023 |. C743 14 06000>mov dword ptr [ebx+14], 6
- 0123102A |. C743 18 07000>mov dword ptr [ebx+18], 7
- 01231031 |. C743 1C 08000>mov dword ptr [ebx+1C], 8
- 01231038 |. C743 20 09000>mov dword ptr [ebx+20], 9
- 0123103F |. C743 24 0A000>mov dword ptr [ebx+24], 0A
- 01231046 |. 57 push edi
- 01231047 |. B8 01000000 mov eax, 1
- 0123104C |. 896B 28 mov dword ptr [ebx+28], ebp
- 0123104F |. 90 nop
- 01231050 |> 33C9 /xor ecx, ecx ; 这可是个大循环啊~~~先初始化所有的临时变量b[10],c[10]
- 01231052 |. 894C24 34 |mov dword ptr [esp+34], ecx
- 01231056 |. 894C24 38 |mov dword ptr [esp+38], ecx
- 0123105A |. 894C24 3C |mov dword ptr [esp+3C], ecx
- 0123105E |. 894C24 40 |mov dword ptr [esp+40], ecx
- 01231062 |. 894C24 44 |mov dword ptr [esp+44], ecx
- 01231066 |. 894C24 48 |mov dword ptr [esp+48], ecx
- 0123106A |. 894C24 4C |mov dword ptr [esp+4C], ecx
- 0123106E |. 894C24 50 |mov dword ptr [esp+50], ecx
- 01231072 |. 894C24 54 |mov dword ptr [esp+54], ecx
- 01231076 |. 894C24 58 |mov dword ptr [esp+58], ecx
- 0123107A |. 894C24 0C |mov dword ptr [esp+C], ecx
- 0123107E |. 894C24 10 |mov dword ptr [esp+10], ecx
- 01231082 |. 894C24 14 |mov dword ptr [esp+14], ecx
- 01231086 |. 894C24 18 |mov dword ptr [esp+18], ecx
- 0123108A |. 894C24 1C |mov dword ptr [esp+1C], ecx
- 0123108E |. 894C24 20 |mov dword ptr [esp+20], ecx
- 01231092 |. 894C24 24 |mov dword ptr [esp+24], ecx
- 01231096 |. 894C24 28 |mov dword ptr [esp+28], ecx
- 0123109A |. 894C24 2C |mov dword ptr [esp+2C], ecx
- 0123109E |. 894C24 30 |mov dword ptr [esp+30], ecx
- 012310A2 |. 8BF0 |mov esi, eax
- 012310A4 |. 85C0 |test eax, eax
- 012310A6 |. 74 67 |je short 0123110F ;在下面这个循环凡是用到ebx的取内存数据都是类似b[ecx],凡是用到esp的都是取临时数组c[ecx] d[ecx]此类
- 012310A8 |. EB 06 |jmp short 012310B0
- 012310AA | 8D9B 00000000 |lea ebx, dword ptr [ebx]
- 012310B0 |> 8B4424 60 |/mov eax, dword ptr [esp+60] ; 传进来的参数,存的是待排序数组地址
- 012310B4 |. 8B0CB0 ||mov ecx, dword ptr [eax+esi*4]
- 012310B7 |. 8BFD ||mov edi, ebp
- 012310B9 |. 85ED ||test ebp, ebp
- 012310BB |. 7E 1B ||jle short 012310D8
- 012310BD |. 8D49 00 ||lea ecx, dword ptr [ecx]
- 012310C0 |> B8 67666666 ||/mov eax, 66666667 ;下面几个是除法优化后的指令(ecx/10),如果不明白可以参考第一篇hash逆向,里面有更详细的解释
- 012310C5 |. F7E9 |||imul ecx
- 012310C7 |. C1FA 02 |||sar edx, 2
- 012310CA |. 8BCA |||mov ecx, edx
- 012310CC |. C1E9 1F |||shr ecx, 1F
- 012310CF |. 03CA |||add ecx, edx ;截至到这里就取得了除法的商
- 012310D1 |. 74 05 |||je short 012310D8
- 012310D3 |. 4F |||dec edi
- 012310D4 |. 85FF |||test edi, edi
- 012310D6 |.^ 7F E8 ||\jg short 012310C0
- 012310D8 |> B8 67666666 ||mov eax, 66666667 ;依然是除法优化,ecx/10
- 012310DD |. F7E9 ||imul ecx
- 012310DF |. C1FA 02 ||sar edx, 2
- 012310E2 |. 8BC2 ||mov eax, edx
- 012310E4 |. C1E8 1F ||shr eax, 1F
- 012310E7 |. 03C2 ||add eax, edx
- 012310E9 |. 8D1480 ||lea edx, dword ptr [eax+eax*4]
- 012310EC |. 03D2 ||add edx, edx
- 012310EE |. 2BCA ||sub ecx, edx ; 这里应该是得到指定位数字的结果吧,前面先不管了看不懂这种优化。。
- 012310F0 |. 837C8C 0C 00 ||cmp dword ptr [esp+ecx*4+C], 0 ; 下面几句大体上是这样if(c[ecx]==0) c[ecx]=esi; else b[d[ecx]]=esi;
- 012310F5 |. 75 06 ||jnz short 012310FD
- 012310F7 |. 89748C 0C ||mov dword ptr [esp+ecx*4+C], esi
- 012310FB |. EB 07 ||jmp short 01231104
- 012310FD |> 8B448C 34 ||mov eax, dword ptr [esp+ecx*4+34]
- 01231101 |. 893483 ||mov dword ptr [ebx+eax*4], esi
- 01231104 |> 89748C 34 ||mov dword ptr [esp+ecx*4+34], esi
- 01231108 |. 8B34B3 ||mov esi, dword ptr [ebx+esi*4]
- 0123110B |. 85F6 ||test esi, esi ; 这个比较大的循环里整体浏览下也可以发现esi是循环判断条件,但esi又牵扯到前面几个指令,其中又有我们暂时不知道干嘛的寄存器,于是可以先把架子写出来加上注释,等弄懂内部循环后再来修改也行
- 0123110D |.^ 75 A1 |\jnz short 012310B0
- 0123110F |> 33C9 |xor ecx, ecx
- 01231111 |. 394C24 0C |cmp dword ptr [esp+C], ecx
- 01231115 |. 75 08 |jnz short 0123111F
- 01231117 |> 41 |/inc ecx
- 01231118 |. 837C8C 0C 00 ||cmp dword ptr [esp+ecx*4+C], 0
- 0123111D |.^ 74 F8 |\je short 01231117
- 0123111F |> 8B448C 0C |mov eax, dword ptr [esp+ecx*4+C]
- 01231123 |. 8B548C 34 |mov edx, dword ptr [esp+ecx*4+34]
- 01231127 |. 41 |inc ecx
- 01231128 |. 83F9 0A |cmp ecx, 0A
- 0123112B |. 7D 1B |jge short 01231148
- 0123112D |. 03C9 |add ecx, ecx
- 0123112F |. 03C9 |add ecx, ecx
- 01231131 |> 8B7C0C 0C |/mov edi, dword ptr [esp+ecx+C]
- 01231135 |. 85FF ||test edi, edi
- 01231137 |. 74 07 ||je short 01231140
- 01231139 |. 893C93 ||mov dword ptr [ebx+edx*4], edi
- 0123113C |. 8B540C 34 ||mov edx, dword ptr [esp+ecx+34]
- 01231140 |> 83C1 04 ||add ecx, 4
- 01231143 |. 83F9 28 ||cmp ecx, 28
- 01231146 |.^ 7C E9 |\jl short 01231131
- 01231148 |> 45 |inc ebp
- 01231149 |. 83FD 02 |cmp ebp, 2 ; 这里ebp为判断条件并且可以发现没有地方改变ebp的值,于是整个for框架可以直接写出来了
- 0123114C |. C70493 000000>|mov dword ptr [ebx+edx*4], 0
- 01231153 |.^ 0F8E F7FEFFFF \jle 01231050
- 01231159 |. 5F pop edi
- 0123115A |. 5E pop esi
- 0123115B |. 5D pop ebp
- 0123115C |. 83C4 50 add esp, 50
- 0123115F \. C3 retn
//LSD基数排序(桶排序,模拟队列实现)#include <stdio.h>#include <stdlib.h>#include <time.h>#define MAX_SIZE 11 //PS:set nodes numbervoid listsort(int a[],int link[],int n,int first);int digit(int a,int i,int r){int n=2-i;while(n>0&&(a/=r))n--;a%=10;return a;}int radixsort(int a[],int link[],int d,int r,int n){int i,last,first=1,bin,current;int front[10],rear[10];//10个桶for(i=1;i<n;i++)link[i]=i+1;link[n]=0;for(i=d-1;i>=0;i--)//对相应位排序入桶{for(bin=0;bin<r;bin++){front[bin]=0;rear[bin]=0;}for(current=first;current;current=link[current]){bin=digit(a[current],i,r);//取相应位的数字if(front[bin]==0)front[bin]=current;elselink[rear[bin]]=current;rear[bin]=current;}for(bin=0;!front[bin];bin++);first=front[bin];last=rear[bin];for(bin++;bin<r;bin++)//将各桶连接if(front[bin]){link[last]=front[bin];last=rear[bin];}link[last]=0;}return first;}int main(){int i,first,current;int a[MAX_SIZE];int link[MAX_SIZE];srand((unsigned)time(0));for(i=1;i<MAX_SIZE;i++)a[i]=rand()%1000;for(i=1;i<MAX_SIZE;i++)printf("%4d",a[i]);putchar('\n');first=radixsort(a,link,3,10,10);for(current=first;current;current=link[current])printf("%4d",a[current]);/*listsort(a,link,MAX_SIZE,first);for(i=1;i<MAX_SIZE;i++)printf("%4d",a[i]);链表记录重放*/system("pause");return 0;}/*void listsort(int a[],int link[],int n,int first)//链表记录重放{int q,i,temp;for(i=1;i<n;i++){while(first<i) first=link[first];q=link[first];if(first!=n){SWAP(a[i],a[first],temp);link[first]=link[i];link[i]=first;}first=q;}}*/主函数就不贴了,很简单这里贴上主要的排序函数,在下面的代码中假设不知道源码的情况下,我假设了4个int [10]大小的数组,其中2个是参数a[10],b[10],2个是函数内的局部变量c[10],d[10]01231000 >/$ 83EC 50 sub esp, 50 ; 此时eax中存放着待排序数组a[10],ebx存放另一个数组b[10]01231003 |. 55 push ebp01231004 |. 56 push esi01231005 |. 33ED xor ebp, ebp01231007 |. C743 04 02000>mov dword ptr [ebx+4], 2 ; 初始化第二个数组0123100E |. C743 08 03000>mov dword ptr [ebx+8], 301231015 |. C743 0C 04000>mov dword ptr [ebx+C], 40123101C |. C743 10 05000>mov dword ptr [ebx+10], 501231023 |. C743 14 06000>mov dword ptr [ebx+14], 60123102A |. C743 18 07000>mov dword ptr [ebx+18], 701231031 |. C743 1C 08000>mov dword ptr [ebx+1C], 801231038 |. C743 20 09000>mov dword ptr [ebx+20], 90123103F |. C743 24 0A000>mov dword ptr [ebx+24], 0A01231046 |. 57 push edi01231047 |. B8 01000000 mov eax, 10123104C |. 896B 28 mov dword ptr [ebx+28], ebp0123104F |. 90 nop01231050 |> 33C9 /xor ecx, ecx ; 这可是个大循环啊~~~先初始化所有的临时变量b[10],c[10]01231052 |. 894C24 34 |mov dword ptr [esp+34], ecx01231056 |. 894C24 38 |mov dword ptr [esp+38], ecx0123105A |. 894C24 3C |mov dword ptr [esp+3C], ecx0123105E |. 894C24 40 |mov dword ptr [esp+40], ecx01231062 |. 894C24 44 |mov dword ptr [esp+44], ecx01231066 |. 894C24 48 |mov dword ptr [esp+48], ecx0123106A |. 894C24 4C |mov dword ptr [esp+4C], ecx0123106E |. 894C24 50 |mov dword ptr [esp+50], ecx01231072 |. 894C24 54 |mov dword ptr [esp+54], ecx01231076 |. 894C24 58 |mov dword ptr [esp+58], ecx0123107A |. 894C24 0C |mov dword ptr [esp+C], ecx0123107E |. 894C24 10 |mov dword ptr [esp+10], ecx01231082 |. 894C24 14 |mov dword ptr [esp+14], ecx01231086 |. 894C24 18 |mov dword ptr [esp+18], ecx0123108A |. 894C24 1C |mov dword ptr [esp+1C], ecx0123108E |. 894C24 20 |mov dword ptr [esp+20], ecx01231092 |. 894C24 24 |mov dword ptr [esp+24], ecx01231096 |. 894C24 28 |mov dword ptr [esp+28], ecx0123109A |. 894C24 2C |mov dword ptr [esp+2C], ecx0123109E |. 894C24 30 |mov dword ptr [esp+30], ecx012310A2 |. 8BF0 |mov esi, eax012310A4 |. 85C0 |test eax, eax012310A6 |. 74 67 |je short 0123110F ;在下面这个循环凡是用到ebx的取内存数据都是类似b[ecx],凡是用到esp的都是取临时数组c[ecx] d[ecx]此类012310A8 |. EB 06 |jmp short 012310B0012310AA | 8D9B 00000000 |lea ebx, dword ptr [ebx]012310B0 |> 8B4424 60 |/mov eax, dword ptr [esp+60] ; 传进来的参数,存的是待排序数组地址012310B4 |. 8B0CB0 ||mov ecx, dword ptr [eax+esi*4]012310B7 |. 8BFD ||mov edi, ebp012310B9 |. 85ED ||test ebp, ebp012310BB |. 7E 1B ||jle short 012310D8012310BD |. 8D49 00 ||lea ecx, dword ptr [ecx]012310C0 |> B8 67666666 ||/mov eax, 66666667 ;下面几个是除法优化后的指令(ecx/10),如果不明白可以参考第一篇hash逆向,里面有更详细的解释012310C5 |. F7E9 |||imul ecx012310C7 |. C1FA 02 |||sar edx, 2012310CA |. 8BCA |||mov ecx, edx012310CC |. C1E9 1F |||shr ecx, 1F012310CF |. 03CA |||add ecx, edx ;截至到这里就取得了除法的商012310D1 |. 74 05 |||je short 012310D8012310D3 |. 4F |||dec edi012310D4 |. 85FF |||test edi, edi012310D6 |.^ 7F E8 ||\jg short 012310C0012310D8 |> B8 67666666 ||mov eax, 66666667 ;依然是除法优化,ecx/10012310DD |. F7E9 ||imul ecx012310DF |. C1FA 02 ||sar edx, 2012310E2 |. 8BC2 ||mov eax, edx012310E4 |. C1E8 1F ||shr eax, 1F012310E7 |. 03C2 ||add eax, edx012310E9 |. 8D1480 ||lea edx, dword ptr [eax+eax*4]012310EC |. 03D2 ||add edx, edx012310EE |. 2BCA ||sub ecx, edx ; 这里应该是得到指定位数字的结果吧,前面先不管了看不懂这种优化。。012310F0 |. 837C8C 0C 00 ||cmp dword ptr [esp+ecx*4+C], 0 ; 下面几句大体上是这样if(c[ecx]==0) c[ecx]=esi; else b[d[ecx]]=esi;012310F5 |. 75 06 ||jnz short 012310FD012310F7 |. 89748C 0C ||mov dword ptr [esp+ecx*4+C], esi012310FB |. EB 07 ||jmp short 01231104012310FD |> 8B448C 34 ||mov eax, dword ptr [esp+ecx*4+34]01231101 |. 893483 ||mov dword ptr [ebx+eax*4], esi01231104 |> 89748C 34 ||mov dword ptr [esp+ecx*4+34], esi01231108 |. 8B34B3 ||mov esi, dword ptr [ebx+esi*4]0123110B |. 85F6 ||test esi, esi ; 这个比较大的循环里整体浏览下也可以发现esi是循环判断条件,但esi又牵扯到前面几个指令,其中又有我们暂时不知道干嘛的寄存器,于是可以先把架子写出来加上注释,等弄懂内部循环后再来修改也行0123110D |.^ 75 A1 |\jnz short 012310B00123110F |> 33C9 |xor ecx, ecx01231111 |. 394C24 0C |cmp dword ptr [esp+C], ecx01231115 |. 75 08 |jnz short 0123111F01231117 |> 41 |/inc ecx01231118 |. 837C8C 0C 00 ||cmp dword ptr [esp+ecx*4+C], 00123111D |.^ 74 F8 |\je short 012311170123111F |> 8B448C 0C |mov eax, dword ptr [esp+ecx*4+C]01231123 |. 8B548C 34 |mov edx, dword ptr [esp+ecx*4+34]01231127 |. 41 |inc ecx01231128 |. 83F9 0A |cmp ecx, 0A0123112B |. 7D 1B |jge short 012311480123112D |. 03C9 |add ecx, ecx0123112F |. 03C9 |add ecx, ecx01231131 |> 8B7C0C 0C |/mov edi, dword ptr [esp+ecx+C]01231135 |. 85FF ||test edi, edi01231137 |. 74 07 ||je short 0123114001231139 |. 893C93 ||mov dword ptr [ebx+edx*4], edi0123113C |. 8B540C 34 ||mov edx, dword ptr [esp+ecx+34]01231140 |> 83C1 04 ||add ecx, 401231143 |. 83F9 28 ||cmp ecx, 2801231146 |.^ 7C E9 |\jl short 0123113101231148 |> 45 |inc ebp01231149 |. 83FD 02 |cmp ebp, 2 ; 这里ebp为判断条件并且可以发现没有地方改变ebp的值,于是整个for框架可以直接写出来了0123114C |. C70493 000000>|mov dword ptr [ebx+edx*4], 001231153 |.^ 0F8E F7FEFFFF \jle 0123105001231159 |. 5F pop edi0123115A |. 5E pop esi0123115B |. 5D pop ebp0123115C |. 83C4 50 add esp, 500123115F \. C3 retn
注释不多,不过我想说说逆向这个函数的时候的我的方法
首先浏览下所有的跳转,清楚哪些跳转跳向哪里,然后观察一些条件判断用到的寄存器,回溯看看有没有在其他地方用到他而不用管他到底做了什么,如果只在判断处用到了的话最好了那么直接用个变量代替寄存器就能写出这个循环的整体架子,然后逐步深入,诸如if else类的跳转也可以先写出来而不用管其内部指令干了什么,就像造房子的时候先把它的架子给搞出来,之后内部再慢慢添砖加瓦,我们可以先对函数有个模糊的架子印象然后再去纠结这个函数到底做了什么
我以前也干过像把寄存器记在纸上逐条翻译指令最后再整理出结果这样纯粹蛮力的逆向一个函数,至于怎样做更效率更准确我也不好说,只能说我个人觉得有技巧性的逆向更好,学到的也更多
下面我再把边逆向边还原出的代码贴上来,应该也能看出点门道吧嗯~~~~~
- int eax=1;int c[10] d[10]
- for (int i=0;i<=2;i++,b[edx]=0)
- {
- esi=eax;
- for(esi=eax;esi;esi=b[esi])
- {
- ecx=a[esi];
- 取得特定位于ecx
- if(c[ecx]==0)
- {
- c[ecx]=esi;
- }
- else
- {
- b[ d[ecx] ]=esi;
- }
- d[ecx]=esi;
- }
- for(x=c[ecx=0];!x;ecx++)
- ;
- eax=c[ecx];edx=d[ecx];
- ecx++;
- for(;ecx<10;ecx++)
- {
- if(c[ecx])
- {
- b[edx]=c[ecx];
- edx=d[ecx];
- }
- }
- }
逆向之循环数组队列
由于最近看了点除法优化的东西,这里就特意逆一个用取模比较多的程序吧,权当熟悉
版本:Release
优化选项:O2
调试工具:OD
源码:
- #include <stdio.h>
- #include <stdlib.h>
- #define FALSE 0
- #define TRUE 1
- #define MAX_SIZE 6
- int capacity=MAX_SIZE;
- enum {EXIT,ADD,DEL,SHOW};
- typedef struct
- {
- int element;
- }queue;
- queue q[MAX_SIZE];
- int front=-1,rear=-1;
- int isempty()
- {
- return rear%capacity==(front+capacity)%capacity;
- }
- int isfull()
- {
- return (rear+1)%capacity==(front+capacity)%capacity;
- }
- int addq(int element)
- {
- if(isfull()==TRUE)
- {
- fprintf(stderr,"queue is full,auto redouble...\n");
- return FALSE;
- //redouble();
- }
- rear=(rear+1)%capacity;
- q[rear].element=element;
- return TRUE;
- }
- int deleteq()
- {
- if(isempty())
- {
- fprintf(stderr,"empty");
- return FALSE;
- }
- front=(front+1)%capacity;
- return TRUE;
- }
- void show()
- {
- int i;
- if(isempty()==TRUE)
- {
- printf("empty\n");
- return;
- }
- for(i=front+1;i!=(rear+1)%capacity;i=(i+1)%capacity)
- printf("%d\t",q[i].element);
- putchar('\n');
- }
- int main()
- {
- int chose;
- int element;
- while(TRUE)
- {
- printf("ADD 1\nDEL 2\nSHOW 3\nEXIT 0\n");
- printf("please input chose: ");
- scanf("%d",&chose);
- fflush(stdin);
- switch(chose)
- {
- case ADD:
- printf("please input add element :");
- scanf("%d",&element);
- fflush(stdin);
- if(addq(element)==TRUE)
- printf("add success\n");
- else
- printf("add failed...\n");
- break;
- case DEL:
- if(deleteq()==TRUE)
- printf("del success\n");
- else
- printf("del failed\n");
- break;
- case SHOW:
- show();
- break;
- case EXIT:
- return 0;
- default:
- printf("input error\n");
- break;
- }
- }
- system("pause");
- return 0;
- }
- 主函数就把switch case主要跳转代码贴上来,OD自动加上的注释已经很多了就不说
- 00B91130 |> /68 3821B900 /push 00B92138 ; ASCII "ADD 1",LF,"DEL 2",LF,"SHOW 3",LF,"EXIT 0",LF
- ...................................
- ...................................
- 00B9115C |. |83F8 03 |cmp eax, 3 ; Switch (cases 0..3)
- 00B9115F |. |0F87 BB000000 |ja 00B91220
- 00B91165 |. |FF2485 3C12B9>|jmp dword ptr [eax*4+B9123C]
- 00B9116C |> |68 7021B900 |push 00B92170 ; ASCII "please input add element :"; Case 1 of switch 00B9115C
- ..............................
- ..............................
- 00B911EE |> |E8 0DFEFFFF |call deleteq ; Case 2 of switch 00B9115C
- ............................
- ..........................
- 00B91216 |> |E8 55FEFFFF |call show ; Case 3 of switch 00B9115C
- ............................
- ............................
- 00B9122A |.^\E9 01FFFFFF \jmp 00B91130
- 00B9122F ;这里就退出流程了
- 用于case跳转的分支表
- 00B9123C . \2F12B900 dd test.00B9122F ; 分支表 被用于 00B91165
- 00B91240 . 6C11B900 dd test.00B9116C
- 00B91244 . EE11B900 dd test.00B911EE
- 00B91248 . 1612B900 dd test.00B91216
- addq函数代码
- 00B91184 |. A1 2030B900 |mov eax, dword ptr [rear] ; eax=rear
- 00B91189 |. 40 |inc eax ; rear++
- 00B9118A |. 99 |cdq ; 将rear扩展为64位(edx:eax)
- 00B9118B |. B9 06000000 |mov ecx, 6
- 00B91190 |. F7F9 |idiv ecx ; rear/6
- 00B91192 |. A1 1C30B900 |mov eax, dword ptr [front] ; eax=front
- 00B91197 |. 83C0 06 |add eax, 6 ; eax+=6
- 00B9119A |. BD 06000000 |mov ebp, 6
- 00B9119F |. 83C4 10 |add esp, 10
- 00B911A2 |. 8BCA |mov ecx, edx ; 将前面获得的余数存到ecx
- 00B911A4 |. 99 |cdq
- 00B911A5 |. F7FD |idiv ebp ; eax/6
- 00B911A7 |. 3BCA |cmp ecx, edx ; if(ecx!=edx) 将2次获得的余数相比较
- 00B911A9 |. 75 23 |jnz short 00B911CE
- 00B911AB |. 68 0421B900 |push 00B92104 ; ASCII "queue is full,auto redouble...",LF
- 00B911B0 |. FFD7 |call edi
- 00B911B2 |. 83C0 40 |add eax, 40 ; |
- 00B911B5 |. 50 |push eax ; |stream
- 00B911B6 |. FF15 A020B900 |call dword ptr [<&MSVCR90.fprintf>] ; \fprintf
- 00B911BC |. 83C4 08 |add esp, 8
- 00B911BF |. 68 9C21B900 |push 00B9219C ; ASCII "add failed...",LF
- 00B911C4 |. FFD6 |call esi
- 00B911C6 |. 83C4 04 |add esp, 4
- 00B911C9 |.^ E9 62FFFFFF |jmp 00B91130
- 00B911CE |> 8B5424 14 |mov edx, dword ptr [esp+14] ; esp+14处存储的是scanf输入的数
- 00B911D2 |. 68 8C21B900 |push 00B9218C ; ASCII "add success",LF
- 00B911D7 |. 890D 2030B900 |mov dword ptr [rear], ecx ; rear = ecx
- 00B911DD |. 89148D 7C33B9>|mov dword ptr [ecx*4+q], edx ; q[rear]=[esp+14],即真正的入队操作
- 00B911E4 |. FFD6 |call esi
- 下面是deleteq函数
- 00B91000 >/$ 8B0D 2030B900 mov ecx, dword ptr [rear] ; ecx=rear
- 00B91006 |. B8 ABAAAA2A mov eax, 2AAAAAAB ; 下面几个指令是取模优化,这个16进制数用小数方式来计算大概是0.16左右的值,其实源码也就是1/6了
- 00B9100B |. F7E9 imul ecx
- 00B9100D |. 8BC2 mov eax, edx
- 00B9100F |. C1E8 1F shr eax, 1F
- 00B91012 |. 03C2 add eax, edx ; 这里eax即为rear/6的结果
- 00B91014 |. 8D0440 lea eax, dword ptr [eax+eax*2]
- 00B91017 |. 03C0 add eax, eax
- 00B91019 |. 56 push esi
- 00B9101A |. 8B35 1C30B900 mov esi, dword ptr [front]
- 00B91020 |. 2BC8 sub ecx, eax ; 这里ecx才是真正取模的结果
- 00B91022 |. 8D46 06 lea eax, dword ptr [esi+6] ; 先加6再取模
- 00B91025 |. 57 push edi
- 00B91026 |. 99 cdq
- 00B91027 |. BF 06000000 mov edi, 6
- 00B9102C |. F7FF idiv edi
- 00B9102E |. 3BCA cmp ecx, edx ; if ((front+6)%6)!=(rear%6)
- 00B91030 |. 75 1D jnz short 00B9104F
- 00B91032 |. 68 2421B900 push 00B92124 ; ASCII "empty"
- 00B91037 |. FF15 AC20B900 call dword ptr [<&MSVCR90.__iob_func>] ; MSVCR90.__p__iob
- 00B9103D |. 83C0 40 add eax, 40 ; |
- 00B91040 |. 50 push eax ; |stream
- 00B91041 |. FF15 A020B900 call dword ptr [<&MSVCR90.fprintf>] ; \fprintf
- 00B91047 |. 83C4 08 add esp, 8
- 00B9104A |. 5F pop edi
- 00B9104B |. 33C0 xor eax, eax
- 00B9104D |. 5E pop esi
- 00B9104E |. C3 retn
- 00B9104F |> 8D46 01 lea eax, dword ptr [esi+1] ; front=(front+1)%6
- 00B91052 |. 99 cdq
- 00B91053 |. 8BCF mov ecx, edi
- 00B91055 |. F7F9 idiv ecx
- 00B91057 |. 5F pop edi
- 00B91058 |. B8 01000000 mov eax, 1
- 00B9105D |. 5E pop esi
- 00B9105E |. 8915 1C30B900 mov dword ptr [front], edx
- 00B91064 \. C3 retn
- 最后一个show函数有兴趣自己看看吧,就加点提示不多注释了
- 00B91070 >/$ 8B0D 2030B900 mov ecx, dword ptr [rear] ; rear%6!=(front+6)%6
- 00B91076 |. B8 ABAAAA2A mov eax, 2AAAAAAB
- 00B9107B |. F7E9 imul ecx
- 00B9107D |. 8BC2 mov eax, edx
- 00B9107F |. C1E8 1F shr eax, 1F
- 00B91082 |. 03C2 add eax, edx
- 00B91084 |. 53 push ebx
- 00B91085 |. 8D0440 lea eax, dword ptr [eax+eax*2]
- 00B91088 |. 56 push esi
- 00B91089 |. 8B35 1C30B900 mov esi, dword ptr [front]
- 00B9108F |. 03C0 add eax, eax
- 00B91091 |. 57 push edi
- 00B91092 |. 8BF9 mov edi, ecx
- 00B91094 |. 2BF8 sub edi, eax
- 00B91096 |. 8D46 06 lea eax, dword ptr [esi+6]
- 00B91099 |. 99 cdq
- 00B9109A |. BB 06000000 mov ebx, 6
- 00B9109F |. F7FB idiv ebx
- 00B910A1 |. 3BFA cmp edi, edx
- 00B910A3 |. 75 12 jnz short 00B910B7
- 00B910A5 |. 68 2C21B900 push 00B9212C ; /format = "empty",LF,""
- 00B910AA |. FF15 A420B900 call dword ptr [<&MSVCR90.printf>] ; \printf
- 00B910B0 |. 83C4 04 add esp, 4
- 00B910B3 |. 5F pop edi
- 00B910B4 |. 5E pop esi
- 00B910B5 |. 5B pop ebx
- 00B910B6 |. C3 retn
- 00B910B7 |> 8D41 01 lea eax, dword ptr [ecx+1] ; front+1!=rear+1%6
- 00B910BA |. 99 cdq
- 00B910BB |. 8BCB mov ecx, ebx
- 00B910BD |. F7F9 idiv ecx
- 00B910BF |. 46 inc esi
- 00B910C0 |. 3BF2 cmp esi, edx
- 00B910C2 |. 74 35 je short 00B910F9
- 00B910C4 |. 8B3D A420B900 mov edi, dword ptr [<&MSVCR90.printf>] ; MSVCR90.printf
- 00B910CA |. 8D9B 00000000 lea ebx, dword ptr [ebx]
- 00B910D0 |> 8B14B5 7C33B9>/mov edx, dword ptr [esi*4+q]
- 00B910D7 |. 52 |push edx
- 00B910D8 |. 68 3421B900 |push 00B92134 ; ASCII "%d",TAB
- 00B910DD |. FFD7 |call edi
- 00B910DF |. 8D46 01 |lea eax, dword ptr [esi+1] ; front=(front+1)%6
- 00B910E2 |. 99 |cdq
- 00B910E3 |. 8BCB |mov ecx, ebx
- 00B910E5 |. F7F9 |idiv ecx
- 00B910E7 |. A1 2030B900 |mov eax, dword ptr [rear]
- 00B910EC |. 40 |inc eax
- 00B910ED |. 83C4 08 |add esp, 8
- 00B910F0 |. 8BF2 |mov esi, edx
- 00B910F2 |. 99 |cdq
- 00B910F3 |. F7F9 |idiv ecx
- 00B910F5 |. 3BF2 |cmp esi, edx
- 00B910F7 |.^ 75 D7 \jnz short 00B910D0
- 00B910F9 |> 6A 0A push 0A ; /c = 0A (Line Feed)
- 00B910FB |. FF15 9C20B900 call dword ptr [<&MSVCR90.putchar>] ; \putchar
- 00B91101 |. 83C4 04 add esp, 4
- 00B91104 |. 5F pop edi
- 00B91105 |. 5E pop esi
- 00B91106 |. 5B pop ebx
- 00B91107 \. C3 retn
- 逆向分析之LSD基数排序 ;逆向之循环数组队列
- 第六篇:逆向分析之LSD基数排序
- 第七篇:逆向之循环数组队列
- 基数排序之LSD
- 基数排序之LSD
- Android逆向之静态分析
- Android逆向分析之APKTool
- Android逆向分析之Cydia
- android逆向分析之反编译
- 基数排序之LSD篇 (知识点小结)
- linux逆向分析之ElfCrackme分析
- 逆向分析之核心代码的分析
- 逆向分析之寻找main函数
- notebook 4.0 逆向分析 之新成果:
- Android逆向分析之dex2jar异常处理
- Android逆向分析之dex2jar异常处理
- linux逆向分析之ELF文件详解
- 逆向分析之花指令1
- 常见音频视频格式简介
- 数组与Object的关系及其反射类型,数组反射应用实例,通过Array类实现数组的反射
- xml
- lesson1_01
- SSH练习之Tomcat启动错误日志
- 逆向分析之LSD基数排序 ;逆向之循环数组队列
- Gstreamer 中的playback插件
- Linux TCP 连接数修改
- 12/9/16 成都网赛 总结
- 标准输入,标准输出和标准出错的缓冲
- 文件大小
- 青蛙又回到了井里
- 逆向之KMP算法 ;逆向之hanoi塔
- lesson1_02