• 标 题: 【原创】WinImage 7.0 序列号算法
  • 作 者:lionel
  • 时 间:2005-01-20 13:36

TITLE  : WinImage 7.0 序列号算法
AUTHOR : lionel@nkbbs.org
WEBLOG : http://lionel.blogchina.com/
DATE   : 01/19/2005

SOFTWARE : WinImage Version 7.0.7000
COMPANY  : Gilles Vollant
HOMEPAGE : http://www.winimage.com/

CONTEXT : WinImage使用的序列号算法应该是自创的,所以算法比较简单,只是对用户

    名进行了简单的四则运算,每一个用户名应该可以有10种不同的序列号可用,下面

    是对用户名进行运算的代码:

    初始化时,ECX = 0,[EBP - 4] = 0x47694C

0044883C   /MOV EAX,ECX                        ; eax = 0
0044883E   |PUSH 0E
00448840   |CDQ                                ; edx = 0
00448841   |POP EBX                            ; ebx = 0x0E
00448842   |IDIV EBX                           ; edx = eax % ebx
00448844   |TEST EDX,EDX                       ; eax = eax / ebx
00448846   |JNZ SHORT winimage.0044884B
00448848   |PUSH 27
0044884A   |POP ESI                            ; esi = 0x27
0044884B   |LEA EAX,DWORD PTR DS:[ECX+3]       ; eax = ecx + 3
0044884E   |MOVZX EDX,BYTE PTR DS:[EDI+EAX]    ; edx = user_name[ecx]
00448852   |IMUL EDX,ESI                       ; edx = edx * esi
00448855   |ADD DWORD PTR SS:[EBP-4],EDX       ; [EBP-4] += edx
00448858   |PUSH 0E
0044885A   |CDQ                                ; edx = 0
0044885B   |POP EBX                            ; ebx = 0x0E
0044885C   |IDIV EBX                           ; edx = eax % ebx
0044885E   |TEST EDX,EDX                       ; eax = eax / ebx
00448860   |JE SHORT winimage.00448867
00448862   |LEA ESI,DWORD PTR DS:[ESI+ESI*2]   ; esi = esi * 3
00448865   |JMP SHORT winimage.0044886A
00448867   |IMUL ESI,ESI,7                     ; esi = esi * 7
0044886A   |INC ECX
0044886B   |CMP ECX,DWORD PTR SS:[EBP-8]       ; [ebp-8] = strlen(user_name)
0044886E   \JL SHORT winimage.0044883C

    经过上述运算,如果user_name = "lionel"的话,那么运算后[ebp-4] = 0x579453

    程序在这里还有一处判断,就是[ebp-4] != 0xB8DCDD26,但我不清楚什么用户名能

    算出来这种结果。

    下面对刚算出来的结果进一步计算,总共有10步,但每一步的算法都是一样的:

    这里我们把刚刚算出来的结果记作val0 = 0x579453

0044887F    PUSH DWORD PTR SS:[EBP+C]                ; /val0
00448882    MOV ESI,DWORD PTR SS:[EBP+8]             ; |
00448885    LEA EAX,DWORD PTR SS:[EBP-10]            ; |
00448888    PUSH winimage.0045A2D0                   ; |Format = "%lX"
0044888D    PUSH EAX                                 ; |buf
0044888E    CALL DWORD PTR DS:[<&USER32.wsprintfA>]  ; \wsprintfA
00448894    MOV AL,BYTE PTR SS:[EBP-10]
00448897    ADD ESP,0C
0044889A    TEST AL,AL
0044889C    JE SHORT winimage.004488BB
0044889E    LEA ECX,DWORD PTR SS:[EBP-10]
004488A1    SUB ECX,ESI
004488A3    /CMP AL,38                               ; if(al == '8')
004488A5    |JNZ SHORT winimage.004488AB             ;    al += 0x0A;
004488A7    |ADD AL,0A
004488A9    |JMP SHORT winimage.004488B1
004488AB    |CMP AL,42                               ; else if(al == 0x42)
004488AD    |JNZ SHORT winimage.004488B1             ;    al -= 0x0A;
004488AF    |ADD AL,0F6
004488B1    |MOV BYTE PTR DS:[ESI],AL
004488B3    |INC ESI
004488B4    |MOV AL,BYTE PTR DS:[ECX+ESI]
004488B7    |TEST AL,AL
004488B9    \JNZ SHORT winimage.004488A3

    其实上面的运算就是把 val0中的 8替换成B,把 B换成 8,然后与输入的序列号进

    行比较;如果不相等,那么val1 = val0 + 0x14051948,再进行上面的替换,然后

    比较;如果还不相等,那么val2 = val1 + 0x17061954,再进行上面的替换,然后

    比较;算上第一次,总共是比较了10次,这10次中,每次加上的常量分别是:
    0x00000000 0x14051948 0x17061954 0x10051981 0x40111995
    0x20611997 0x12091999 0x16062004 0x21042002 0x13062004

    大家可以看出,后面 4位竟然都是年份!我觉得这很可能是对前几个版本序列号的

    兼容,或者说着几个年份对Gilles Vollant公司有什么特别的意义,呵呵。

    下面是我根据以上算法写的keygen,算出来的序列号是第一次比较就能通过的。

    http://xs.blogchina.com/upload/2005...41006881133.zip