首页
社区
课程
招聘
[原创][表格算法]压缩工具 WinIMP v1.11 注册算法分析 + delphi(kol/mck)完整注册机源代码(七年后续写)
发表于: 2007-5-22 15:11 12885

[原创][表格算法]压缩工具 WinIMP v1.11 注册算法分析 + delphi(kol/mck)完整注册机源代码(七年后续写)

2007-5-22 15:11
12885

WinIMP软件是和WinRAR、WinZIP等类似的一款压缩打包软件,而其独有的.imp格式的压缩率远高于ZIP格式,和RAR也是各有千秋,而它的自解压格式更是我的至爱,时至今日仍然不比其它同类软件逊色。

七年前,小楼大侠曾经写过一篇与它相关的算法文章,可能是受当时的工具所限,却不理想。而dr0大侠倒是丢了个注册机外(感谢你的注册机),从此再无与 WinIMP 注册算法相关的信息了。

这两天无聊,再次把这个软件拖入了OD中,呵呵,机缘巧合,居然给看懂了(也许是受到刚分析ReadBook1.51plus的影响,呵呵),写此文章,留作纪念!也纪念这个优秀的、却被人淡忘的、不再继续开发的软件!

好,我们开始分析,通过错误提示信息“the keys do not match the names...”,由字符串参考方式,我们轻松的来到了这里:
004260DA  |.  68 28CC4400   push    winimp32.0044CC28

顺着它,往上查找,来到了这个call的开始处,F2键下断后,F9键运行软件,然后打开注册窗口,输入一组实验码:

Name: aCaFeeL
Key1: 1234567
Key2: 7654321

然后点击‘OK’按钮,便在OD中断了下来,来到如下位置:

》》》》》》》》
00426013  /$  53            push    ebx                              ; 被断在了这里
00426014  |.  51            push    ecx
00426015  |.  52            push    edx
00426016  |.  56            push    esi
00426017  |.  57            push    edi
00426018  |.  C8 240000     enter   24, 0
0042601C  |.  89C6          mov     esi, eax
0042601E  |.  68 00010000   push    100                              ; /Count = 100 (256.)
00426023  |.  68 603C4500   push    winimp32.00453C60                ; |Buffer = winimp32.00453C60
00426028  |.  6A 65         push    65                               ; |ControlID = 65 (101.)
0042602A  |.  50            push    eax                              ; |hWnd
0042602B  |.  31DB          xor     ebx, ebx                         ; |
0042602D  |.  2E:FF15 A0D74>call    dword ptr cs:[<&USER32.GetDlgIte>; \得到注册名
00426034  |.  C745 FC 00000>mov     dword ptr [ebp-4], 0
0042603B  |.  B8 603C4500   mov     eax, winimp32.00453C60           ;  注册名 -> eax
00426040  |.  EB 04         jmp     short winimp32.00426046
00426042  |>  83E3 03       /and     ebx, 3                          ;  ebx = ebx and $3
00426045  |.  40            |inc     eax                             ;  取注册名的下一个字符
00426046  |>  8038 00        cmp     byte ptr [eax], 0               ;  结果是否为空?
00426049  |.  74 1C         |je      short winimp32.00426067         ;  结束检查才跳
0042604B  |.  8038 20       |cmp     byte ptr [eax], 20              ;  是否为空格
0042604E  |.^ 74 F2         |je      short winimp32.00426042         ;  如若是
00426050  |.  8038 2E       |cmp     byte ptr [eax], 2E              ;  是否为符号.
00426053  |.^ 74 ED         |je      short winimp32.00426042         ;  如若是
00426055  |.  0FB638        |movzx   edi, byte ptr [eax]             ;  依次取注册名字符码 -> edi
00426058  |.  89DA          |mov     edx, ebx
0042605A      8A8F 10114500 mov     cl, byte ptr [edi+451110]        ;  cl := [edi + 451110]所指码数//从451110开始的一张表
00426060  |.  43            |inc     ebx                             ;  ebx = ebx + 1
00426061  |.  004C2A FC     |add     byte ptr [edx+ebp-4], cl        ;  tempA := tempA + cl;//edx由ebx赋值,注意and 3后的结果
00426065  |.^ EB DB         \jmp     short winimp32.00426042         ;  上面这个结果tempA将和后面的结果tempB比较,判断是否成功
00426067  |>  6A 0C         push    0C                               ; /Count = C (12.)
00426069  |.  8D45 DC       lea     eax, dword ptr [ebp-24]          ; |
0042606C  |.  50            push    eax                              ; |Buffer
0042606D  |.  6A 66         push    66                               ; |ControlID = 66 (102.)
0042606F  |.  56            push    esi                              ; |hWnd
00426070  |.  BB 10000000   mov     ebx, 10                          ; |
00426075  |.  2E:FF15 A0D74>call    dword ptr cs:[<&USER32.GetDlgIte>; \得到Key1
0042607C  |.  8D45 DC       lea     eax, dword ptr [ebp-24]          ;  Key1
0042607F  |.  31D2          xor     edx, edx
00426081  |.  E8 CE130100   call    winimp32.00437454                ;  key1 -> eax
00426086  |.  6A 0C         push    0C                               ; /Count = C (12.)
00426088  |.  8945 F4       mov     dword ptr [ebp-C], eax           ; |
0042608B  |.  8D45 DC       lea     eax, dword ptr [ebp-24]          ; |
0042608E  |.  50            push    eax                              ; |Buffer
0042608F  |.  6A 67         push    67                               ; |ControlID = 67 (103.)
00426091  |.  56            push    esi                              ; |hWnd
00426092  |.  C745 F8 00000>mov     dword ptr [ebp-8], 0             ; |
00426099  |.  BB 10000000   mov     ebx, 10                          ; |
0042609E  |.  2E:FF15 A0D74>call    dword ptr cs:[<&USER32.GetDlgIte>; \得到Key2
004260A5  |.  8D45 DC       lea     eax, dword ptr [ebp-24]
004260A8  |.  31D2          xor     edx, edx
004260AA  |.  E8 A5130100   call    winimp32.00437454                ;  key2 -> eax
004260AF  |.  8B55 F4       mov     edx, dword ptr [ebp-C]           ;  key1 -> edx
004260B2  |.  8945 F8       mov     dword ptr [ebp-8], eax
004260B5  |.  81FA 00000001 cmp     edx, 1000000                     ;  edx = key1,不能小于1000000
004260BB  |.  72 16         jb      short winimp32.004260D3
004260BD  |.  3D 00000001   cmp     eax, 1000000                     ;  eax = key2,不能小于1000000
004260C2  |.  72 0F         jb      short winimp32.004260D3
004260C4  |.  89D0          mov     eax, edx                         ;  key1 -> eax(key1/key2互换)
004260C6  |.  8B55 F8       mov     edx, dword ptr [ebp-8]           ;  key2 -> edx(key1/key2互换)
004260C9  |.  E8 D9010000   call    winimp32.004262A7                ;  ×××算法Call×××::F7进入×××
004260CE  |.  3B45 FC       cmp     eax, dword ptr [ebp-4]           ;  eax结果(tempB) = 上面的循环结果(tempA) ?
004260D1  |.  74 18         je      short winimp32.004260EB          ;  相等便成功,之后保存注册相关的信息
004260D3  |>  6A 30         push    30                               ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
004260D5  |.  68 30D24400   push    winimp32.0044D230                ; |Title = "WinImp"
004260DA  |.  68 28CC4400   push    winimp32.0044CC28                ; |Text = "The keys do not match ..."
004260DF  |.  56            push    esi                              ; |hOwner
004260E0  |.  2E:FF15 0CD84>call    dword ptr cs:[<&USER32.MessageBo>; \注册错误对话框
004260E7  |.  31C0          xor     eax, eax
004260E9  |.  EB 68         jmp     short winimp32.00426153
004260EB  |>  BB 603C4500   mov     ebx, winimp32.00453C60           ;  ASCII "aCaFeeL"
004260F0  |.  BA 98DA4400   mov     edx, winimp32.0044DA98           ;  ASCII "Register"
004260F5  |.  B8 D8DA4400   mov     eax, winimp32.0044DAD8           ;  ASCII "Options"
004260FA  |.  E8 D868FFFF   call    winimp32.0041C9D7
004260FF  |.  31F6          xor     esi, esi
00426101  |.  31C0          xor     eax, eax
00426103  |>  8D78 01       /lea     edi, dword ptr [eax+1]
00426106  |.  57            |push    edi
00426107  |.  68 A8DA4400   |push    winimp32.0044DAA8               ;  ASCII "Key%d"
0042610C  |.  8D45 E8       |lea     eax, dword ptr [ebp-18]
0042610F  |.  50            |push    eax
00426110  |.  E8 1B090100   |call    winimp32.00436A30
00426115  |.  83C4 0C       |add     esp, 0C
00426118  |.  FF742E F4     |push    dword ptr [esi+ebp-C]
0042611C  |.  68 A8E64400   |push    winimp32.0044E6A8               ;  ASCII "%X"
00426121  |.  8D45 DC       |lea     eax, dword ptr [ebp-24]
00426124  |.  50            |push    eax
00426125  |.  8D5D DC       |lea     ebx, dword ptr [ebp-24]
00426128  |.  8D55 E8       |lea     edx, dword ptr [ebp-18]
0042612B  |.  E8 00090100   |call    winimp32.00436A30
00426130  |.  83C4 0C       |add     esp, 0C
00426133  |.  B8 D8DA4400   |mov     eax, winimp32.0044DAD8          ;  ASCII "Options"
00426138  |.  83C6 04       |add     esi, 4
0042613B  |.  E8 9768FFFF   |call    winimp32.0041C9D7
00426140  |.  89F8          |mov     eax, edi
00426142  |.  83FF 02       |cmp     edi, 2
00426145  |.^ 7C BC         \jl      short winimp32.00426103
00426147  |.  C605 52134500>mov     byte ptr [451352], 1
0042614E  |.  B8 01000000   mov     eax, 1
00426153  |>  C9            leave
00426154  |.  5F            pop     edi
00426155  |.  5E            pop     esi
00426156  |.  5A            pop     edx
00426157  |.  59            pop     ecx
00426158  |.  5B            pop     ebx
00426159  \.  C3            retn
》》》》》》》》

可能大家也都注意到了:

0042605A      8A8F 10114500 mov     cl, byte ptr [edi+451110]

这里的byte ptr [edi+451110],我们顺着来到 00451110 后,会发现这是一张字符码对应表格,长度为:(4x4)x16 = 256,格式如下:

00451110   00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  ...
..
00451120   10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F  
00451130   20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F   !"#$%&'()*+,-./
00451140   30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F  0123456789:;<=>?
00451150   40 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F  @abcdefghijklmno
00451160   70 71 72 73 74 75 76 77 78 79 7A 5B 5C 5D 5E 5F  pqrstuvwxyz[\]^_
00451170   60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F  `abcdefghijklmno
00451180   70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F  pqrstuvwxyz{|}~
00451190   80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F  €亗儎厗噲墛媽崕
004511A0   90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F  悜挀敃枟槞殯湞灍
004511B0   A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF  牎ⅲぅΗī
004511C0   B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF  氨渤吹斗腹夯冀究
004511D0   C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF  懒旅呐魄壬仕掏蜗
004511E0   D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF  醒矣哉肿刭谯茌捱
004511F0   E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF  噌忏溴骁栝觌祉铒
00451200   F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF  瘃蝮趱鲼?

通过分析上面的这张表格,我们会发现,这张表格的主要作用便是:不管你输入的注册名字符是否为大写字母,他都通过这张表格将注册名全部转换为小写字母。

而 00426042~00426065 处的循环算法我用 delphi+kol/mck 源码表示,则为如下形式:

》》》》》》》》
  for i:=0 to 3 do sum[i] := $00; //初始化变量sum
  Tebx := 0;
  for i:=1 to length(RegName) do
    begin
      if (ord(RegName[i])=$20) or (ord(RegName[i])=$2E)
      then Tebx := (Tebx and $3)
      else begin
             sum[Tebx] := sum[Tebx]  + key[ord(RegName[i]) and $FF];
             Tebx := Tebx + 1;
             Tebx := (Tebx and $3);
           end;
    end;
  sumAll := int2hex(sum[3],2)+int2hex(sum[2],2)+int2hex(sum[1],2)+int2hex(sum[0],2);
  tempA  := Hex2Int('$' + sumAll);        //得到的前部分的结果(RegName -> TempA)
》》》》》》》》

上面的算法举列来说就是:

比如我输入的注册名为:aCaFeeL,则查找到上面我给出来的‘字符码对应表格’中相应的ASCII码就是:61 63 61 66 65 65 6C;sum[0]=61,sum[1]=63,sum[2]=61,sum[3]=66;然后又开始从sum[0]开始累加,即:sum[0]=61+65=C6,sum[1]=63+65=C8,sum[2]=61+6C=CD,sum[3]=66;则结果在内存窗口中为:sum[0]=C6 sum[1]=C8 sum[2]=CD sum[3]=66,故实际为十六进制的:$66CDC8C6 数字,暂且命名为tempA吧!

走过上面的循环运算后,我们继续F8键向下分析,来到这里后:

》》》》》》》》
004260AA  |.  E8 A5130100   call    winimp32.00437454                ;  key2 -> eax
004260AF  |.  8B55 F4       mov     edx, dword ptr [ebp-C]           ;  key1 -> edx
004260B2  |.  8945 F8       mov     dword ptr [ebp-8], eax
004260B5  |.  81FA 00000001 cmp     edx, 1000000                     ;  edx = hex(key1),不能小于1000000
004260BB  |.  72 16         jb      short winimp32.004260D3
004260BD  |.  3D 00000001   cmp     eax, 1000000                     ;  eax = hex(key2),不能小于1000000
004260C2  |.  72 0F         jb      short winimp32.004260D3
004260C4  |.  89D0          mov     eax, edx                         ;  key1 -> eax(key1/key2互换)
004260C6  |.  8B55 F8       mov     edx, dword ptr [ebp-8]           ;  key2 -> edx(key1/key2互换)
004260C9  |.  E8 D9010000   call    winimp32.004262A7                ;  ×××算法Call×××::F7进入×××
004260CE  |.  3B45 FC       cmp     eax, dword ptr [ebp-4]           ;  eax结果(tempB) = 上面的循环结果(tempA) ?
004260D1  |.  74 18         je      short winimp32.004260EB          ;  成功后保存注册相关的信息
004260D3  |>  6A 30         push    30                               ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
》》》》》》》》

我们知道了,Key1、Key2的数值都必须大于$1000000才行,而满足上述条件后,我们便来到了后面部分的算法相关的call子程序了,这便是:

004260C9  |.  E8 D9010000   call    winimp32.004262A7

我们需要进入到这个子程序中一探究竟,按F7键进入后,来到了这里:

》》》》》》》》
004262A7  /$  53            push    ebx
004262A8  |.  51            push    ecx
004262A9  |.  56            push    esi
004262AA  |.  89C1          mov     ecx, eax                         ;  key1 -> ecx
004262AC  |.  89D3          mov     ebx, edx                         ;  key2 -> ebx
004262AE  |.  8B15 64A74400 mov     edx, dword ptr [44A764]          ;  $E8B8D413 -> edx
004262B4  |.  E8 74FFFFFF   call    winimp32.0042622D                ;  ::F7进入::(注意:只要eax的结果)
004262B9  |.  89C6          mov     esi, eax                         ;  (运算结果eax)TempB -> (esi下面要用)
004262BB  |.  89DA          mov     edx, ebx
004262BD  |.  BB 20000000   mov     ebx, 20
004262C2  |.  89C8          mov     eax, ecx                         ;  key1 -> eax
004262C4  |.  31C9          xor     ecx, ecx
004262C6  |.  E8 B3080100   call    winimp32.00436B7E                ;  key2 -> eax
004262CB  |.  31F0          xor     eax, esi                         ;  tempB = hex(key2) xor TempB(esi上面算法中得到的值)
004262CD  |.  5E            pop     esi                              ;  如要注册成功,则必须: TempA = TempB
004262CE  |.  59            pop     ecx                              ;  即推出:Key2 = TempA xor TempB;
004262CF  |.  5B            pop     ebx
004262D0  \.  C3            retn
》》》》》》》》

通过上面的代码,我们看到后半部分的关键算法便在:

004262B4  |.  E8 74FFFFFF   call    winimp32.0042622D

的这个子call中,所以走到这里后,F7键进入,来到了如下的地方:

》》》》》》》》
0042622D  /$  53            push    ebx
0042622E  |.  51            push    ecx
0042622F  |.  56            push    esi
00426230  |.  57            push    edi
00426231  |.  C8 040000     enter   4, 0
00426235  |.  52            push    edx
00426236  |.  F645 F8 01    test    byte ptr [ebp-8], 1
0042623A  |.  75 07         jnz     short winimp32.00426243
0042623C  |.  B9 01000000   mov     ecx, 1
00426241  |.  EB 02         jmp     short winimp32.00426245
00426243  |>  89C1          mov     ecx, eax                         ;  ecx = eax = key1
00426245  |>  C745 FC 02000>mov     dword ptr [ebp-4], 2             ;  $2 -> [ebp-4]
0042624C  |.  89C7          mov     edi, eax                         ;  edi = eax = key1
0042624E  |.  EB 09         jmp     short winimp32.00426259
00426250  |>  D165 FC       /shl     dword ptr [ebp-4], 1            ;  [ebp-4] = [ebp-4] shl 1
00426253  |.  837D FC 00    |cmp     dword ptr [ebp-4], 0            ;  ? = 0
00426257  |.  74 46         |je      short winimp32.0042629F
00426259  |>  8B35 60A74400  mov     esi, dword ptr [44A760]         ;  $F527789F -> esi
0042625F  |.  89F8          |mov     eax, edi
00426261  |.  89FA          |mov     edx, edi                        ;  下面是大数运算
00426263  |.  F7E2          |mul     edx                             ;  edx <- (edi*edi) 无符号乘法,结果送eax/edx
00426265  |.  39D6          |cmp     esi, edx                        ;  $F527789F 与 edx 结果比较
00426267  |.  77 0A         |ja      short winimp32.00426273         ;  $F527789F > edx 结果,便跳转
00426269  |.  89C3          |mov     ebx, eax
0042626B  |.  89D0          |mov     eax, edx
0042626D  |.  31D2          |xor     edx, edx
0042626F  |.  F7F6          |div     esi
00426271  |.  89D8          |mov     eax, ebx
00426273  |>  F7F6          |div     esi                             ;  上面的乘积 div $F527789F 无符号除法
00426275  |.  8B75 F8       |mov     esi, dword ptr [ebp-8]          ;  $E8B8D413 -> esi
00426278  |.  89D0          |mov     eax, edx                        ;  除法余数 -> eax
0042627A  |.  89D7          |mov     edi, edx                        ;  -> edi
0042627C  |.  8575 FC       |test    dword ptr [ebp-4], esi          ;  [ebp-4] and $E8B8D413 = 0 ??
0042627F  |.^ 74 CF         |je      short winimp32.00426250         ;  =0,跳
00426281  |.  8B35 60A74400 |mov     esi, dword ptr [44A760]         ;  $F527789F -> esi
00426287  |.  89CA          |mov     edx, ecx                        ;  key1 -> edx
00426289  |.  F7E2          |mul     edx                             ;  eax * edx
0042628B  |.  39D6          |cmp     esi, edx                        ;  $F527789F 与 edx 结果比较
0042628D  |.  77 0A         |ja      short winimp32.00426299         ;  $F527789F > edx 结果,便跳转
0042628F  |.  89C3          |mov     ebx, eax
00426291  |.  89D0          |mov     eax, edx
00426293  |.  31D2          |xor     edx, edx
00426295  |.  F7F6          |div     esi
00426297  |.  89D8          |mov     eax, ebx
00426299  |>  F7F6          |div     esi                             ;  无符号 eax div $F527789F
0042629B  |.  89D1          |mov     ecx, edx                        ;  edx -> ecx 最终结果
0042629D  |.^ EB B1         \jmp     short winimp32.00426250
0042629F  |>  89C8          mov     eax, ecx                         ;  最终结果ecx -> eax
004262A1  |.  C9            leave
004262A2  |.  5F            pop     edi
004262A3  |.  5E            pop     esi
004262A4  |.  59            pop     ecx
004262A5  |.  5B            pop     ebx
004262A6  \.  C3            retn
004262A7  /$  53            push    ebx
004262A8  |.  51            push    ecx
004262A9  |.  56            push    esi
004262AA  |.  89C1          mov     ecx, eax                         ;  key1 -> ecx
004262AC  |.  89D3          mov     ebx, edx                         ;  key2 -> ebx
004262AE  |.  8B15 64A74400 mov     edx, dword ptr [44A764]          ;  $E8B8D413 -> edx
004262B4  |.  E8 74FFFFFF   call    winimp32.0042622D                ;  ::F7进入::(注意:只要eax的结果)
004262B9  |.  89C6          mov     esi, eax                         ;  (运算结果eax)TempB -> (esi下面要用)
004262BB  |.  89DA          mov     edx, ebx
004262BD  |.  BB 20000000   mov     ebx, 20
004262C2  |.  89C8          mov     eax, ecx                         ;  key1 -> eax
004262C4  |.  31C9          xor     ecx, ecx
004262C6  |.  E8 B3080100   call    winimp32.00436B7E                ;  key2 -> eax
004262CB  |.  31F0          xor     eax, esi                         ;  tempA = tempB = hex(key2) xor TempB(esi上面算法中得到的值)
004262CD  |.  5E            pop     esi                              ;  即是:Key2 = TempA xor TempB;
004262CE  |.  59            pop     ecx
004262CF  |.  5B            pop     ebx
004262D0  \.  C3            retn
》》》》》》》》

由上面的代码,我们知道了它的算法形式如下:

》》》》》》》》
  Key1 := hex2int('$' + KeyCode1);
  Tecx := Key1;
  Tebp := $2;
  Tedi := Key1;
  goto cz59;
cz50:
  Tebp := Tebp shl $1;
  if (Tebp - 0) = 0 then goto cz9F;
cz59:
  Tesi := $F527789F;
  Teax := Tedi;
  Tedx := Tedi;
  // Tedx_eax := Teax * Tedx;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    MUL  EDX
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;                                 //showmessage('cz59:  '+int2hex(Tedx,8));
  if Tesi > Tedx then goto cz73;
  Tebx := Teax;
  Teax := Tedx;
  Tedx := Tedx xor Tedx;
//Tedx := Tedx_eax mod Tesi;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    DIV  ESI
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;                                 //showmessage('cz73:  '+int2hex(Tedx,8));
  Teax := Tebx;
cz73:
//Tedx := Tedx_eax mod Tesi;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    DIV  ESI
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;                                 //showmessage('cz73:  '+int2hex(Tedx,8));
  Tesi := $E8B8D413;
  Teax := Tedx;
  Tedi := Tedx;
  if (Tebp and Tesi)=0 then goto cz50;
  Tesi := $F527789F;
  Tedx := Tecx;
//Tedx_eax := Teax * Tedx;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    MUL  EDX
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;                                 //showmessage('cz73:  '+int2hex(Tedx,8));
  if Tesi > Tedx then goto cz99;
  Tebx := Teax;
  Teax := Tedx;
  Tedx := Tedx xor Tedx;
//Tedx := Tedx_eax mod Tesi;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    DIV  ESI
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;                                 //showmessage('cz73:  '+int2hex(Tedx,8));
  Teax := Tebx;
cz99:
//Tedx := Tedx_eax mod Tesi;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    DIV  ESI
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;                                 //showmessage('cz73:  '+int2hex(Tedx,8));
  Tecx := Tedx;
  goto cz50;
cz9F:
  TempB := Tecx;                          //得到的后部分的结果(KeyCode1 ->TempB)
》》》》》》》》

在分析上面的这个算法前,我们已知道:
》》》》》》》》
004262C2  |.  89C8          mov     eax, ecx                         ;  key1 -> eax
004262C4  |.  31C9          xor     ecx, ecx
004262C6  |.  E8 B3080100   call    winimp32.00436B7E                ;  key2 -> eax
004262CB  |.  31F0          xor     eax, esi                         ;  tempB = hex(key2) xor TempB(esi上面算法中得到的值)
004262CD  |.  5E            pop     esi                              ;  如要注册成功,则必须: TempA = TempB
004262CE  |.  59            pop     ecx                              ;  即推出:Key2 = TempA xor TempB;
004262CF  |.  5B            pop     ebx
004262D0  \.  C3            retn
》》》》》》》》

也就是说:Key2的值是由上面分析并得到的tempA(由 注册名 运算后得到)和tempB(由 Key1 运算后得到)异或之后得到的,通过上面的完整分析,我们便可以写出一个完整的注册机来玩玩了,呵呵!注册机(Delphi + KOL/MCK)源代码如下:(已写成为一个string函数格式,方便你的调用和修改,嘿嘿 :)

                                                      //WinIMP v1.11注册算法
function WinIMP_sn(RegName, KeyCode1: string): string;//定义为string函数
var
  i, ii : integer;
  TempA, TempB, Key1 : longInt;
  Tesi, Tedi, Teax, Tebx, Tecx, Tedx, Tebp : cardinal;
  sumALL,strEDX, strEAX, strEDX_EAX : string;
  sum : array [0 .. 3] of byte;
label
  cz50, cz59, cz73, cz99, cz9F;
const
  key : array[0 .. 255] of byte =                     //字符表常量,不变
       ($00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F,
        $10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$1A,$1B,$1C,$1D,$1E,$1F,
        $20,$21,$22,$23,$24,$25,$26,$27,$28,$29,$2A,$2B,$2C,$2D,$2E,$2F,
        $30,$31,$32,$33,$34,$35,$36,$37,$38,$39,$3A,$3B,$3C,$3D,$3E,$3F,
        $40,$61,$62,$63,$64,$65,$66,$67,$68,$69,$6A,$6B,$6C,$6D,$6E,$6F,
        $70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$7A,$5B,$5C,$5D,$5E,$5F,
        $60,$61,$62,$63,$64,$65,$66,$67,$68,$69,$6A,$6B,$6C,$6D,$6E,$6F,
        $70,$71,$72,$73,$74,$75,$76,$77,$78,$79,$7A,$7B,$7C,$7D,$7E,$7F,
        $80,$81,$82,$83,$84,$85,$86,$87,$88,$89,$8A,$8B,$8C,$8D,$8E,$8F,
        $90,$91,$92,$93,$94,$95,$96,$97,$98,$99,$9A,$9B,$9C,$9D,$9E,$9F,
        $A0,$A1,$A2,$A3,$A4,$A5,$A6,$A7,$A8,$A9,$AA,$AB,$AC,$AD,$AE,$AF,
        $B0,$B1,$B2,$B3,$B4,$B5,$B6,$B7,$B8,$B9,$BA,$BB,$BC,$BD,$BE,$BF,
        $C0,$C1,$C2,$C3,$C4,$C5,$C6,$C7,$C8,$C9,$CA,$CB,$CC,$CD,$CE,$CF,
        $D0,$D1,$D2,$D3,$D4,$D5,$D6,$D7,$D8,$D9,$DA,$DB,$DC,$DD,$DE,$DF,
        $E0,$E1,$E2,$E3,$E4,$E5,$E6,$E7,$E8,$E9,$EA,$EB,$EC,$ED,$EE,$EF,
        $F0,$F1,$F2,$F3,$F4,$F5,$F6,$F7,$F8,$F9,$FA,$FB,$FC,$FD,$FE,$FF);
begin
  if RegName='' then
    begin
      showmessage('输入的 注册名 不能为空!');
      exit;
    end;
  for i:=0 to 3 do sum[i] := $00; //初始化变量sum
  ii := 0; //初始化变量ii
  for i:=1 to length(RegName) do  //开始循环计算:
    begin
      if (ord(RegName[i])=$20) or (ord(RegName[i])=$2E)
      then ii := (ii and $3)
      else begin
             sum[ii] := sum[ii] + key[ord(RegName[i]) and $FF];//取字符表中的相应值
             ii := ii + 1;
             ii := (ii and $3);
           end;
    end;
  sumAll := int2hex(sum[3],2)+int2hex(sum[2],2)+int2hex(sum[1],2)+int2hex(sum[0],2);
  TempA  := Hex2Int('$' + sumAll);        //得到的前部分的结果(RegName -> TempA)

  Key1 := hex2int('$' + KeyCode1);
  Tecx := Key1;
  Tebp := $2;
  Tedi := Key1;
  goto cz59;
cz50:
  Tebp := Tebp shl $1;
  if (Tebp - 0) = 0 then goto cz9F;
cz59:
  Tesi := $F527789F;
  Teax := Tedi;
  Tedx := Tedi;
  // Tedx_eax := Teax * Tedx;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    MUL  EDX
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;
  if Tesi > Tedx then goto cz73;
  Tebx := Teax;
  Teax := Tedx;
  Tedx := Tedx xor Tedx;
  //Tedx := Tedx_eax mod Tesi;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    DIV  ESI
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;
  Teax := Tebx;
cz73:
  //Tedx := Tedx_eax mod Tesi;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    DIV  ESI
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;
  Tesi := $E8B8D413;
  Teax := Tedx;
  Tedi := Tedx;
  if (Tebp and Tesi)=0 then goto cz50;
  Tesi := $F527789F;
  Tedx := Tecx;
  //Tedx_eax := Teax * Tedx;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    MUL  EDX
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;
  if Tesi > Tedx then goto cz99;
  Tebx := Teax;
  Teax := Tedx;
  Tedx := Tedx xor Tedx;
  //Tedx := Tedx_eax mod Tesi;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    DIV  ESI
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;
cz99:
  //Tedx := Tedx_eax mod Tesi;
  asm
    MOV  ESI,[Tesi]
    MOV  EAX,[Teax]
    MOV  EDX,[Tedx]
    DIV  ESI
    mov  [Teax],EAX
    mov  [Tedx],EDX
  end;
  Tecx := Tedx;
  goto cz50;
cz9F:
  TempB := Tecx;                          //得到的后部分的结果(KeyCode1 ->TempB)

  Result := int2hex((TempA xor TempB),8); //最终返回的 KeyCode2 结果是由 TempA xor TempB 后得到的
end;

好了,就到这里结束吧!分析难免有不当之处,还望大家给我指出来!

放上一组可用的Key:

name: aCaFeeL
key1: ABF8FB42
key2: 8DB47F89

注册机的算法在多台机器上使用不同注册名通过验证,但没有时间再优化它了,应该不存在bug的问题,附件中为我打包后的注册机源代码。

另:如果问我这次分析最大的收获是什么?我会说,那就是学会了如何将大数运算的高位数和低位数分配到相应的EDX和EAX中了!别笑,呵呵!

[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (13)
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
好,顶了再看
2007-5-22 15:15
0
雪    币: 250
活跃值: (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
七年后续写
2007-5-22 16:37
0
雪    币: 44229
活跃值: (19965)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
acafeel算法分析能力好强。
这位dr0大侠还经常来论坛看看的,偶尔发发帖。;)
2007-5-22 17:38
0
雪    币: 333
活跃值: (116)
能力值: ( LV9,RANK:570 )
在线值:
发帖
回帖
粉丝
5
嗯,谢谢坛主的鼓励!
想想7年前自己还是个学生,对能写出注册机的那些大侠们我是视为天人的,而现在自己也能写写简单的注册机了!
嘿嘿!菜鸟一个!
路途漫漫,还望大家多多指教呀!
2007-5-22 18:06
0
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
6
号召坛主向acafeel学习!
2007-5-22 19:28
0
雪    币: 333
活跃值: (116)
能力值: ( LV9,RANK:570 )
在线值:
发帖
回帖
粉丝
7
被楼上说得来只有一个字,汗
2007-5-22 20:17
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
8
分析能力太强了,佩服一个~~
2007-5-22 20:34
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
高手还这么谦虚,真是难得啊
2007-5-23 15:13
0
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
10
楼主说:
自解压格式更是我的至爱


我说:
把自解压结构逆源如何~~~


大家说:
期待中````
2007-5-23 15:52
0
雪    币: 442
活跃值: (287)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
skycn搜索了下,是1.21了

WinImp V1.21 汉化版  [压缩解压] 2001-03-24 261KB 8324

是一个压缩率比一般压缩软件还高出许多的压缩软件,除了解压缩自己专属的IMP格式,还支持解压缩ARJ、GZIP、RAR、TAR、ZIP、UUencoded等常见的解压缩,唯较可惜的是0.93Beta版尚未支...

授权方式:共享版 | 插件情况: 镜像:[电信 | 网通 | 铁通 | 联通]

WinImp V1.21  [压缩解压] 2001-03-17 265KB 4069

是一个压缩率比一般压缩软件还高出许多的压缩软件,除了解压缩自己专属的IMP格式,还支持解压缩ARJ、GZIP、RAR、TAR、ZIP、UUencoded等常见的解压缩,唯较可惜的是0.93Beta版尚未支...

授权方式:共享版 | 插件情况:
2007-5-24 20:57
0
雪    币: 188
活跃值: (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
看了winImp,感觉很亲切,当年初学电脑,这款软件被评价很高,超过Winrar,不过如今这两款软件的境遇已是两重天了。

也来发一个7年前没做完的任务。

软件名称:ReadBook 1.21 (版本有点老了,现在都1.51了)

不想帖汇编代码了,毕竟这款软件现在down都不好down了,以前用的是softice,crack不掉,现在用了OD,马马虎虎的写了个注册机,都不知道是不是完全准确。贴出来只是好玩,如果有不正确的地方,希望大侠们多多指正。

#include <stdio.h>

int main( int argc, char *argv[] )
{
        long regcode[4];
        long length;
        unsigned char name[200];
        unsigned char i;
       
        memset(name, 0x20, 200);
       
        printf("%s", "Name:");
        scanf("%s", name);
       
        length = strlen( (char*) name );
       
        for ( i = 0; i < length; ++i )
                name[i] = tolower(name[i]);
       
        memcpy(regcode, name, 16);

        regcode[1] += (regcode[2] + regcode[3]);
       
        regcode[1] = regcode[1] * 0x7531;
        regcode[0] = regcode[0] * 0x7531;
       
        regcode[0] -= regcode[1];

        printf("%ld", regcode[0]);
       
        return 0;
}
2007-5-24 21:03
0
雪    币: 101
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
先顶在说了~~~
2007-5-26 13:57
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
acafeel算法分析能力好强。
这位dr0大侠还经常来论坛看看的,偶尔发发帖
2007-6-3 15:47
0
游客
登录 | 注册 方可回帖
返回
//