【文章标题】: AAA AceCapture 1.95 算法分析
【文章作者】: qifeon
【软件名称】: AAA AceCapture 1.95
【下载地址】: 自己搜索下载
【使用工具】: od,peid
【操作平台】: winxp sp2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  一、peid 查壳,显示无壳,编程语言为:Microsoft Visual C++ 6.0。
  
  二、试运行软件,输入“qifeon,12345-67890”.有错误提示。“registration code is invalid”。
         同时注意注册码部分无法输入字母,即只能为数字。
  
  三、od载入程序,查找错误提示字符串。
  
  
  Ultra String Reference, 条目 280
   Address=0040FE47
   Disassembly=push    0046E074
   Text String=registration code is invalid!
  
  双击来到
  
  

代码:
0040FE45  |.  57            push    edi
  0040FE46  |.  57            push    edi
  0040FE47  |.  68 74E04600   push    0046E074                         ;  registration code is invalid!
  0040FE4C  |.  EB 22         jmp     short 0040FE70                       返回处
  0040FE4E  |>  837D EC 01    cmp     dword ptr [ebp-14], 1
  0040FE52  |.  75 21         jnz     short 0040FE75
  0040FE54  |.  57            push    edi
  0040FE55  |.  57            push    edi
  0040FE56  |.  68 58E04600   push    0046E058                         ;  thank you for supporting!
  0040FE5B  |.  E8 34AB0200   call    0043A994
  0040FE60  |.  8BCE          mov     ecx, esi
  0040FE62  |.  E8 57E70100   call    0042E5BE
  
  ***************************************************************************************************************************
  
  
  向上找到段首
  
  ***************************************************************************************************************************
  
  
代码:
0040FCF8  /$  B8 6C114500   mov     eax, 0045116C               段首
  0040FCFD  |.  E8 86CF0000   call    0041CC88
  0040FD02  |.  81EC E0000000 sub     esp, 0E0
  0040FD08  |.  53            push    ebx
  0040FD09  |.  56            push    esi
  0040FD0A  |.  57            push    edi
  0040FD0B  |.  8BF1          mov     esi, ecx
  0040FD0D  |.  33FF          xor     edi, edi
  0040FD0F  |.  8975 E4       mov     dword ptr [ebp-1C], esi
  0040FD12  |.  897D F0       mov     dword ptr [ebp-10], edi
  0040FD15  |.  8D45 F0       lea     eax, dword ptr [ebp-10]
  0040FD18  |.  897D FC       mov     dword ptr [ebp-4], edi
  0040FD1B  |.  50            push    eax
  0040FD1C  |.  E8 06020000   call    0040FF27
  0040FD21  |.  85C0          test    eax, eax
  0040FD23  |.  0F84 4C010000 je      0040FE75
  0040FD29  |.  57            push    edi
  0040FD2A  |.  8BCE          mov     ecx, esi
  0040FD2C  |.  E8 D2260200   call    00432403
  0040FD31  |.  8B45 F0       mov     eax, dword ptr [ebp-10]
  0040FD34  |.  50            push    eax
  0040FD35  |.  8B08          mov     ecx, dword ptr [eax]
  0040FD37  |.  FF51 1C       call    dword ptr [ecx+1C]
  0040FD3A  |.  3BC7          cmp     eax, edi
  0040FD3C  |.  0F8C 33010000 jl      0040FE75
  0040FD42  |.  8B45 F0       mov     eax, dword ptr [ebp-10]
  0040FD45  |.  8D55 E8       lea     edx, dword ptr [ebp-18]
  0040FD48  |.  897D E8       mov     dword ptr [ebp-18], edi
  0040FD4B  |.  52            push    edx
  0040FD4C  |.  8B08          mov     ecx, dword ptr [eax]
  0040FD4E  |.  50            push    eax
  0040FD4F  |.  FF51 20       call    dword ptr [ecx+20]
  0040FD52  |.  3BC7          cmp     eax, edi
  0040FD54  |.  0F8C 1B010000 jl      0040FE75
  0040FD5A  |.  837D E8 01    cmp     dword ptr [ebp-18], 1
  0040FD5E  |.  75 0C         jnz     short 0040FD6C
  0040FD60  |.  57            push    edi
  0040FD61  |.  57            push    edi
  0040FD62  |.  68 94E04600   push    0046E094                         ;  you needn't register more than 1 time!
  0040FD67  |.  E9 04010000   jmp     0040FE70
  0040FD6C  |>  68 40040000   push    440
  0040FD71  |.  8BCE          mov     ecx, esi
  0040FD73  |.  E8 9DF90100   call    0042F715
  0040FD78  |.  8D8D 14FFFFFF lea     ecx, dword ptr [ebp-EC]
  0040FD7E  |.  68 C7000000   push    0C7
  0040FD83  |.  51            push    ecx
  0040FD84  |.  8BC8          mov     ecx, eax
  0040FD86  |.  E8 01FB0100   call    0042F88C
  0040FD8B  |.  8D85 14FFFFFF lea     eax, dword ptr [ebp-EC]          ;  用户名
  0040FD91  |.  50            push    eax
  0040FD92  |.  E8 19CF0000   call    0041CCB0
  0040FD97  |.  83F8 05       cmp     eax, 5                           ;  用户名长度与5相比较
  0040FD9A  |.  59            pop     ecx
  0040FD9B  |.  0F8C C8000000 jl      0040FE69                             低于5位则跳向失败
  0040FDA1  |.  3D 96000000   cmp     eax, 96                              用户名长度与150比较
  0040FDA6  |.  0F8F BD000000 jg      0040FE69                              大于150则跳向失败
  0040FDAC  |.  8D85 14FFFFFF lea     eax, dword ptr [ebp-EC]
  0040FDB2  |.  85C0          test    eax, eax
  0040FDB4  |.  75 04         jnz     short 0040FDBA
  0040FDB6  |.  33DB          xor     ebx, ebx
  0040FDB8  |.  EB 38         jmp     short 0040FDF2
  0040FDBA  |>  8D85 14FFFFFF lea     eax, dword ptr [ebp-EC]
  0040FDC0  |.  50            push    eax                              ; /String
  0040FDC1  |.  FF15 54424500 call    dword ptr [<&KERNEL32.lstrlenA>] ; \lstrlenA
  0040FDC7  |.  8BF0          mov     esi, eax                         ;  用户名长度
  0040FDC9  |.  46            inc     esi
  0040FDCA  |.  8D0436        lea     eax, dword ptr [esi+esi]
  0040FDCD  |.  83C0 03       add     eax, 3
  0040FDD0  |.  24 FC         and     al, 0FC
  0040FDD2  |.  E8 B9D50000   call    0041D390
  0040FDD7  |.  8BDC          mov     ebx, esp
  0040FDD9  |.  56            push    esi                              ; /WideBufSize
  0040FDDA  |.  53            push    ebx                              ; |WideCharBuf
  0040FDDB  |.  8D85 14FFFFFF lea     eax, dword ptr [ebp-EC]          ; |
  0040FDE1  |.  6A FF         push    -1                               ; |StringSize = FFFFFFFF (-1.)
  0040FDE3  |.  50            push    eax                              ; |StringToMap
  0040FDE4  |.  57            push    edi                              ; |Options
  0040FDE5  |.  57            push    edi                              ; |CodePage
  0040FDE6  |.  66:893B       mov     word ptr [ebx], di               ; |
  0040FDE9  |.  FF15 90424500 call    dword ptr [<&KERNEL32.MultiByteT>; \MultiByteToWideChar
  0040FDEF  |.  8B75 E4       mov     esi, dword ptr [ebp-1C]          ;  单字节转化为宽字节
  0040FDF2  |>  53            push    ebx
  0040FDF3  |.  FF15 5C444500 call    dword ptr [<&OLEAUT32.#2>]       ;  OLEAUT32.SysAllocString
  0040FDF9  |.  8B4D F0       mov     ecx, dword ptr [ebp-10]
  0040FDFC  |.  50            push    eax
  0040FDFD  |.  51            push    ecx                              ;  
  0040FDFE  |.  8B11          mov     edx, dword ptr [ecx]
  0040FE00  |.  FF52 28       call    dword ptr [edx+28]
  0040FE03  |.  3BC7          cmp     eax, edi
  0040FE05  |.  7C 6E         jl      short 0040FE75
  0040FE07  |.  8B86 00020000 mov     eax, dword ptr [esi+200]         ;  试炼码第一部分16进制
  0040FE0D  |.  8D55 DC       lea     edx, dword ptr [ebp-24]
  0040FE10  |.  8945 DC       mov     dword ptr [ebp-24], eax
  0040FE13  |.  8B86 04020000 mov     eax, dword ptr [esi+204]         ;  试炼码第2部分16进制
  0040FE19  |.  8945 E0       mov     dword ptr [ebp-20], eax
  0040FE1C  |.  8B45 F0       mov     eax, dword ptr [ebp-10]
  0040FE1F  |.  6A 02         push    2
  0040FE21  |.  52            push    edx
  0040FE22  |.  8B08          mov     ecx, dword ptr [eax]
  0040FE24  |.  50            push    eax
  0040FE25  |.  FF51 2C       call    dword ptr [ecx+2C]
  0040FE28  |.  3BC7          cmp     eax, edi
  0040FE2A  |.  7C 49         jl      short 0040FE75
  0040FE2C  |.  8B45 F0       mov     eax, dword ptr [ebp-10]
  0040FE2F  |.  8D55 EC       lea     edx, dword ptr [ebp-14]
  0040FE32  |.  897D EC       mov     dword ptr [ebp-14], edi
  0040FE35  |.  52            push    edx
  0040FE36  |.  8B08          mov     ecx, dword ptr [eax]
  0040FE38  |.  50            push    eax
  0040FE39  |.  FF51 30       call    dword ptr [ecx+30]               ;  算法call,待会进入
  0040FE3C  |.  3BC7          cmp     eax, edi                            关键跳转    
  0040FE3E  |.  7C 35         jl      short 0040FE75
  0040FE40  |.  397D EC       cmp     dword ptr [ebp-14], edi
  0040FE43  |.  75 09         jnz     short 0040FE4E
  0040FE45  |.  57            push    edi
  0040FE46  |.  57            push    edi
  0040FE47  |.  68 74E04600   push    0046E074                         ;  registration code is invalid!
  0040FE4C  |.  EB 22         jmp     short 0040FE70                       返回处
  0040FE4E  |>  837D EC 01    cmp     dword ptr [ebp-14], 1
  0040FE52  |.  75 21         jnz     short 0040FE75
  0040FE54  |.  57            push    edi
  0040FE55  |.  57            push    edi
  0040FE56  |.  68 58E04600   push    0046E058                         ;  thank you for supporting!
  0040FE5B  |.  E8 34AB0200   call    0043A994
  0040FE60  |.  8BCE          mov     ecx, esi
  0040FE62  |.  E8 57E70100   call    0042E5BE
  0040FE67  |.  EB 0C         jmp     short 0040FE75
  0040FE69  |>  57            push    edi
  0040FE6A  |.  57            push    edi
  0040FE6B  |.  68 3CE04600   push    0046E03C                         ;  must the length of name>=5
  0040FE70  |>  E8 1FAB0200   call    0043A994
  0040FE75  |>  8B45 F0       mov     eax, dword ptr [ebp-10]
  0040FE78  |.  834D FC FF    or      dword ptr [ebp-4], FFFFFFFF
  0040FE7C  |.  3BC7          cmp     eax, edi
  0040FE7E  |.  74 06         je      short 0040FE86
  0040FE80  |.  8B08          mov     ecx, dword ptr [eax]
  0040FE82  |.  50            push    eax
  0040FE83  |.  FF51 08       call    dword ptr [ecx+8]
  0040FE86  |>  8B4D F4       mov     ecx, dword ptr [ebp-C]
  0040FE89  |.  8DA5 08FFFFFF lea     esp, dword ptr [ebp-F8]
  0040FE8F  |.  64:890D 00000>mov     dword ptr fs:[0], ecx
  0040FE96  |.  5F            pop     edi
  0040FE97  |.  5E            pop     esi
  0040FE98  |.  5B            pop     ebx
  0040FE99  |.  C9            leave
  0040FE9A  \.  C3            retn
  
  ***************************************************************************************************************************
  
  
  段首下断,输入试炼码。F9运行,断下后调试。单步进入算法call
  
  
  
  **********************************************************************************************************************8
  
 进入 算法call
  
  
 
代码:
 100014C1    55              push    ebp
  100014C2    8BEC            mov     ebp, esp
  100014C4    81EC 08040000   sub     esp, 408
  100014CA    53              push    ebx
  100014CB    56              push    esi
  100014CC    57              push    edi
  100014CD    8B7D 08         mov     edi, dword ptr [ebp+8]
  100014D0    33F6            xor     esi, esi
  100014D2    3977 08         cmp     dword ptr [edi+8], esi
  100014D5    0F84 F2000000   je      100015CD
  100014DB    3977 0C         cmp     dword ptr [edi+C], esi
  100014DE    0F84 E9000000   je      100015CD
  100014E4    8B5F 10         mov     ebx, dword ptr [edi+10]
  100014E7    3BDE            cmp     ebx, esi
  100014E9    74 30           je      short 1000151B
  100014EB    53              push    ebx
  100014EC    FF15 A4500010   call    dword ptr [<&KERNEL32.lstrlenW>] ; kernel32.lstrlenW
  100014F2    8D7C00 02       lea     edi, dword ptr [eax+eax+2]       ; 取用户名长度
  100014F6    8BC7            mov     eax, edi
  100014F8    83C0 03         add     eax, 3
  100014FB    24 FC           and     al, 0FC
  100014FD    E8 EE270000     call    10003CF0
  10001502    33C0            xor     eax, eax
  10001504    8BF4            mov     esi, esp
  10001506    50              push    eax
  10001507    50              push    eax
  10001508    8026 00         and     byte ptr [esi], 0
  1000150B    57              push    edi
  1000150C    56              push    esi
  1000150D    6A FF           push    -1
  1000150F    53              push    ebx
  10001510    50              push    eax
  10001511    50              push    eax
  10001512    FF15 A8500010   call    dword ptr [<&KERNEL32.WideCharTo>; kernel32.WideCharToMultiByte
  10001518    8B7D 08         mov     edi, dword ptr [ebp+8]           ; 宽字节转化为单字节
  1000151B    8D85 F8FBFFFF   lea     eax, dword ptr [ebp-408]
  10001521    56              push    esi
  10001522    50              push    eax
  10001523    E8 D8260000     call    10003C00
  10001528    59              pop     ecx
  10001529    33D2            xor     edx, edx                         ; edx初值为0
  1000152B    59              pop     ecx
  1000152C    33F6            xor     esi, esi                         ; esi 初值为0
  1000152E    8955 FC         mov     dword ptr [ebp-4], edx           ; [ebp-4]初值为0
  10001531    8D85 F8FBFFFF   lea     eax, dword ptr [ebp-408]         ; 用户名地址入eax
  10001537    0FBE18          movsx   ebx, byte ptr [eax]              ; 循环取用户名ASCII值扩展送入ebx
  1000153A    83FA 04         cmp     edx, 4                           ; 比较edx是否小于4,进入不同算法
  1000153D    7D 14           jge     short 10001553                   ; 大于或等于4则跳向算法2,即针对用户名4位后字符
  ……………………………………………………………………………………………………………………

   当edx值小于4时即进入下面算法1部分,算法1也是计算注册码第一部分16进制值
      edx值是与取用户名ASCII所在位数值同步自增的,所以直接影响到用户名的字符部分
      参与到注册码哪一部分的计算。

……………………………………………………………………………………………………………………

 
代码:
 1000153F    6A 03           push    3                                ; 常数3入栈
  10001541    81C3 E1100000   add     ebx, 10E1                        ; ebx=ebx+10E1h
  10001547    59              pop     ecx                              ; 常数3出栈,ecx=3
  10001548    2BCA            sub     ecx, edx                         ; ecx=ecx-edx
  1000154A    C1E1 03         shl     ecx, 3                           ; ecx逻辑左移3位
  1000154D    D3E3            shl     ebx, cl                          ; ebx逻辑左移cl位
  1000154F    0BF3            or      esi, ebx                         ; esi=esi or ebx ,esi 最终值即为注册码第一部分16进制值
  10001551    EB 13           jmp     short 10001566
…………………………………………………………………………………………………………

  当edx 值大于或等于4时,进入算法2.算法2是求注册码第二部分16进制值
……………………………………………………………………………………………………………
  
代码:
10001553    6A 07           push    7
  10001555    81C3 D2040000   add     ebx, 4D2                         ; ebx=ebx+4D2h
  1000155B    59              pop     ecx                              ; ecx=7
  1000155C    2BCA            sub     ecx, edx                         ; ecx=ecx-edx
  1000155E    C1E1 03         shl     ecx, 3                               ecx值逻辑左移3位
  10001561    D3E3            shl     ebx, cl                                  ebx逻辑左移cl位  
  10001563    095D FC         or      dword ptr [ebp-4], ebx         [ebp-4] 值与ebx相或, [ebp-4]最终值即为注册码第二部分16进制值     
  10001566    42              inc     edx                              ; edx自增1
  10001567    83FA 08         cmp     edx, 8                        edx值与8相比较
  1000156A    75 02           jnz     short 1000156E              不等于8则正常循环
  1000156C    33D2            xor     edx, edx                        等于8则edx清0,即用户名第8位起4位又进入算法1
  1000156E    40              inc     eax                              ; eax自增1
  1000156F    8038 00         cmp     byte ptr [eax], 0                ; 判断用户名是否取完
  10001572  ^ 75 C3           jnz     short 10001537                     未取完则继续循环取下一位
  10001574    3977 08         cmp     dword ptr [edi+8], esi           ; 比较esi值和试炼码第一部分16进制值
  10001577    75 4A           jnz     short 100015C3                          不等则挂,爆破点
  10001579    8B45 FC         mov     eax, dword ptr [ebp-4]           ; ebp-4]值传送到eax
  1000157C    3947 0C         cmp     dword ptr [edi+C], eax              比较[ebp-4]值和试炼码第二部分16进制值
  1000157F    75 42           jnz     short 100015C3                            不等则挂,爆破点
  10001581    8B4D 0C         mov     ecx, dword ptr [ebp+C]              上面两处相等则开始建立注册表项
  10001584    6A 01           push    1
  10001586    58              pop     eax
  10001587    8901            mov     dword ptr [ecx], eax
  10001589    8945 0C         mov     dword ptr [ebp+C], eax
  1000158C    8D45 08         lea     eax, dword ptr [ebp+8]
  1000158F    50              push    eax
  10001590    68 1C600010     push    1000601C                         ; ASCII "TypeInfo\CLSID"
  10001595    68 00000080     push    80000000
  1000159A    FF15 1C500010   call    dword ptr [<&ADVAPI32.RegCreateK>; ADVAPI32.RegCreateKeyA
  100015A0    8D45 0C         lea     eax, dword ptr [ebp+C]
  100015A3    6A 04           push    4
  100015A5    50              push    eax
  100015A6    6A 03           push    3
  100015A8    6A 00           push    0
  100015AA    68 2C600010     push    1000602C                         ; ASCII "{39B6DCDB-01A1-49f0-8609-DB6C815D96BC}"
  100015AF    FF75 08         push    dword ptr [ebp+8]
  100015B2    FF15 18500010   call    dword ptr [<&ADVAPI32.RegSetValu>; ADVAPI32.RegSetValueExA
  100015B8    FF75 08         push    dword ptr [ebp+8]
  100015BB    FF15 24500010   call    dword ptr [<&ADVAPI32.RegCloseKe>; ADVAPI32.RegCloseKey
  100015C1    EB 06           jmp     short 100015C9
  100015C3    8B45 0C         mov     eax, dword ptr [ebp+C]
  100015C6    8320 00         and     dword ptr [eax], 0
  100015C9    33C0            xor     eax, eax
  100015CB    EB 05           jmp     short 100015D2
  100015CD    B8 05400080     mov     eax, 80004005
  100015D2    8DA5 ECFBFFFF   lea     esp, dword ptr [ebp-414]
  100015D8    5F              pop     edi
  100015D9    5E              pop     esi
  100015DA    5B              pop     ebx
  100015DB    C9              leave
  100015DC    C2 0800         retn    8
  
  
--------------------------------------------------------------------------------
四、算法小结

       1、注册码分两部分,“- ”连接。由用户名计算而来。用户名位数必须介于5150之间。

        2、算法1部分计算所得数值转为10进制,即为注册码第一部分。注册码第一部分主要由用户名前4位参与计算而得。

             如果用户名大于9位,则第9,10,11,12可能参与计算(取决于用户名长度,)

        3、算法2部分计算所得数值转为10进制,即为注册码第二部分。注册码第二部分主要由用户名第5,6.7.8或13位开始参与计算而得。
              
             具体参与位数取决于用户名长度。

四、C 语言注册机代码

代码:
#include "stdio.h"
#include "string.h"
int main()
{
 int len, reg1,reg2=0;
 char name[250];
 scanf("%s",name);
 len=strlen(name);
 if (len>=5 && len<=150)
 {
 _asm
 {xor esi,esi
  xor edx,edx
  xor edi,edi
  L0:
  movsx   ebx, byte ptr [name+edi]
  cmp     edx, 4
  jge L011
  push    3
  add     ebx, 10E1h
  pop     ecx
  sub     ecx, edx
  shl     ecx, 3
  shl     ebx, cl
  or      esi, ebx
  jmp L018
  L011:
  push    7
  add     ebx, 4D2h
  pop     ecx
  sub     ecx, edx
  shl     ecx, 3
  shl     ebx, cl
  or      reg2, ebx
  L018:
  inc     edx
  cmp     edx, 8
  jnz L022
  xor     edx, edx
  L022:
  add edi,1
  cmp     byte ptr [name+edi], 0
  jnz L0
  mov reg1,esi
  }
   printf("%d-%d",reg1,reg2);
  }
  else
  printf("用户名至少为5位");
   return 0; 
   }