【破文标题】  ScreenFlash V1.7 注册算法分析
【破文作者】  snake
【软件名称】  ScreenFlash
【下载地址】  http://unflash.com/
【调试环境】  Windows XP + SP2
【作者声明】  只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

【破解过程】
用PEiD查壳为Microsoft Visual C++ 7.0 [Debug],无壳。

运行程序输入注册信息
Name: snake
Activation: 123456789ABC
点“Activate”按钮后提示错误信息,并把注册信息写入到注册表中

OD载入程序,下断bp RegQueryValueExA,F9运行,断下,连续按N次F9,直到堆栈显示内容为
0012D8F4   005E0E2C  /CALL 到 RegQueryValueExA 来自 SFlash.005E0E2A
0012D8F8   000000A8  |hKey = A8
0012D8FC   00DD6EB0  |ValueName = "sn"
0012D900   00000000  |Reserved = NULL
0012D904   0012D920  |pValueType = 0012D920
0012D908   00DD5E58  |Buffer = 00DD5E58
0012D90C   0012D91C  \pBufSize = 0012D91C
F2取消断点,Alt+F9返回程序领空,N次F8到004C6B2C处,算法验证处

004C6B2C   > \8B4C24 14     mov     ecx, [esp+14]                    ;  用户名
004C6B30   .  8B41 F4       mov     eax, [ecx-C]
004C6B33   .  85C0          test    eaxeax
004C6B35   .  0F8E EC010000 jle     004C6D27                         ;  不能为空
004C6B3B   .  8B5424 20     mov     edx, [esp+20]                    ;  注册码
004C6B3F   .  837A F4 0C    cmp     dword ptr [edx-C], 0C            ;  为12位字符串
004C6B43   .  0F85 DE010000 jnz     004C6D27
004C6B49   .  6A 04         push    4
004C6B4B   .  8D4424 2C     lea     eax, [esp+2C]
004C6B4F   .  50            push    eax
004C6B50   .  8D4C24 28     lea     ecx, [esp+28]
004C6B54   .  E8 27E1F4FF   call    00414C80
004C6B59   .  C64424 74 0D  mov     byte ptr [esp+74], 0D
004C6B5E   .  8D4C24 20     lea     ecx, [esp+20]
004C6B62   .  51            push    ecx
004C6B63   .  8D4C24 14     lea     ecx, [esp+14]
004C6B67   .  E8 64B9F3FF   call    004024D0
004C6B6C   .  C64424 74 0E  mov     byte ptr [esp+74], 0E
004C6B71   .  8B5424 10     mov     edx, [esp+10]
004C6B75   .  8B4C24 14     mov     ecx, [esp+14]
004C6B79   .  8B42 F4       mov     eax, [edx-C]
004C6B7C   .  8B71 F4       mov     esi, [ecx-C]
004C6B7F   .  50            push    eax
004C6B80   .  8D4C24 14     lea     ecx, [esp+14]
004C6B84   .  E8 97B9F3FF   call    00402520
004C6B89   .  50            push    eax
004C6B8A   .  56            push    esi
004C6B8B   .  8D4C24 1C     lea     ecx, [esp+1C]
004C6B8F   .  E8 8CB9F3FF   call    00402520
004C6B94   .  8BF8          mov     edieax
004C6B96   .  E8 85DFFFFF   call    004C4B20                         ;  算法验证call
;根据前4位注册码生成最后4位注册码,并与假码的最后4位相比较,al=1继续验证
{{{
004C4B20  /$  81EC 18010000 sub     esp, 118
004C4B26  |.  A1 00156900   mov     eax, [691500]
004C4B2B  |.  53            push    ebx
004C4B2C  |.  55            push    ebp
004C4B2D  |.  8BAC24 240100>mov     ebp, [esp+124]
004C4B34  |.  56            push    esi
004C4B35  |.  8D7424 20     lea     esi, [esp+20]
004C4B39  |.  898424 200100>mov     [esp+120], eax
004C4B40  |.  E8 5BFFFFFF   call    004C4AA0                         ;  生成长字符串

"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCD"

004C4B45  |.  803F 00       cmp     byte ptr [edi], 0
004C4B48  |.  74 0E         je      short 004C4B58
004C4B4A  |.  8BC7          mov     eaxedi
004C4B4C  |.  8D6424 00     lea     esp, [esp]
004C4B50  |>  8A48 01       /mov     cl, [eax+1]
004C4B53  |.  40            |inc     eax
004C4B54  |.  84C9          |test    clcl
004C4B56  |.^ 75 F8         \jnz     short 004C4B50
004C4B58  |>  8BC5          mov     eaxebp
004C4B5A  |.  8B08          mov     ecx, [eax]
004C4B5C  |.  8B50 04       mov     edx, [eax+4]
004C4B5F  |.  8B40 08       mov     eax, [eax+8]
004C4B62  |.  894C24 10     mov     [esp+10], ecx
004C4B66  |.  895424 14     mov     [esp+14], edx
004C4B6A  |.  894424 18     mov     [esp+18], eax
004C4B6E  |.  33C9          xor     ecxecx
004C4B70  |>  8A540C 20     /mov     dl, [esp+ecx+20]                ;  取前4位注册码分别在长字符串中的索引值
004C4B74  |.  33C0          |xor     eaxeax
004C4B76  |>  385404 10     |/cmp     [esp+eax+10], dl
004C4B7A  |.  75 04         ||jnz     short 004C4B80
004C4B7C  |.  884C04 0C     ||mov     [esp+eax+C], cl                ;  保存索引值
004C4B80  |>  40            ||inc     eax
004C4B81  |.  83F8 04       ||cmp     eax, 4
004C4B84  |.^ 7C F0         |\jl      short 004C4B76
004C4B86  |.  41            |inc     ecx
004C4B87  |.  83F9 24       |cmp     ecx, 24
004C4B8A  |.^ 7C E4         \jl      short 004C4B70
004C4B8C  |.  8A4424 0F     mov     al, [esp+F]
004C4B90  |.  8A5424 0E     mov     dl, [esp+E]
004C4B94  |.  8B4C24 0C     mov     ecx, [esp+C]
004C4B98  |.  8AD8          mov     blal
004C4B9A  |.  02DA          add     bldl
004C4B9C  |.  02DD          add     blch
004C4B9E  |.  02D9          add     blcl
004C4BA0  |.  0FB6F3        movzx   esibl                          ;  4个索引值相运算
004C4BA3  |.  8A5D 08       mov     bl, [ebp+8]                      ;  取注册码第9位
004C4BA6  |.  3A5C34 20     cmp     bl, [esp+esi+20]                 ;  与长串中的值比较
004C4BAA  |.  74 18         je      short 004C4BC4                   ;  关键跳转 jmp
004C4BAC  |>  5E            pop     esi
004C4BAD  |.  5D            pop     ebp
004C4BAE  |.  32C0          xor     alal
004C4BB0  |.  5B            pop     ebx
004C4BB1  |.  8B8C24 140100>mov     ecx, [esp+114]
004C4BB8  |.  E8 51270A00   call    0056730E
004C4BBD  |.  81C4 18010000 add     esp, 118
004C4BC3  |.  C3            retn
004C4BC4  |>  8ADA          mov     bldl
004C4BC6  |.  2AD8          sub     blal
004C4BC8  |.  02DD          add     blch
004C4BCA  |.  02D9          add     blcl
004C4BCC  |.  80C3 24       add     bl, 24
004C4BCF  |.  0FB6F3        movzx   esibl                          ;  4个索引值相运算
004C4BD2  |.  8A5D 09       mov     bl, [ebp+9]                      ;  取注册码第10位
004C4BD5  |.  3A5C34 20     cmp     bl, [esp+esi+20]                 ;  与长串中的值比较
004C4BD9  |.^ 75 D1         jnz     short 004C4BAC                   ;  关键跳转 nop
004C4BDB  |.  8ADD          mov     blch
004C4BDD  |.  2AD8          sub     blal
004C4BDF  |.  2ADA          sub     bldl
004C4BE1  |.  02D9          add     blcl
004C4BE3  |.  80C3 48       add     bl, 48
004C4BE6  |.  0FB6F3        movzx   esibl                          ;  4个索引值相运算
004C4BE9  |.  8A5D 0A       mov     bl, [ebp+A]                      ;  取注册码第11位
004C4BEC  |.  3A5C34 20     cmp     bl, [esp+esi+20]                 ;  与长串中的值比较
004C4BF0  |.^ 75 BA         jnz     short 004C4BAC                   ;  关键跳转 nop
004C4BF2  |.  2AC5          sub     alch
004C4BF4  |.  02C2          add     aldl
004C4BF6  |.  8A55 0B       mov     dl, [ebp+B]                      ;  取注册码第12位
004C4BF9  |.  02C1          add     alcl
004C4BFB  |.  04 24         add     al, 24
004C4BFD  |.  0FB6C8        movzx   ecxal                          ;  4个索引值相运算
004C4C00  |.  8A440C 20     mov     al, [esp+ecx+20]
004C4C04  |.  8B8C24 200100>mov     ecx, [esp+120]
004C4C0B  |.  5E            pop     esi
004C4C0C  |.  3AD0          cmp     dlal                           ;  与长串中的值比较
004C4C0E  |.  5D            pop     ebp
004C4C0F  |.  0F94C0        sete    al                               ;  al=1
004C4C12  |.  5B            pop     ebx
004C4C13  |.  E8 F6260A00   call    0056730E
004C4C18  |.  81C4 18010000 add     esp, 118
004C4C1E  \.  C3            retn
}}}
004C6B9B   .  83C4 04       add     esp, 4
004C6B9E   .  84C0          test    alal
004C6BA0   .  0F84 66010000 je      004C6D0C                         ;  关键跳转 nop
004C6BA6   .  8B5424 14     mov     edx, [esp+14]
004C6BAA   .  8B42 F4       mov     eax, [edx-C]
004C6BAD   .  50            push    eax
004C6BAE   .  8D4C24 18     lea     ecx, [esp+18]
004C6BB2   .  E8 69B9F3FF   call    00402520
004C6BB7   .  8D5C24 60     lea     ebx, [esp+60]
004C6BBB   .  8BF8          mov     edieax                         ;  用户名"snake"
004C6BBD   .  E8 5EE0FFFF   call    004C4C20                         ;  算法call,由用户名生成4位的字符串
{{{
004C4C20  /$  81EC 04010000 sub     esp, 104
004C4C26  |.  A1 00156900   mov     eax, [691500]
004C4C2B  |.  56            push    esi
004C4C2C  |.  8D7424 04     lea     esi, [esp+4]
004C4C30  |.  898424 040100>mov     [esp+104], eax
004C4C37  |.  E8 64FEFFFF   call    004C4AA0                         ;  生成长字符串
004C4C3C  |.  8A07          mov     al, [edi]
004C4C3E  |.  33C9          xor     ecxecx
004C4C40  |.  84C0          test    alal
004C4C42  |.  B2 20         mov     dl, 20
004C4C44  |.  74 09         je      short 004C4C4F
004C4C46  |>  8A4439 01     /mov     al, [ecx+edi+1]                 ;  计算用户名长度
004C4C4A  |.  41            |inc     ecx
004C4C4B  |.  84C0          |test    alal
004C4C4D  |.^ 75 F7         \jnz     short 004C4C46
004C4C4F  |>  33C0          xor     eaxeax
004C4C51  |.  85C9          test    ecxecx
004C4C53  |.  7E 08         jle     short 004C4C5D
004C4C55  |>  021438        /add     dl, [eax+edi]                   ;  分别取用户名的ASCII值进行运算
004C4C58  |.  40            |inc     eax
004C4C59  |.  3BC1          |cmp     eaxecx
004C4C5B  |.^ 7C F8         \jl      short 004C4C55
004C4C5D  |>  0FB6C2        movzx   eaxdl                          ;  运算结果
004C4C60  |.  8A4404 04     mov     al, [esp+eax+4]                  ;  al='O'
004C4C64  |.  33F6          xor     esiesi
004C4C66  |.  85C9          test    ecxecx
004C4C68  |.  8803          mov     [ebx], al
004C4C6A  |.  A2 1C466D00   mov     [6D461C], al
004C4C6F  |.  B2 40         mov     dl, 40
004C4C71  |.  7E 0C         jle     short 004C4C7F
004C4C73  |>  8A043E        /mov     al, [esi+edi]                   ;  分别取用户名的ASCII值进行运算
004C4C76  |.  F6EA          |imul    dl
004C4C78  |.  46            |inc     esi
004C4C79  |.  3BF1          |cmp     esiecx
004C4C7B  |.  8AD0          |mov     dlal
004C4C7D  |.^ 7C F4         \jl      short 004C4C73
004C4C7F  |>  0FB6D2        movzx   edxdl                          ;  运算结果
004C4C82  |.  8A4414 04     mov     al, [esp+edx+4]                  ;  al='U'
004C4C86  |.  8843 01       mov     [ebx+1], al
004C4C89  |.  A2 1D466D00   mov     [6D461D], al
004C4C8E  |.  33C0          xor     eaxeax
004C4C90  |.  85C9          test    ecxecx
004C4C92  |.  B2 80         mov     dl, 80
004C4C94  |.  5E            pop     esi
004C4C95  |.  7E 08         jle     short 004C4C9F
004C4C97  |>  2A1438        /sub     dl, [eax+edi]                   ;  分别取用户名的ASCII值进行运算
004C4C9A  |.  40            |inc     eax
004C4C9B  |.  3BC1          |cmp     eaxecx
004C4C9D  |.^ 7C F8         \jl      short 004C4C97
004C4C9F  |>  8A0C0C        mov     cl, [esp+ecx]                    ;  cl='F'
004C4CA2  |.  0FB6C2        movzx   eaxdl
004C4CA5  |.  8A0404        mov     al, [esp+eax]                    ;  al='C'
004C4CA8  |.  8843 02       mov     [ebx+2], al
004C4CAB  |.  A2 1E466D00   mov     [6D461E], al
004C4CB0  |.  884B 03       mov     [ebx+3], cl                      ;  最终结果为
004C4CB3  |.  880D 1F466D00 mov     [6D461F], cl                     ;  006D461C  4F 55 43 46 串"OUCF"
004C4CB9  |.  8B8C24 000100>mov     ecx, [esp+100]
004C4CC0  |.  E8 49260A00   call    0056730E
004C4CC5  |.  81C4 04010000 add     esp, 104
004C4CCB  \.  C3            retn
}}}
004C6BC2   .  6A 04         push    4
004C6BC4   .  8D4424 30     lea     eax, [esp+30]
004C6BC8   .  50            push    eax
004C6BC9   .  8D4C24 28     lea     ecx, [esp+28]
004C6BCD   .  E8 1EBAF3FF   call    004025F0
004C6BD2   .  C64424 74 0F  mov     byte ptr [esp+74], 0F
004C6BD7   .  50            push    eax
004C6BD8   .  8D4C24 14     lea     ecx, [esp+14]
004C6BDC   .  E8 1FBBF3FF   call    00402700
004C6BE1   .  C64424 74 0E  mov     byte ptr [esp+74], 0E
004C6BE6   .  8D4C24 2C     lea     ecx, [esp+2C]
004C6BEA   .  E8 41B8F3FF   call    00402430
004C6BEF   .  8B4C24 10     mov     ecx, [esp+10]                    ;  取注册码前4位
004C6BF3   .  8B41 F4       mov     eax, [ecx-C]
004C6BF6   .  50            push    eax
004C6BF7   .  8D4C24 14     lea     ecx, [esp+14]
004C6BFB   .  C64424 68 00  mov     byte ptr [esp+68], 0
004C6C00   .  8BF3          mov     esiebx                         ;  取由用户名生成的字符串
004C6C02   .  E8 19B9F3FF   call    00402520
004C6C07   >  8A10          mov     dl, [eax]                        ;  逐位比较相等则验证通过
004C6C09   .  8A1E          mov     bl, [esi]
004C6C0B   .  8ACA          mov     cldl
004C6C0D   .  3AD3          cmp     dlbl
004C6C0F   .  75 1E         jnz     short 004C6C2F                   ;  关键跳转 nop
004C6C11   .  84C9          test    clcl
004C6C13   .  74 16         je      short 004C6C2B
004C6C15   .  8A50 01       mov     dl, [eax+1]
004C6C18   .  8A5E 01       mov     bl, [esi+1]
004C6C1B   .  8ACA          mov     cldl
004C6C1D   .  3AD3          cmp     dlbl
004C6C1F   .  75 0E         jnz     short 004C6C2F                   ;  关键跳转 nop
004C6C21   .  83C0 02       add     eax, 2
004C6C24   .  83C6 02       add     esi, 2
004C6C27   .  84C9          test    clcl
004C6C29   .^ 75 DC         jnz     short 004C6C07
004C6C2B   >  33C0          xor     eaxeax
004C6C2D   .  EB 04         jmp     short 004C6C33                   ;  中间4位注册码为任意值
004C6C2F   >  1BC0          sbb     eaxeax
004C6C31   .  1BC5          sbb     eaxebp
004C6C33   >  85C0          test    eaxeax
004C6C35   .  0F85 CF000000 jnz     004C6D0A
......

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

.data
szTable    db  "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ01"
    db  "23456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRST"
    db  "UVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKL"
    db  "MNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCD",0
.data?
szName    dd  32 dup (?)
szSerial  db  16 dup (?)
szTmp    db  8  dup (?)
nCon    dd  ?

.code
GetRegKey  proc  hDlg
  pushad
  invoke  GetDlgItemText,hDlg,IDC_NAME,addr szName,sizeof szName
  .if  eax
    mov  nCon,eax
    lea  esi,szTable
    mov  dl,[esi+eax]
    mov  [szSerial+3],dl
    xor  edx,edx
    lea  edi,szName
  @@:
    add  dl,[edi+eax-1]
    dec  eax
    jnz  @b
    cmp  dl,80h
    ja  @1
    mov  ecx,80h
    sub  ecx,edx
    jmp  @2
  @1:
    mov  ecx,180h
    sub  ecx,edx
  @2:
    mov  dl,[esi+ecx]
    mov  [szSerial+2],dl
    mov  ecx,nCon
    xor  ebx,ebx
    mov  dl,40h
  @@:
    mov  al,[edi+ebx]
    imul  dl
    mov  dl,al
    inc  ebx
    dec  ecx
    jnz  @b
    mov  al,[esi+edx]
    mov  [szSerial+1],al
    xor  edx,edx
    mov  ecx,nCon
  @@:
    sub  dl,[edi+ecx-1]
    dec  ecx
    jnz  @b
    cmp  dl,20h
    ja  @3
    mov  ecx,20h
    sub  ecx,edx
    jmp  @4
  @3:
    mov  ecx,120h
    sub  ecx,edx
  @4:
    mov  dl,[esi+ecx]
    mov  [szSerial],dl    
    lea  edi,szSerial
    lea  ebx,szTmp
    xor  ecx,ecx
  @@:
    mov  dl,[esi+ecx]
    xor  eax,eax
  @6:
    cmp  dl,[edi+eax]
    jnz  @5
    mov  [ebx+eax],cl
  @5:
    inc  eax
    cmp  eax,4
    jl  @6
    inc  ecx
    cmp  ecx,24h
    jl  @b
    xor  edx,edx
    mov  ecx,4
  @@:
    add  dl,[ebx+ecx-1]
    dec  ecx
    jnz  @b
    mov  dl,[esi+edx]
    mov  [szSerial+8],dl    
    mov  dl,[ebx+2]
    sub  dl,[ebx+3]
    add  dl,[ebx+1]
    add  dl,[ebx]
    add  dl,24h
    mov  dl,[esi+edx]
    mov  [szSerial+9],dl    
    mov  dl,[ebx+1]
    sub  dl,[ebx+3]
    sub  dl,[ebx+2]
    add  dl,[ebx]
    add  dl,48h
    mov  dl,[esi+edx]
    mov  [szSerial+0Ah],dl    
    mov  dl,[ebx+3]
    sub  dl,[ebx+1]
    add  dl,[ebx+2]
    add  dl,[ebx]
    add  dl,24h    
    mov  dl,[esi+edx]
    mov  [szSerial+0Bh],dl
    invoke  GetTickCount
    and  eax,3Fh
    mov  ecx,4
  @@:
    mov  dl,[esi+eax]
    mov  [szSerial+3+ecx],dl
    add  eax,7
    dec  ecx
    jnz  @b
    invoke  SetDlgItemText,hDlg,IDC_REG,addr szSerial
  .else
    invoke  SetDlgItemText,hDlg,IDC_REG,CTXT("Please Enter the Name!")
  .endif
  popad
  ret
GetRegKey  endp

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