飘云阁

 找回密码
 加入我们

QQ登录

只需一步,快速开始

查看: 2577|回复: 6

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

[复制链接]

该用户从未签到

发表于 2009-1-20 11:05:03 | 显示全部楼层 |阅读模式
【文章标题】: IMToo系列软件的算法分析
【文章作者】: iawen
【作者主页】: www.iawen.com
【软件名称】: IMToo系列软件
【下载地址】: 自己搜索下载
【加壳方式】: 无
【保护方式】: 注册码
【编写语言】: VC
【使用工具】: OD
【操作平台】: XP SP3
【软件介绍】: 视频音频类的工具
【作者声明】: 此文章献给PYG在休息20天之后终于恢复,以示庆祝!!
--------------------------------------------------------------------------------
【详细过程】
  同样是一个通过专用DLL来验证程序,通过在DLL里查看导出函数,很快就能找到:
  UILib8_M.ImRegUserInfo::IsValidRegInfo_private
  
  双击来到段着下断:

  1.   0046D040 UILib8>/$  6A FF             push -1
  2.   0046D042        |.  68 BB914A00       push UILib8_M.004A91BB                       ;  SE 句柄安装
  3.   0046D047        |.  64:A1 00000000    mov eax,dword ptr fs:[0]
  4.   0046D04D        |.  50                push eax
  5.   0046D04E        |.  64:8925 00000000  mov dword ptr fs:[0],esp
  6.   0046D055        |.  81EC B8000000     sub esp,0B8
  7.   
复制代码
经过一段注册表的读取过程,很快来到这里:

  1.   0046D225        |> \6A 14             push 14                                      ; /Arg2 = 00000014
  2.   0046D227        |.  8D4C24 0C         lea ecx,dword ptr ss:[esp+C]                 ; |
  3.   0046D22B        |.  51                push ecx                                     ; |Arg1 = 0013E8AC
  4.   0046D22C        |.  8D4C24 18         lea ecx,dword ptr ss:[esp+18]                ; |取输入的假码前20位,设为:szConst
  5.   0046D230        |.  FF15 C8E54A00     call dword ptr ds:[<&MFC71U.#3990>]          ; \MFC71U.7C29977E
  6.   
复制代码
继续单步,就看到了对注册码的长度的比较:

  1.   0046D27F        |.  8D4C24 10         lea ecx,dword ptr ss:[esp+10]
  2.   0046D283        |.  FF15 8CE54A00     call dword ptr ds:[<&MFC71U.#2895>]          ;  MFC71U.7C256550
  3.   0046D289        |.  83F8 27           cmp eax,27                                   ;  将注册码长度与0x27比较
  4.   0046D28C        |.  0F85 D3030000     jnz UILib8_M.0046D665                        ;  不等则失败
  5.   
复制代码

  1.   0046D2D6        |.  50                push eax                                     ;  出现字符:ImTOOavimpegconverter5
  2.   0046D2D7        |.  6A 00             push 0                                       ;  我们记为:sName
  3.   0046D2D9        |.  E8 824B0000       call UILib8_M.CImTools::WC_A
  4.   
复制代码
继续单步吧,很快就来到了注册算法的关键部分了,呵呵

  1.   0046D343        |.  8B4C24 20         mov ecx,dword ptr ss:[esp+20]                ;  将ECX指向字符串
  2.   0046D347        |.  8B41 F4           mov eax,dword ptr ds:[ecx-C]                 ;  将字符串的长度存储到EAX
  3.   0046D34A        |.  33F6              xor esi,esi
  4.   0046D34C        |.  85C0              test eax,eax
  5.   0046D34E        |.  C68424 C8000000 0>mov byte ptr ss:[esp+C8],9
  6.   0046D356        |.  7E 5D             jle short UILib8_M.0046D3B5
  7.   0046D358        |.  EB 06             jmp short UILib8_M.0046D360
  8.   0046D35A        |   8D9B 00000000     lea ebx,dword ptr ds:[ebx]
  9.   0046D360        |>  8BD6              /mov edx,esi
  10.   0046D362        |.  81E2 01000080     |and edx,80000001
  11.   0046D368        |.  79 05             |jns short UILib8_M.0046D36F
  12.   0046D36A        |.  4A                |dec edx
  13.   0046D36B        |.  83CA FE           |or edx,FFFFFFFE
  14.   0046D36E        |.  42                |inc edx
  15.   0046D36F        |>  75 38             |jnz short UILib8_M.0046D3A9                 ;  测试EDX是否为0
  16.   0046D371        |.  56                |push esi
  17.   0046D372        |.  8D4C24 24         |lea ecx,dword ptr ss:[esp+24]
  18.   0046D376        |.  FF15 7CE34A00     |call dword ptr ds:[<&MFC71U.#861>]          ;  MFC71U.7C29986D
  19.   0046D37C        |.  8D4C24 0C         |lea ecx,dword ptr ss:[esp+C]
  20.   0046D380        |.  50                |push eax
  21.   0046D381        |.  FF15 44E34A00     |call dword ptr ds:[<&MFC71U.#904>]          ;  MFC71U.7C29B289
  22.   0046D387        |.  8D46 01           |lea eax,dword ptr ds:[esi+1]                ;  将ESI+1的结果保存到EAX
  23.   0046D38A        |.  99                |cdq
  24.   0046D38B        |.  B9 FF000000       |mov ecx,0FF
  25.   0046D390        |.  F7F9              |idiv ecx                                    ;  然后除以0xFF
  26.   0046D392        |.  84D2              |test dl,dl                                  ;  比较余数不否为0
  27.   0046D394        |.  885424 08         |mov byte ptr ss:[esp+8],dl
  28.   0046D398        |.  74 0F             |je short UILib8_M.0046D3A9                  ;  为0则跳转,否则保存到ESP+8的位置
  29.   0046D39A        |.  8B5424 08         |mov edx,dword ptr ss:[esp+8]
  30.   0046D39E        |.  52                |push edx
  31.   0046D39F        |.  8D4C24 10         |lea ecx,dword ptr ss:[esp+10]
  32.   0046D3A3        |.  FF15 44E34A00     |call dword ptr ds:[<&MFC71U.#904>]          ;  MFC71U.7C29B289
  33.   0046D3A9        |>  8B4C24 20         |mov ecx,dword ptr ss:[esp+20]
  34.   0046D3AD        |.  8B41 F4           |mov eax,dword ptr ds:[ecx-C]
  35.   0046D3B0        |.  46                |inc esi
  36.   0046D3B1        |.  3BF0              |cmp esi,eax
  37.   0046D3B3        |.^ 7C AB             \jl short UILib8_M.0046D360
  38.   0046D3B5        |>  8B41 F4           mov eax,dword ptr ds:[ecx-C]
  39.   
复制代码
用代码来表示如下:

  1.   len=strlen(sName);
  2.           int num1[32]={0};
  3.           int num1len=0;
  4.           for(int i=0;i<len;i++){
  5.                   int tmp=i;
  6.                   tmp=tmp & 0x80000001;
  7.                   if(tmp==0){
  8.                           tmp=(i+1) % 0xFF;
  9.                           if(tmp!=0){
  10.                                   num1[num1len]=tmp;
  11.                                   num1len++;
  12.                           }
  13.                   }
  14.           }
  15.   
复制代码
下面还有一段相同的,操作相反的代码(取偶数位,上面的是取奇数位):

  1.   0046D3BE        |.  8BFF              mov edi,edi
  2.   0046D3C0        |>  8BC6              /mov eax,esi
  3.   0046D3C2        |.  25 01000080       |and eax,80000001
  4.   0046D3C7        |.  79 05             |jns short UILib8_M.0046D3CE
  5.   0046D3C9        |.  48                |dec eax
  6.   0046D3CA        |.  83C8 FE           |or eax,FFFFFFFE
  7.   0046D3CD        |.  40                |inc eax
  8.   0046D3CE        |>  74 38             |je short UILib8_M.0046D408
  9.   0046D3D0        |.  56                |push esi
  10.   0046D3D1        |.  8D4C24 24         |lea ecx,dword ptr ss:[esp+24]
  11.   0046D3D5        |.  FF15 7CE34A00     |call dword ptr ds:[<&MFC71U.#861>]          ;  MFC71U.7C29986D
  12.   0046D3DB        |.  8D4C24 0C         |lea ecx,dword ptr ss:[esp+C]
  13.   0046D3DF        |.  50                |push eax
  14.   0046D3E0        |.  FF15 44E34A00     |call dword ptr ds:[<&MFC71U.#904>]          ;  MFC71U.7C29B289
  15.   0046D3E6        |.  8D46 01           |lea eax,dword ptr ds:[esi+1]
  16.   0046D3E9        |.  99                |cdq
  17.   0046D3EA        |.  B9 FF000000       |mov ecx,0FF
  18.   0046D3EF        |.  F7F9              |idiv ecx
  19.   0046D3F1        |.  84D2              |test dl,dl
  20.   0046D3F3        |.  885424 08         |mov byte ptr ss:[esp+8],dl
  21.   0046D3F7        |.  74 0F             |je short UILib8_M.0046D408
  22.   0046D3F9        |.  8B5424 08         |mov edx,dword ptr ss:[esp+8]
  23.   0046D3FD        |.  52                |push edx
  24.   0046D3FE        |.  8D4C24 10         |lea ecx,dword ptr ss:[esp+10]
  25.   0046D402        |.  FF15 44E34A00     |call dword ptr ds:[<&MFC71U.#904>]          ;  MFC71U.7C29B289
  26.   0046D408        |>  8B4424 20         |mov eax,dword ptr ss:[esp+20]
  27.   0046D40C        |.  8B48 F4           |mov ecx,dword ptr ds:[eax-C]
  28.   0046D40F        |.  46                |inc esi
  29.   0046D410        |.  3BF1              |cmp esi,ecx
  30.   0046D412        |.^ 7C AC             \jl short UILib8_M.0046D3C0                  ;  与上一个循环进行相反的操作
  31.   0046D414        |>  8D4C24 2C         lea ecx,dword ptr ss:[esp+2C]
  32.   
复制代码
同样用代码表示如下:

  1.   int num2[32]={0};
  2.           int num2len=0;
  3.           for(int i=0;i<len;i++){
  4.                   int tmp=i;
  5.                   tmp=tmp & 0x80000001;
  6.                   if(tmp!=0){
  7.                           tmp=(i+1) % 0xFF;
  8.                           if(tmp!=0){
  9.                                   num2[num2len]=tmp;
  10.                                   num2len++;
  11.                           }
  12.                   }
  13.           }
  14.   
复制代码
接下来就是对关键字符串的合成了:

  1.   …………
  2.   0046D566        |.  52                push edx
  3.   0046D567        |.  8D4424 2C         lea eax,dword ptr ss:[esp+2C]
  4.   0046D56B        |.  50                push eax
  5.   0046D56C        |.  8D4C24 1C         lea ecx,dword ptr ss:[esp+1C]
  6.   0046D570        |.  51                push ecx
  7.   0046D571        |.  E8 6AF8FFFF       call UILib8_M.0046CDE0                 ;  合成字符
  8.   0046D576        |.  83C4 18           add esp,18
  9.   0046D579        |.  50                push eax
  10.   0046D57A        |.  8D4C24 10         lea ecx,dword ptr ss:[esp+10]
  11.   0046D57E        |.  C68424 CC000000 1>mov byte ptr ss:[esp+CC],11
  12.   0046D586        |.  FF15 34E34A00     call dword ptr ds:[<&MFC71U.#903>]     ;  MFC71U.7C29B383
  13.   0046D58C        |.  8D4C24 08         lea ecx,dword ptr ss:[esp+8]
  14.   0046D590        |.  889C24 C8000000   mov byte ptr ss:[esp+C8],bl
  15.   0046D597        |.  FF15 1CE54A00     call dword ptr ds:[<&MFC71U.#578>]     ;  MFC71U.7C2868E9
  16.   
复制代码
通过观察与分析,首先是将上面两个大循环得到的结果,与软件名位错位相连,然后嫁接两个0x30,
  再把假码的前20位与软件名连接到上面。首位不变,是0x31!

  1.   strCode[0]=0x31;
  2.           int k=1,i=0,j=0;
  3.           while(j<num1len){
  4.                   strCode[k]=sName;
  5.                   i+=2;
  6.                   strCode[k+1]=num1[j];
  7.                   j++;
  8.                   k+=2;
  9.           }
  10.   
  11.           j=0,i=1;
  12.           while(j<num2len){
  13.                   strCode[k]=sName;
  14.                   i+=2;
  15.                   strCode[k+1]=num2[j];
  16.                   j++;
  17.                   k+=2;
  18.           }
  19.   
  20.           strCode[k]=0x30;
  21.           k++;
  22.           strCode[k]=0x30;
  23.           k++;
  24.   
  25.           TCHAR szConst[]="11111A22222B33333C44";
  26.           for(int i=0;i<20;i++,k++)
  27.                   strCode[k]=szConst;
  28.   
  29.           for(int i=0;i<len;i++,k++)
  30.                   strCode[k]=sName;
  31.   
复制代码
观察数据窗口:

  1.   03FC4018  31 49 01 54 03 4F 05 76 07 6D 09 65 0B 63 0D 6E  1ITOvm.e c.n
  2.   03FC4028  0F 65 11 74 13 72 15 6D 02 4F 04 61 06 69 08 70  etrmOaip
  3.   03FC4038  0A 67 0C 6F 0E 76 10 72 12 65 14 35 16 30 30 31  .g.ovre5001
  4.   03FC4048  31 31 31 31 41 32 32 32 32 32 42 33 33 33 33 33  1111A22222B33333
  5.   03FC4058  43 34 34 49 6D 54 4F 4F 61 76 69 6D 70 65 67 63  C44ImTOOavimpegc
  6.   03FC4068  6F 6E 76 65 72 74 65 72 35                       onverter5
  7.   
复制代码
然后对上面的字符串进行MD5计算:

  1.   0046D5A1        |.  52                push edx                               ; /Arg1
  2.   0046D5A2        |.  8D8C24 84000000   lea ecx,dword ptr ss:[esp+84]          ; |
  3.   0046D5A9        |.  E8 12E40200       call UILib8_M.0049B9C0                 ; \UILib8_M.0049B9C0
  4.   
复制代码
接下来,继续对得到的MD5字符串,进行处理:

  1.   0046D6B4        |> /56                /push esi
  2.   0046D6B5        |. |8D4C24 34         |lea ecx,dword ptr ss:[esp+34]
  3.   0046D6B9        |. |FF15 7CE34A00     |call dword ptr ds:[<&MFC71U.#861>]    ;  MFC71U.7C29986D
  4.   0046D6BF        |. |8D4C24 0C         |lea ecx,dword ptr ss:[esp+C]
  5.   0046D6C3        |. |50                |push eax
  6.   0046D6C4        |. |FF15 44E34A00     |call dword ptr ds:[<&MFC71U.#904>]    ;  MFC71U.7C29B289
  7.   0046D6CA        |. |8BCE              |mov ecx,esi
  8.   0046D6CC        |. |D1E9              |shr ecx,1                             ;  <<1,将最低位移到CF中
  9.   0046D6CE        |. |41                |inc ecx
  10.   0046D6CF        |. |81E1 03000080     |and ecx,80000003
  11.   0046D6D5        |. |79 05             |jns short UILib8_M.0046D6DC
  12.   0046D6D7        |. |49                |dec ecx
  13.   0046D6D8        |. |83C9 FC           |or ecx,FFFFFFFC
  14.   0046D6DB        |. |41                |inc ecx
  15.   0046D6DC        |> |75 0F             |jnz short UILib8_M.0046D6ED
  16.   0046D6DE        |. |68 38F94A00       |push UILib8_M.004AF938
  17.   0046D6E3        |. |8D4C24 10         |lea ecx,dword ptr ss:[esp+10]
  18.   0046D6E7        |. |FF15 60E34A00     |call dword ptr ds:[<&MFC71U.#907>]    ;  MFC71U.7C29B867
  19.   0046D6ED        |> |83C6 02           |add esi,2
  20.   0046D6F0        |. |83FE 20           |cmp esi,20
  21.   0046D6F3        |.^\7C BF             \jl short UILib8_M.0046D6B4
  22.   0046D6F5        |.  8D4C24 0C         lea ecx,dword ptr ss:[esp+C]           ;  对MD5值的字符串进行处理
  23.   0046D6F9        |.  FF15 74E34A00     call dword ptr ds:[<&MFC71U.#4079>]    ;  隔位取,4位一组,以-相连
  24.   
复制代码

  1.   0046D706        |.  6A 01             push 1
  2.   0046D708        |.  48                dec eax
  3.   0046D709        |.  50                push eax
  4.   0046D70A        |.  8D4C24 14         lea ecx,dword ptr ss:[esp+14]          ;  去掉最后多出的一个“-”
  5.   
复制代码
将处理得到的字符串嫁接到假码的前20位后面,与假码进行比较,然后就开始设置标志位了,呵呵!

  1.   0046D718        |.  50                push eax
  2.   0046D719        |.  6A 00             push 0
  3.   0046D71B        |.  8D4C24 14         lea ecx,dword ptr ss:[esp+14]
  4.   0046D71F        |.  FF15 78E34A00     call dword ptr ds:[<&MFC71U.#3844>]    ;  MFC71U.7C299F0A
  5.   0046D725        |.  8B4C24 34         mov ecx,dword ptr ss:[esp+34]          ;  将上面提所得字符串转大写
  6.   0046D729        |.  51                push ecx                               ;  与假码的前20位相连
  7.   0046D72A        |.  8D4C24 10         lea ecx,dword ptr ss:[esp+10]          ;  然后与假码比较
  8.   0046D72E        |.  FF15 54E34A00     call dword ptr ds:[<&MFC71U.#1473>]    ;  MFC71U.7C29927C
  9.   0046D734        |.  F7D8              neg eax
  10.   0046D736        |.  1AC0              sbb al,al
  11.   0046D738        |.  FEC0              inc al
  12.   
复制代码
完整的VC代码如下(这里将前20位固定下来了,没有模拟随机生成!):

  1.   void RegistMyCrackMe(HWND hDlg){
  2.           TCHAR sName[STR_LEN]={0};
  3.           memset(sName,0,STR_LEN);
  4.           int len=GetDlgItemText(hDlg,IDC_SNAME,sName,STR_LEN);
  5.           if(len==0){
  6.                   MessageBox(hDlg,TEXT("请按照说明输入软件名称!用户名随意"),TEXT("提示"),0);
  7.                   return;
  8.           }
  9.   
  10.           //计算用户名的MD5散列
  11.           MD5_CTX context;
  12.           TCHAR szHash[STR_LEN]={0};
  13.           TCHAR szBuffer[STR_LEN]={0};
  14.           memset(szBuffer,0,STR_LEN);
  15.           memset(strCode,0,STR_LEN);
  16.          
  17.           len=strlen(sName);
  18.           int num1[32]={0};
  19.           int num1len=0;
  20.           for(int i=0;i<len;i++){
  21.                   int tmp=i;
  22.                   tmp=tmp & 0x80000001;
  23.                   if(tmp==0){
  24.                           tmp=(i+1) % 0xFF;
  25.                           if(tmp!=0){
  26.                                   num1[num1len]=tmp;
  27.                                   num1len++;
  28.                           }
  29.                   }
  30.           }
  31.   
  32.           int num2[32]={0};
  33.           int num2len=0;
  34.           for(int i=0;i<len;i++){
  35.                   int tmp=i;
  36.                   tmp=tmp & 0x80000001;
  37.                   if(tmp!=0){
  38.                           tmp=(i+1) % 0xFF;
  39.                           if(tmp!=0){
  40.                                   num2[num2len]=tmp;
  41.                                   num2len++;
  42.                           }
  43.                   }
  44.           }
  45.   
  46.           strCode[0]=0x31;
  47.           int k=1,i=0,j=0;
  48.           while(j<num1len){
  49.                   strCode[k]=sName;
  50.                   i+=2;
  51.                   strCode[k+1]=num1[j];
  52.                   j++;
  53.                   k+=2;
  54.           }
  55.   
  56.           j=0,i=1;
  57.           while(j<num2len){
  58.                   strCode[k]=sName;
  59.                   i+=2;
  60.                   strCode[k+1]=num2[j];
  61.                   j++;
  62.                   k+=2;
  63.           }
  64.   
  65.           strCode[k]=0x30;
  66.           k++;
  67.           strCode[k]=0x30;
  68.           k++;
  69.   
  70.           TCHAR szConst[]="11111A22222B33333C44";
  71.           for(int i=0;i<20;i++,k++)
  72.                   strCode[k]=szConst;
  73.   
  74.           for(int i=0;i<len;i++,k++)
  75.                   strCode[k]=sName;
  76.   
  77.           len=strlen(strCode);
  78.           MD5Init(&context);
  79.           MD5Update(&context,(unsigned char*)strCode, len);
  80.           MD5Final((unsigned char*)szHash, &context);               
  81.           for(int i=0; i < 16; i++)   // 将szHash[]中的16进制转换成字符形式显示
  82.                   wsprintf(&szBuffer[i*2], "%02X", *(byte*)(szHash+i));
  83.   
  84.           memset(strCode,0,STR_LEN);
  85.           k=0;
  86.           for(int i=0;i<20;i++,k++)
  87.                   strCode[k]=szConst;
  88.           j=0;
  89.           for(int i=0;i<32;i+=2){
  90.                   strCode[k]=szBuffer;
  91.                   j++;
  92.                   if((j%4)==0){
  93.                           k++;
  94.                           strCode[k]='-';
  95.                   }
  96.                   k++;
  97.           }
  98.           strCode[k-1]=0;//去掉最后一个'-1'
  99.   
  100.           SetDlgItemText(hDlg,IDC_PWD,strCode);
  101.           return;
  102.   }
  103.   
复制代码
--------------------------------------------------------------------------------
【版权声明】: 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年01月15日 15:47:11

[ 本帖最后由 iawen 于 2009-1-20 23:45 编辑 ]

评分

参与人数 1威望 +20 飘云币 +40 收起 理由
tianxj + 20 + 40 您发布的主题属于精品!

查看全部评分

PYG19周年生日快乐!
  • TA的每日心情
    开心
    2015-8-3 23:07
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    发表于 2009-1-20 15:25:20 | 显示全部楼层
    分析得很牛,
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2024-5-1 14:44
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2009-1-20 23:42:42 | 显示全部楼层
    支持 iawen 加入[PYG]!!
    PYG19周年生日快乐!
  • TA的每日心情
    开心
    2020-8-30 18:31
  • 签到天数: 52 天

    [LV.5]常住居民I

    发表于 2009-1-20 23:55:07 | 显示全部楼层
    嘎嘎,我也来支持一下哈。
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2018-4-24 11:02
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2009-1-21 00:02:24 | 显示全部楼层
    强悍的老亚,肯定没问题的!!!/:good
    PYG19周年生日快乐!
  • TA的每日心情
    慵懒
    2024-10-16 20:38
  • 签到天数: 1491 天

    [LV.10]以坛为家III

    发表于 2009-1-21 09:15:09 | 显示全部楼层
    分析得的确非常牛!
    PYG19周年生日快乐!

    该用户从未签到

    发表于 2009-1-21 11:25:56 | 显示全部楼层
    又看见牛人了  希望大侠多发精品/:good
    PYG19周年生日快乐!
    您需要登录后才可以回帖 登录 | 加入我们

    本版积分规则

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