【破文标题】  豪杰屏幕录像机注册算法分析
【破文作者】  snake
【软件名称】  豪杰屏幕录像机 V2.0 Build 0801
【下载地址】  http://www4.skycn.com/soft/12856.html
【软件简介】  “课件制作”的全新突破,跟踪录制屏幕上所有区域的动作和键盘、鼠标的声音,可保存为
              EXE,AVI,GIF和HSR格式,编码速度快,高保真,也常被应用进行计算机监控管理。
【调试环境】  Windows XP SP2
【作者声明】  只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

【破解过程】

程序安装好后,目录下有一个AuthReg.exe文件,运行后是程序的注册模块,就直接调试它吧。
用PEiD查壳为Microsoft Visual C++ 6.0 [Debug],无壳。

OD载入程序,F9运行输入注册信息
用户名:snake
注册码:1234-5678-9876-5432
确定后弹出注册失败窗口

Ctrl+F2重新载入程序,搜索ASCII串,在此处下断点
 Ultra String Reference Plugin, 条目 13
 Address=00401663
 Disassembly=push    0040A088
 Text String=AuthReg.ini

F9运行,程序断下,F8单步跟踪

00401660  |.  83C4 08       add     esp, 8                           ;  下面部分是读取文件中的内容(略)
00401663  |.  68 88A04000   push    0040A088                         ; /AuthReg.ini
00401668  |.  68 60CC4000   push    0040CC60                         ; |D:\Program Files\hero\AuthReg.ini
0040166D  |.  FF15 10914000 call    [<&KERNEL32.llstrcatA>]           ; \llstrcatA
00401673  |.  33DB          xor     ebxebx
00401675  |.  8BAC24 A80000>mov     ebp, [esp+A8]
0040167C  |.  897424 14     mov     [esp+14], esi
00401680  |.  55            push    ebp                              ; /String
00401681  |.  FF15 F4904000 call    [<&KERNEL32.lstrlenA>]           ; \lstrlenA
00401687  |.  8BF8          mov     edieax
......
004017C8  |> \C605 80CD4000>mov     byte ptr [40CD80], 0
004017CF  |.  E8 1C090000   call    004020F0                         ;  ***跟进***
004017D4  |.  A3 40F84000   mov     [40F840], eax
004017D9  |.  8B4424 00     mov     eax, [esp]
004017DD  |.  85C0          test    eaxeax
004017DF  |.  75 0A         jnz     short 004017EB
004017E1  |.  FF15 B4914000 call    [<&USER32.GetForegroundWindow>]  ; [GetForegroundWindow
004017E7  |.  894424 00     mov     [esp], eax
......

=================    004017CF  |.  E8 1C090000   call    004020F0    ====================

004020F0  /$  81EC 44020000 sub     esp, 244
004020F6  |.  33C0          xor     eaxeax
004020F8  |.  A0 53C74000   mov     al, [40C753]
004020FD  |.  33C9          xor     ecxecx
004020FF  |.  8A0D 52C74000 mov     cl, [40C752]
00402105  |.  56            push    esi
00402106  |.  50            push    eax                              ; /<%02X>
00402107  |.  A1 50C74000   mov     eax, [40C750]                    ; |
......
; 这部分代码的功能是:生成打开注册表键值的字符串
; CLSID\{C0483E67-A363-40C8-BC4C-22EC7419CD21}\Implemented Categories
; 读取该键值下的内容,并还原为输入的注册信息,供程序后面逆计算验证用。
; 此部分代码与算法无关,略。

00402240  |.  8D5424 08     lea     edx, [esp+8]
00402244  |.  85C0          test    eaxeax
00402246  |.  52            push    edx                              ;  假码入栈"1234-5678-9876-5432"
00402247  |.  74 0F         je      short 00402258
00402249  |.  8D4C24 4C     lea     ecx, [esp+4C]
0040224D  |.  51            push    ecx                              ;  用户名入栈"snake"
0040224E  |.  FFD0          call    eax                              ;  ***算法call,跟进***
00402250  |.  5E            pop     esi
00402251  |.  81C4 44020000 add     esp, 244
00402257  |.  C3            retn

================    0040224E  |.  FFD0          call    eax     ====================

100010A0    83EC 20         sub     esp, 20
100010A3    56              push    esi
100010A4    57              push    edi
100010A5    B9 08000000     mov     ecx, 8
100010AA    33C0            xor     eaxeax
100010AC    8D7C24 08       lea     edi, [esp+8]
100010B0    F3:AB           rep     stos dword ptr es:[edi]
100010B2    8B4424 2C       mov     eax, [esp+2C]
100010B6    50              push    eax                              ; 用户名"snake"运算
100010B7    E8 A4010000     call    10001260                         ; ***跟进***
100010BC    83C4 04         add     esp, 4
100010BF    894424 08       mov     [esp+8], eax                     ; 运算结果为 0012FC34  2F 1C 8C 96
100010C3    33F6            xor     esiesi
100010C5    0FBE4434 08     movsx   eaxbyte ptr [esp+esi+8]        ; 读取字符进行计算
100010CA    83F8 41         cmp     eax, 41
100010CD    7C 08           jl      short 100010D7
100010CF    83F8 5A         cmp     eax, 5A
100010D2    7F 03           jg      short 100010D7
100010D4    83C0 20         add     eax, 20
100010D7    50              push    eax
100010D8    E8 33020000     call    10001310
100010DD    83C4 04         add     esp, 4
100010E0    884434 08       mov     [esp+esi+8], al
100010E4    46              inc     esi
100010E5    83FE 04         cmp     esi, 4
100010E8  ^ 7C DB           jl      short 100010C5
100010EA    8B7C24 30       mov     edi, [esp+30]                    ; 计算结果为
100010EE    8D4C24 08       lea     ecx, [esp+8]                     ; 0012FC34  31 33 33 39 串"1339"
100010F2    8BF7            mov     esiedi
100010F4    33D2            xor     edxedx
100010F6    2BF1            sub     esiecx
100010F8    8D4C14 08       lea     ecx, [esp+edx+8]
100010FC    0FBE040E        movsx   eaxbyte ptr [esi+ecx]          ; 生成的串"1339"与假码第一部分"1234"比较
10001100    83F8 41         cmp     eax, 41
10001103    7C 08           jl      short 1000110D
10001105    83F8 5A         cmp     eax, 5A
10001108    7F 03           jg      short 1000110D
1000110A    83C0 20         add     eax, 20
1000110D    0FBE09          movsx   ecxbyte ptr [ecx]
10001110    3BC1            cmp     eaxecx
10001112    0F85 32010000   jnz     1000124A                         ; 关键跳转 nop
10001118    42              inc     edx
10001119    83FA 04         cmp     edx, 4
1000111C  ^ 7C DA           jl      short 100010F8
1000111E    8B4424 08       mov     eax, [esp+8]                     ; eax=39333331
10001122    8D1440          lea     edx, [eax+eax*2]
10001125    8D0C95 09000000 lea     ecx, [edx*4+9]
1000112C    0FAFC8          imul    ecxeax                         ; ecx=17EB8545
1000112F    894C24 0C       mov     [esp+C], ecx                     ; 0012FC38  45 85 EB 17
10001133    33F6            xor     esiesi
10001135    8A5434 0C       mov     dl, [esp+esi+C]                  ; 读取字符进行计算
10001139    52              push    edx
1000113A    56              push    esi
1000113B    E8 80030000     call    100014C0
10001140    25 FF000000     and     eax, 0FF
10001145    50              push    eax
10001146    E8 C5010000     call    10001310
1000114B    83C4 0C         add     esp, 0C                          ; 计算结果为
1000114E    884434 0C       mov     [esp+esi+C], al                  ; 0012FC38  33 62 35 33 串"3b53"
10001152    46              inc     esi
10001153    83FE 04         cmp     esi, 4
10001156  ^ 7C DD           jl      short 10001135
10001158    33C9            xor     ecxecx
1000115A    0FBE440F 05     movsx   eaxbyte ptr [edi+ecx+5]        ; 生成的串"3b53"与假码第二部分"5678"比较
1000115F    83F8 41         cmp     eax, 41
10001162    7C 08           jl      short 1000116C
10001164    83F8 5A         cmp     eax, 5A
10001167    7F 03           jg      short 1000116C
10001169    83C0 20         add     eax, 20
1000116C    0FBE540C 0C     movsx   edxbyte ptr [esp+ecx+C]
10001171    3BC2            cmp     eaxedx
10001173    0F85 D1000000   jnz     1000124A                         ; 关键跳转 nop
10001179    41              inc     ecx
1000117A    83F9 04         cmp     ecx, 4
1000117D  ^ 7C DB           jl      short 1000115A
1000117F    8B4424 0C       mov     eax, [esp+C]                     ; eax=33356233
10001183    8B4C24 08       mov     ecx, [esp+8]                     ; ecx=39333331
10001187    8BD0            mov     edxeax
10001189    33D1            xor     edxecx
1000118B    42              inc     edx
1000118C    0FAFD1          imul    edxecx
1000118F    8D0C80          lea     ecx, [eax+eax*4]
10001192    8D04C8          lea     eax, [eax+ecx*8]
10001195    8D0440          lea     eax, [eax+eax*2]
10001198    03D0            add     edxeax                         ; edx=96984914
1000119A    33F6            xor     esiesi
1000119C    895424 10       mov     [esp+10], edx                    ; 0012FC3C  14 49 98 96
100011A0    0FBE4C34 10     movsx   ecxbyte ptr [esp+esi+10]       ; 读取字符进行计算
100011A5    51              push    ecx
100011A6    E8 65010000     call    10001310
100011AB    83C4 04         add     esp, 4                           ; 计算结果为
100011AE    884434 10       mov     [esp+esi+10], al                 ; 0012FC3C  35 69 37 39 串"5i79"
100011B2    46              inc     esi
100011B3    83FE 04         cmp     esi, 4
100011B6  ^ 7C E8           jl      short 100011A0
100011B8    33C9            xor     ecxecx
100011BA    0FBE440F 0A     movsx   eaxbyte ptr [edi+ecx+A]        ; 生成的串"5i79"与假码第三部分"9876"比较
100011BF    83F8 41         cmp     eax, 41
100011C2    7C 08           jl      short 100011CC
100011C4    83F8 5A         cmp     eax, 5A
100011C7    7F 03           jg      short 100011CC
100011C9    83C0 20         add     eax, 20
100011CC    0FBE540C 10     movsx   edxbyte ptr [esp+ecx+10]
100011D1    3BC2            cmp     eaxedx
100011D3    75 75           jnz     short 1000124A                   ; 关键跳转 nop
100011D5    41              inc     ecx
100011D6    83F9 04         cmp     ecx, 4
100011D9  ^ 7C DF           jl      short 100011BA
100011DB    8B4424 0C       mov     eax, [esp+C]                     ; eax=33356233
100011DF    8B4C24 08       mov     ecx, [esp+8]                     ; ecx=39333331
100011E3    0FAFC1          imul    eaxecx
100011E6    8D14C5 00000000 lea     edx, [eax*8]
100011ED    2BD0            sub     edxeax
100011EF    8D0489          lea     eax, [ecx+ecx*4]
100011F2    83C2 05         add     edx, 5
100011F5    0FAF5424 10     imul    edx, [esp+10]                    ; [esp+10]的值为39376935
100011FA    03D0            add     edxeax                         ; edx=DC46A197
100011FC    33F6            xor     esiesi
100011FE    895424 14       mov     [esp+14], edx                    ; 0012FC40  97 A1 46 DC
10001202    0FBE4C34 14     movsx   ecxbyte ptr [esp+esi+14]       ; 读取字符进行计算
10001207    51              push    ecx
10001208    E8 03010000     call    10001310
1000120D    83C4 04         add     esp, 4                           ; 计算结果为
10001210    884434 14       mov     [esp+esi+14], al                 ; 0012FC40  39 31 66 73 串"91fs"
10001214    46              inc     esi
10001215    83FE 04         cmp     esi, 4
10001218  ^ 7C E8           jl      short 10001202
1000121A    33C9            xor     ecxecx
1000121C    0FBE440F 0F     movsx   eaxbyte ptr [edi+ecx+F]        ; 生成的串"91fs"与假码第四部分"5432"比较
10001221    83F8 41         cmp     eax, 41
10001224    7C 08           jl      short 1000122E
10001226    83F8 5A         cmp     eax, 5A
10001229    7F 03           jg      short 1000122E
1000122B    83C0 20         add     eax, 20
1000122E    0FBE540C 14     movsx   edxbyte ptr [esp+ecx+14]
10001233    3BC2            cmp     eaxedx
10001235    75 13           jnz     short 1000124A                   ; 关键跳转 nop
10001237    41              inc     ecx
10001238    83F9 04         cmp     ecx, 4
1000123B  ^ 7C DF           jl      short 1000121C
1000123D    5F              pop     edi
1000123E    B8 01000000     mov     eax, 1                           ; 验证通过返回值eax=1
10001243    5E              pop     esi
10001244    83C4 20         add     esp, 20
10001247    C2 0800         retn    8
1000124A    5F              pop     edi                              ; ntdll.7C930738
1000124B    33C0            xor     eaxeax
1000124D    5E              pop     esi
1000124E    83C4 20         add     esp, 20
10001251    C2 0800         retn    8

================    100010B7    E8 A4010000     call    10001260    =================

10001260    81EC 00020000   sub     esp, 200
10001266    B9 80000000     mov     ecx, 80
1000126B    33C0            xor     eaxeax
1000126D    53              push    ebx
1000126E    55              push    ebp
1000126F    56              push    esi
10001270    8BB424 10020000 mov     esi, [esp+210]
10001277    57              push    edi
10001278    8D7C24 10       lea     edi, [esp+10]
1000127C    F3:AB           rep     stos dword ptr es:[edi]
1000127E    56              push    esi                              ; 用户名"snake"
1000127F    33ED            xor     ebpebp
10001281    FF15 04600010   call    [<&KERNEL32.lstrlenA>]           ; kernel32.lstrlenA
10001287    8BD8            mov     ebxeax                         ; 长度 5
10001289    81FB 00020000   cmp     ebx, 200
1000128F    76 12           jbe     short 100012A3                   ; 判断长度有效性
10001291    B9 80000000     mov     ecx, 80
10001296    8D7C24 10       lea     edi, [esp+10]
1000129A    BB 00020000     mov     ebx, 200
1000129F    F3:A5           rep     movs dword ptr es:[edi], dword p>
100012A1    EB 0C           jmp     short 100012AF
100012A3    8D4424 10       lea     eax, [esp+10]
100012A7    56              push    esi
100012A8    50              push    eax
100012A9    FF15 84600010   call    [<&KERNEL32.lstrcpyA>]           ; kernel32.lstrcpyA
100012AF    8BC3            mov     eaxebx                         ; eax=ebx=5 用户名长度
100012B1    99              cdq
100012B2    83E2 03         and     edx, 3
100012B5    03C2            add     eaxedx
100012B7    8BF8            mov     edieax
100012B9    C1FF 02         sar     edi, 2
100012BC    F6C3 03         test    bl, 3
100012BF    74 01           je      short 100012C2
100012C1    47              inc     edi                              ; edi=2
100012C2    33C9            xor     ecxecx
100012C4    85DB            test    ebxebx
100012C6    7E 17           jle     short 100012DF
100012C8    8A540C 10       mov     dl, [esp+ecx+10]                 ; 依次读取用户名字符并运算
100012CC    52              push    edx
100012CD    51              push    ecx
100012CE    E8 ED010000     call    100014C0
100012D3    83C4 08         add     esp, 8
100012D6    88440C 10       mov     [esp+ecx+10], al
100012DA    41              inc     ecx
100012DB    3BCB            cmp     ecxebx
100012DD  ^ 7C E9           jl      short 100012C8
; 该循环过后的运算结果
; 0012FCA8  73 6E 61 6B 65 00                                snake.
; ----->转换为
; 0012FA24  B9 37 18 2D A6 00 00 00                          ?-?....
100012DF    33F6            xor     esiesi
100012E1    85FF            test    ediedi
100012E3    7E 1C           jle     short 10001301
100012E5    8B5CB4 10       mov     ebx, [esp+esi*4+10]              ; ebx=2D1837B9,000000A6
100012E9    8BC6            mov     eaxesi
100012EB    83E0 1F         and     eax, 1F
100012EE    03EB            add     ebpebx
100012F0    50              push    eax
100012F1    55              push    ebp
100012F2    E8 99020000     call    10001590
100012F7    83C4 08         add     esp, 8                           ; eax=2D1837B9,968C1C2F
100012FA    46              inc     esi
100012FB    3BF7            cmp     esiedi                         ; edi=2
100012FD    8BE8            mov     ebpeax
100012FF  ^ 7C E4           jl      short 100012E5
10001301    5F              pop     edi                              ; 0012FC54
10001302    8BC5            mov     eaxebp                         ; eax=968C1C2F
10001304    5E              pop     esi
10001305    5D              pop     ebp
10001306    5B              pop     ebx
10001307    81C4 00020000   add     esp, 200
1000130D    C3              retn

【汇编注册机算法部分源码】

.data?
szName    db  64 dup (?)
szSerial  db  32 dup (?)
.code
calculat  proc
  xor  eax,eax
  xor  ecx,ecx
@@:
  mov  al,[esi+ecx]
  push  ecx
@2:
  test  al,0C3h
  jpe  @1
  stc
@1:
  rcr  al,1
  dec  cl
  jnz  @2
  pop  ecx
  mov  [esi+ecx],al
  inc  ecx
  cmp  ecx,ebx
  jl  @b
  ret
calculat  endp

convert    proc  nNum:DWORD
  mov  eax,nNum
L000:
  and  eax,7Fh
  cmp  eax,41h
  jl  L006
  cmp  eax,5Ah
  jg  L006
  or  al,20h
L006:
  cmp  eax,6Fh
  jnz  L012
  mov  eax,90h
  xor  eax,0Eh
  or  al,31h
  jmp  L000
L012:
  cmp  eax,30h
  jnz  L018
  mov  eax,0CFh
  xor  eax,0Eh
  or  al,31h
  jmp  L000
L018:
  cmp  eax,61h
  jl  L022
  cmp  eax,7Ah
  jle  L030
L022:
  cmp  eax,31h
  jl  L026
  cmp  eax,39h
  jle     L030
L026:
  xor  eax,0Eh
  or  al,31h
  jmp  L000
L030:  
  ret
convert    endp

GetRegKey  proc  hDlg
  pushad
  invoke  RtlZeroMemory,addr szName,sizeof szName
  invoke  GetDlgItemText,hDlg,IDC_NAME,addr szName,sizeof szName
  .if  eax
    lea  esi,szName
    mov  ebx,eax
    sar  eax,2
    inc  eax
    push  eax
    call  calculat
    pop  ebx
    xor  eax,eax
    xor  ecx,ecx
  @@:
    mov  edx,[esi+ecx*4]
    add  edx,eax
    ror  edx,cl
    mov  eax,edx
    inc  ecx
    cmp  ecx,ebx
    jl  @b
    mov  [esi],eax
    xor  eax,eax
    xor  ecx,ecx
  @@:
    mov  al,[esi+ecx]
    cmp  al,41h
    jl  @3
    cmp  al,5Ah
    jg  @3
    add  al,20h
  @3:
    invoke  convert,eax
    mov  [esi+ecx],al
    inc  ecx
    cmp  ecx,4
    jl  @b
    mov  WORD ptr [esi+ecx],2Dh
    lea  edi,szSerial
    invoke  lstrcpy,edi,esi
    mov  eax,[esi]
    push  eax
    push  eax
    lea  edx,[eax+eax*2]
    lea  ecx,[edx*4+9]
    imul  ecx,eax
    mov  [esi],ecx
    mov  ebx,4
    call  calculat
    xor  eax,eax
    xor  ecx,ecx
  @@:
    mov  al,[esi+ecx]
    invoke  convert,eax
    mov  [esi+ecx],al
    inc  ecx
    cmp  ecx,4
    jl  @b
    mov  WORD ptr [esi+ecx],2Dh
    invoke  lstrcat,edi,esi
    pop  ecx
    mov  eax,[esi]
    push  eax
    mov  edx,eax
    xor  edx,ecx
    inc  edx
    imul  edx,ecx
    lea  ecx,[eax+eax*4]
    lea  eax,[eax+ecx*8]
    lea  eax,[eax+eax*2]
    add  edx,eax
    mov  [esi],edx
    xor  eax,eax
    xor  ecx,ecx
  @@:
    mov  al,[esi+ecx]
    invoke  convert,eax
    mov  [esi+ecx],al
    inc  ecx
    cmp  ecx,4
    jl  @b
    mov  WORD ptr [esi+ecx],2Dh
    invoke  lstrcat,edi,esi
    pop  eax
    pop  ecx
    mov  ebx,[esi]
    imul  eax,ecx
    lea  edx,[eax*8]
    sub  edx,eax
    lea  eax,[ecx+ecx*4]
    add  edx,5
    imul  edx,ebx
    add  edx,eax
    mov  [esi],edx
    xor  eax,eax
    xor  ecx,ecx
  @@:
    mov  al,[esi+ecx]
    invoke  convert,eax
    mov  [esi+ecx],al
    inc  ecx
    cmp  ecx,4
    jl  @b
    mov  WORD ptr [esi+ecx],0
    invoke  lstrcat,edi,esi    
    invoke  SetDlgItemText,hDlg,IDC_REG,edi
  .else
    invoke  SetDlgItemText,hDlg,IDC_REG,CTXT("请输入用户名!")
  .endif
  popad
  ret
GetRegKey  endp

【版权声明】  本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!