飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 1930|回复: 6

iawen申请加入PYG----算法分析3

[复制链接]

该用户从未签到

发表于 2009-1-20 11:07:22 | 显示全部楼层 |阅读模式
目标软件:OJOsoft系列
语言:VC
工具:OD

软件是VC写的,用PEID显示为:Microsoft Visual C++ 7.0 Method2 [调试]
二话不说,直接到OD载入,然后输入假的激活码,很快就能找到关键点:

  1. 00401D6D     .  C74424 1C 00000>mov dword ptr ss:[esp+1C],0
  2. 00401D75     .  E8 96E80100     call <jmp.&MFC71.#3761>
  3. 00401D7A     .  51              push ecx
  4. 00401D7B     .  8D5424 08       lea edx,dword ptr ss:[esp+8]
  5. 00401D7F     .  8BCC            mov ecx,esp
  6. 00401D81     .  896424 10       mov dword ptr ss:[esp+10],esp
  7. 00401D85     .  52              push edx
  8. 00401D86     .  FF15 E4514200   call dword ptr ds:[<&MFC71.#297>]         ;  MFC71.7C14E575
  9. 00401D8C     .  8B8E C8000000   mov ecx,dword ptr ds:[esi+C8]
  10. 00401D92     .  FF15 30504200   call dword ptr ds:[<&Control.AVProxy::Reg>;  Control.AVProxy::RegisteProduct
复制代码
[separator]
显然是通过专用的DLL来验证注册的。
跟进后,来到这里:

  1. 003A6C49      C64424 4C 01      mov byte ptr ss:[esp+4C],1
  2. 003A6C4E      FF15 94803B00     call dword ptr ds:[<&MFC71.#297>]         ; MFC71.7C14E575
  3. 003A6C54      8D4C24 0C         lea ecx,dword ptr ss:[esp+C]
  4. 003A6C58      E8 03DB0000       call Control.003B4760                   //这里同样为关键CALL,跟进继续分析
  5. 003A6C5D      8BF0              mov esi,eax
  6. 003A6C5F      85F6              test esi,esi
  7. 003A6C61      75 76             jnz short Control.003A6CD9
  8. 003A6C63      8D4C24 10         lea ecx,dword ptr ss:[esp+10]
复制代码
继续跟进

  1. 003B485D      8BCE              mov ecx,esi
  2. 003B485F      885C24 3C         mov byte ptr ss:[esp+3C],bl
  3. 003B4863      E8 38F5FFFF       call Control.003B3DA0
  4. 003B4868      0FB6C0            movzx eax,al
  5. 003B486B      85C0              test eax,eax
  6. 003B486D      74 69             je short Control.003B48D8
复制代码
继续跟进

  1. 003B3DE7      8BCE              mov ecx,esi
  2. 003B3DE9      E8 12FAFFFF       call Control.003B3800
  3. 003B3DEE      84C0              test al,al
  4. 003B3DF0      0F84 49010000     je Control.003B3F3F
复制代码
跟进CALL后,发现这里是对激活码的格式的一段验证:

  1. 003B3837      2BC2              sub eax,edx
  2. 003B3839      83F8 18           cmp eax,18             //比较激活码的长度是否为0x18,不是则失败
  3. …………………………
  4. 003B3850     >  56              push esi
  5. 003B3851     . |8D4C24 20       lea ecx,dword ptr ss:[esp+20]
  6. 003B3855     . |FF15 20813B00   call dword ptr ds:[<&MFC71.#865>]              ;  MFC71.7C1894E7
  7. 003B385B     . |0FBEC0          movsx eax,al
  8. 003B385E     . |50              push eax
  9. 003B385F     . |FFD3            call ebx
  10. 003B3861     . |83C4 04         add esp,4
  11. 003B3864     . |83FF 04         cmp edi,4
  12. 003B3867     . |75 08           jnz short Control.003B3871
  13. 003B3869     . |3C 2D           cmp al,2D
  14. 003B386B     . |75 33           jnz short Control.003B38A0
  15. 003B386D     . |33FF            xor edi,edi
  16. 003B386F     . |EB 09           jmp short Control.003B387A
  17. 003B3871     > |3C 41           cmp al,41
  18. 003B3873     . |7C 2B           jl short Control.003B38A0
  19. 003B3875     . |3C 5A           cmp al,5A
  20. 003B3877     . |7F 27           jg short Control.003B38A0
  21. 003B3879     . |47              inc edi
  22. 003B387A     > |46              inc esi
  23. 003B387B     . |83FE 18         cmp esi,18
  24. 003B387E     .^\7C D0           jl short Control.003B3850
复制代码
难过上面一段,我们知道了激活的格式应该为:XXXX-XXXX-XXXX-XXXX-XXXX
而且应该是全为字母,不能为数字!
好了,我们重新输入来过,路跳过上面的分析,来到:

  1. 003B3960    |> /8D4424 14       /lea eax,dword ptr ss:[esp+14]
  2. 003B3964    |. |33ED            |xor ebp,ebp
  3. 003B3966    |. |8D50 01         |lea edx,dword ptr ds:[eax+1]
  4. 003B3969    |. |8DA424 00000000 |lea esp,dword ptr ss:[esp]
  5. 003B3970    |> |8A08            |/mov cl,byte ptr ds:[eax]
  6. 003B3972    |. |40              ||inc eax
  7. 003B3973    |. |84C9            ||test cl,cl
  8. 003B3975    |.^|75 F9           |\jnz short Control.003B3970
  9. 003B3977    |. |2BC2            |sub eax,edx                       ;  取软件名长度-EBX
  10. 003B3979    |. |8BF8            |mov edi,eax
  11. 003B397B    |. |33C9            |xor ecx,ecx
  12. 003B397D    |. |85FF            |test edi,edi
  13. 003B397F    |. |7E 18           |jle short Control.003B3999
  14. 003B3981    |> |0FBE740C 14     |/movsx esi,byte ptr ss:[esp+ecx+1>
  15. 003B3986    |. |8BC3            ||mov eax,ebx
  16. 003B3988    |. |0FAFC6          ||imul eax,esi
  17. 003B398B    |. |99              ||cdq
  18. 003B398C    |. |2BC2            ||sub eax,edx
  19. 003B398E    |. |D1F8            ||sar eax,1
  20. 003B3990    |. |03C6            ||add eax,esi
  21. 003B3992    |. |03E8            ||add ebp,eax
  22. 003B3994    |. |41              ||inc ecx
  23. 003B3995    |. |3BCF            ||cmp ecx,edi
  24. 003B3997    |.^|7C E8           |\jl short Control.003B3981
  25. 003B3999    |> |8BC5            |mov eax,ebp
  26. 003B399B    |. |99              |cdq
  27. 003B399C    |. |B9 1A000000     |mov ecx,1A
  28. 003B39A1    |. |F7F9            |idiv ecx
  29. 003B39A3    |. |8B4424 10       |mov eax,dword ptr ss:[esp+10]     ;  除以常量0x1A
  30. 003B39A7    |. |83C3 06         |add ebx,6                         ;  EB+=6
  31. 003B39AA    |. |83C0 04         |add eax,4
  32. 003B39AD    |. |83FB 19         |cmp ebx,19                        ;  与0x19比较,大于则结束循环
  33. 003B39B0    |. |894424 10       |mov dword ptr ss:[esp+10],eax
  34. 003B39B4    |. |8950 FC         |mov dword ptr ds:[eax-4],edx      ;  将上面的相除所得余数保存到下来
  35. 003B39B7    |.^\7C A7           \jl short Control.003B3960
复制代码
这段代码很重要,主要是针对程序名进行处理,得到4个整数,保存下来后,将参与注册验证!
这里将之记为modNum[4],代码的流程用C++转述如下(注:name记为软件名):

  1. int modNum[4]={0};
  2.         int k=0;
  3.         for(int i=1;i<0x19;i+=6){
  4.                 int len=strlen(name);
  5.                 int sum=0;
  6.                 for(int j=0;j<len;j++){
  7.                         int tmpSum=name[j]*i;
  8.                         tmpSum=(tmpSum>>1);
  9.                         sum=sum+tmpSum+name[j];
  10.                 }
  11.                 modNum[k]=sum % 0x1A;
  12.                 k++;
  13.         }
复制代码
好了,我们继续单步,来到这里:

  1. 003B3E02    |> /83FF 04         /cmp edi,4
  2. 003B3E05    |. |75 04           |jnz short Control.003B3E0B
  3. 003B3E07    |. |33FF            |xor edi,edi
  4. 003B3E09    |. |EB 23           |jmp short Control.003B3E2E
  5. 003B3E0B    |> |53              |push ebx
  6. 003B3E0C    |. |8D8C24 E0000000 |lea ecx,dword ptr ss:[esp+E0]
  7. 003B3E13    |. |FF15 20813B00   |call dword ptr ds:[<&MFC71.#865>] ;  MFC71.7C1894E7
  8. 003B3E19    |. |0FBEC8          |movsx ecx,al
  9. 003B3E1C    |. |51              |push ecx
  10. 003B3E1D    |. |FFD5            |call ebp
  11. 003B3E1F    |. |0FBED0          |movsx edx,al
  12. 003B3E22    |. |83EA 41         |sub edx,41
  13. 003B3E25    |. |83C4 04         |add esp,4
  14. 003B3E28    |. |8916            |mov dword ptr ds:[esi],edx
  15. 003B3E2A    |. |47              |inc edi
  16. 003B3E2B    |. |83C6 04         |add esi,4
  17. 003B3E2E    |> |43              |inc ebx
  18. 003B3E2F    |. |83FB 18         |cmp ebx,18
  19. 003B3E32    |.^\7C CE           \jl short Control.003B3E02
复制代码
上面是对用户输入的假码进行处理,处理的方式是对激活码按位送去0x41(跳过"-")!
然后我们就来到了关键的比较点了:

  1. 003B3F01    |> /8B6C0C 18       /mov ebp,dword ptr ss:[esp+ecx+18]    ;  按位取第1组
  2. 003B3F05    |. |8B840C B8000000 |mov eax,dword ptr ss:[esp+ecx+B8]    ;  按位取上面所得余数
  3. 003B3F0C    |. |8B7C0C 28       |mov edi,dword ptr ss:[esp+ecx+28]    ;  按位取第2组
  4. 003B3F10    |. |8B740C 48       |mov esi,dword ptr ss:[esp+ecx+48]    ;  按位取第4组
  5. 003B3F14    |. |8B540C 38       |mov edx,dword ptr ss:[esp+ecx+38]    ;  按位取第3组
  6. 003B3F18    |. |03C5            |add eax,ebp
  7. 003B3F1A    |. |03C7            |add eax,edi
  8. 003B3F1C    |. |03C6            |add eax,esi
  9. 003B3F1E    |. |03C2            |add eax,edx
  10. 003B3F20    |. |99              |cdq
  11. 003B3F21    |. |BE 1A000000     |mov esi,1A
  12. 003B3F26    |. |F7FE            |idiv esi
  13. 003B3F28    |. |3B940C A8000000 |cmp edx,dword ptr ss:[esp+ecx+A8]    ;  按位与第5组相比
  14. 003B3F2F    |. |89540C 58       |mov dword ptr ss:[esp+ecx+58],edx
  15. 003B3F33    |. |75 0A           |jnz short Control.003B3F3F
  16. 003B3F35    |. |83C1 04         |add ecx,4
  17. 003B3F38    |. |83F9 10         |cmp ecx,10
  18. 003B3F3B    |.^\7C C4           \jl short Control.003B3F01
  19. 003B3F3D    |.  EB 02           jmp short Control.003B3F41
  20. 003B3F3F    |>  32DB            xor bl,bl
  21. 003B3F41    |>  8D8C24 D8000000 lea ecx,dword ptr ss:[esp+D8]
复制代码
分析好了,我们开始写KeyGen了,完整的代码如下:

  1. #include<stdio.h>
  2. #include<time.h>
  3. #include<iOStream>
  4. using namespace std;

  5. int main()
  6. {
  7.         char name[32]={0};
  8.         cout<<"Please Enter SoftName:()\n";
  9.         cin.getline(name,31);
  10.         //cout<<name<<endl;
  11.        
  12.         int modNum[4]={0};
  13.         int k=0;
  14.         for(int i=1;i<0x19;i+=6){
  15.                 int len=strlen(name);
  16.                 int sum=0;
  17.                 for(int j=0;j<len;j++){
  18.                         int tmpSum=name[j]*i;
  19.                         tmpSum=(tmpSum>>1);
  20.                         sum=sum+tmpSum+name[j];
  21.                 }
  22.                 modNum[k]=sum % 0x1A;
  23.                 k++;
  24.         }
  25.        
  26.         srand(time(NULL));
  27.         char code[32]={0};
  28.         for(int i=0;i<4;i++){
  29.                 int n1,n2,n3,n4,n5;
  30.                 while(1){
  31.                         n1=((double)rand()/(double)RAND_MAX)*0x19+0;
  32.                         n2=((double)rand()/(double)RAND_MAX)*0x19+0;
  33.                         n3=((double)rand()/(double)RAND_MAX)*0x19+0;
  34.                         n4=((double)rand()/(double)RAND_MAX)*0x19+0;
  35.                         n5=((double)rand()/(double)RAND_MAX)*0x19+0;
  36.                         int tmp=n1+n2+n3+n4+modNum[i];
  37.                         if((tmp %0x1A)==n5)
  38.                                 break;
  39.                 }
  40.                
  41.                 code[i]=0x41+n1;
  42.                 code[i+5]=0x41+n2;
  43.                 code[i+5*2]=0x41+n3;
  44.                 code[i+5*3]=0x41+n4;
  45.                 code[i+5*4]=0x41+n5;
  46.         }
  47.         code[4]='-';
  48.         code[9]='-';
  49.         code[14]='-';
  50.         code[19]='-';

  51.         cout<<"Your RegCode is: ";
  52.         cout<<code<<endl;;
  53.        
  54.         cout<<"Please Enter a Key to Exit…………\n";
  55.         getchar();
  56.         getchar();
  57.        
  58.         return 0;
  59. }
复制代码

[ 本帖最后由 iawen 于 2009-1-20 23:44 编辑 ]
PYG19周年生日快乐!
  • TA的每日心情
    开心
    前天 14:44
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2009-1-20 23:43:13 | 显示全部楼层
    支持一下!!
    PYG19周年生日快乐!
  • TA的每日心情
    奋斗
    2015-10-29 08:08
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2009-1-21 13:14:11 | 显示全部楼层
    支持牛人来了。。。。
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2009-1-21 21:28:16 | 显示全部楼层
    太强大了,这个不支持不行啊
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2009-1-21 23:11:13 | 显示全部楼层
    进来学习一下了/:good
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2023-1-12 22:33
  • 签到天数: 6 天

    [LV.2]偶尔看看I

    发表于 2009-1-24 21:36:26 | 显示全部楼层
    进来支持了
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2009-5-16 22:59:16 | 显示全部楼层
    看了你的文章我都不敢申请PYG小组了,水平不是一般的牛了
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

    快速回复 返回顶部 返回列表