吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9076|回复: 11
收起左侧

[原创] 160 个 CrackMe 之 159 - Torn@do.2 脱壳修复、注册分析及注册机

[复制链接]
solly 发表于 2019-7-15 02:25
本帖最后由 solly 于 2019-7-15 23:58 编辑

160 个 CrackMe 之 159 - Torn@do.2 是一个加了壳的 CrackMe ,文件信息如下:
01.png
显示未知的壳,用 "scan /t" 重新扫描一下:
02.png
这次显示为 "EncryptPE" 了。而且其文件末尾为字符串“eEnCrypter! :) 2nd&mi”,没见过,只有手动脱壳了。
节信息如下:
03.png
看起来与我原来脱过的 043 Ding Boy 的壳很象,也是很多节,并依次对下一节解码,也就是节名为 ".Stone" 的节,都是解码用的。
在 Windows 10 下OD载入 CrackMe,如下图所示:
04.png
往下拖可以看到 0x0041F096 有一个 jmp eax,我们直接选择在这一条指令上按 F4 , 然后再 F8 就会跳转到下一节的解码代码,与这一节基本一样,也是到 jmp eax 处 F4, 再F8跳转到下一节的解码代码,这个操作有多次,一直来到下面代码处,如下图,才来到 OEP:
05.png
上图的 0x00403560 才是 OEP,到这里我们就可以脱壳了。
再往下拖一下,可以找到 WinMain() 函数的调用,如下图:
06.png
如上图,call 00401DE0 就是调用 WinMain() 函数。
我们先脱壳,脱壳后,我们运行一下,报一个错误,运行不了,错误提示如下所示:
08_win10.png
是一个 API 函数的问题,这个 API 函数是 DefWindowProcA(),我们需要手动修复这个问题,我们重新来到 OEP。用“管理员身份运行” ImportREC,如下图所示:
10_0.png
可以看到,最后一行的 Thunk 的 Valid 为 NO,点击旁边的 ”Show Invalid" 按钮,如下图显示:
10_1.png
其中那条 NtdllDefWindowProc_A 就是要手动修复的,鼠标左键双击这一行,弹出手动导入表编辑对话框,如下图所示:
10_2.png
我们先在 "Module" 下拉列表中,将  “ntdll.dll” 改成 "User32.dll",如下图所示:
10_3.png
然后在 Function 列表中找到“DefWindowProcA”这一行并选择,如上图所示,选好后按 “OK” 即可,这时显示如下图:
10_4.png
所有的函数都有效了,这时就是可以 "Fix Dump" 了,如下图所示,选择要修复的 Dump 文件即可。
10_5.png
这样操作后,就可以正常在 Windows 10 运行了,如果还不行,还可以用 LordPE 来 dump,不用 OD 的 dump 功能,如下图所示:
09.png
再按前面的方法修复,就应该可以在 Windows 10 下运行了。


脱壳后,OD 重新载入 F9 直接运行,来到其界面:
11.png
随便输入几个信息,点“ValIDAte”,没有动静,按3次后,“Validate” 按钮不可用了,提示变成了:"TRY AGAIN!",如下图所示:
23.png
通过前面所述,我们知道  WinMain() 函数入口在 0x00401DE0,我们浏览一下这个 WinMain()函数,可以看到这是一个标准的 Windows 窗口API应用的代码,最后面是消息循环处理。
从最前的4行代码,我们找到了 WndProc 的入口为 0x00401FD0,如下所示:
[Asm] 纯文本查看 复制代码
00401DE0    83EC 4C                sub     esp, 4C
00401DE3    C74424 00 30000000     mov     dword ptr [esp], 30
00401DEB    C74424 04 03000000     mov     dword ptr [esp+4], 3
00401DF3    C74424 08 D01F4000     mov     dword ptr [esp+8], 00401FD0

我们跟随立即数,来到 0x00401FD0,如下所示,是 WndProc() 的主处理代码:
[Asm] 纯文本查看 复制代码
00401FD0    8B4C24 08              mov     ecx, dword ptr [esp+8]                         ; nMessage
00401FD4    56                     push    esi
00401FD5    83F9 01                cmp     ecx, 1                                         ; WM_CREATE
00401FD8    74 2F                  je      short 00402009
00401FDA    83F9 02                cmp     ecx, 2                                         ; WM_DESTROY
00401FDD    0F84 84000000          je      00402067
00401FE3    81F9 11010000          cmp     ecx, 111                                       ; WM_COMMAND
00401FE9    0F84 86000000          je      00402075
00401FEF    8B4424 14              mov     eax, dword ptr [esp+14]                        ; lParam
00401FF3    8B5424 10              mov     edx, dword ptr [esp+10]                        ; wParam
00401FF7    8B7424 08              mov     esi, dword ptr [esp+8]                         ; hWnd
00401FFB    50                     push    eax                                            ; 默认消息处理
00401FFC    52                     push    edx
00401FFD    51                     push    ecx
00401FFE    56                     push    esi
00401FFF    FF15 D4E24000          call    dword ptr [<&USER32.DefWindowProcA>]           ; ntdll.NtdllDefWindowProc_A
00402005    5E                     pop     esi
00402006    C2 1000                retn    10

最后那个 call User32.DefWindowProcA 就是我们前面修复的那个 API 调用。
我们再次跟随 WM_CREATE 消息处理的“je 00402009”,来到 0x00402009,如下所示:
[Asm] 纯文本查看 复制代码
00402009    8B4424 14              mov     eax, dword ptr [esp+14]
0040200D    68 F4010000            push    1F4
00402012    68 88C14000            push    0040C188                                       ; ASCII "F:\Downloads\crack\[url=mailto:159_Torn@do.2]159_Torn@do.2[/url]"
00402017    6A 00                  push    0
00402019    8B48 04                mov     ecx, dword ptr [eax+4]
0040201C    890D F8BE4000          mov     dword ptr [40BEF8], ecx
00402022    FF15 64E24000          call    dword ptr [<&KERNEL32.GetModuleHandleA>]       ; KERNEL32.GetModuleHandleA
00402028    50                     push    eax
00402029    FF15 68E24000          call    dword ptr [<&KERNEL32.GetModuleFileNameA>]     ; KERNEL32.GetModuleFileNameA
0040202F    85C0                   test    eax, eax
00402031    74 10                  je      short 00402043
00402033    B9 5C000000            mov     ecx, 5C
00402038    3888 88C14000          cmp     byte ptr [eax+40C188], cl
0040203E    74 03                  je      short 00402043
00402040    48                     dec     eax
00402041  ^ 75 F5                  jnz     short 00402038
00402043    8B7424 08              mov     esi, dword ptr [esp+8]
00402047    6A 00                  push    0                                              ; lParam == 0x00000000
00402049    C680 88C14000 00       mov     byte ptr [eax+40C188], 0
00402050    68 77777777            push    77777777                                       ;  wParam == 0x77777777
00402055    68 11010000            push    111                                            ;  nMessage == WM_COMMAND
0040205A    56                     push    esi
0040205B    FF15 E4E24000          call    dword ptr [<&USER32.PostMessageA>]             ; USER32.PostMessageA
00402061    33C0                   xor     eax, eax
00402063    5E                     pop     esi
00402064    C2 1000                retn    10

可以看到,在处理 WM_CREATE 消息时,在最后,给窗口 Post 了一条自定义的 WM_COMMAND 消息。我们再次回到前面的 WndProc()框架函数,来到 WM_COMMAND 消息处理跳转 "je 00402075",跟随这个跳转,来到 WM_COMMAND 消息处理代码处:
[Asm] 纯文本查看 复制代码
00402075    817C24 10 77777777     cmp     dword ptr [esp+10], 77777777
0040207D    75 21                  jnz     short 004020A0
0040207F    8B7424 08              mov     esi, dword ptr [esp+8]
00402083    6A 00                  push    0
00402085    68 B0204000            push    004020B0
0040208A    A1 F8BE4000            mov     eax, dword ptr [40BEF8]
0040208F    56                     push    esi
00402090    6A 65                  push    65
00402092    50                     push    eax
00402093    FF15 E0E24000          call    dword ptr [<&USER32.DialogBoxParamA>]          ; USER32.DialogBoxParamA
00402099    56                     push    esi
0040209A    FF15 F0E24000          call    dword ptr [<&USER32.DestroyWindow>]            ; USER32.DestroyWindow
004020A0    33C0                   xor     eax, eax
004020A2    5E                     pop     esi
004020A3    C2 1000                retn    10

这个消息处理非常简单,就是只要wParam为自定义的 0x77777777 就显示 CrackMe 的主对话框,因此这里就是显示主界面的地方,我们也找到了 DlgProc() 的入口为 0x004020B0。
再次“跟随立即数”,来到 0x004020B0,对话框消息处理框架代码如下:
[Asm] 纯文本查看 复制代码
004020B0    8B4424 08              mov     eax, dword ptr [esp+8]
004020B4    53                     push    ebx
004020B5    56                     push    esi
004020B6    83F8 02                cmp     eax, 2                                         ; WM_DESTROY
004020B9    57                     push    edi
004020BA    0F84 C6000000          je      00402186
004020C0    3D 10010000            cmp     eax, 110                                       ; WM_INITDIALOG
004020C5    74 13                  je      short 004020DA
004020C7    3D 11010000            cmp     eax, 111                                       ; WM_COMMAND
004020CC    0F84 9D000000          je      0040216F
004020D2    33C0                   xor     eax, eax
004020D4    5F                     pop     edi
004020D5    5E                     pop     esi
004020D6    5B                     pop     ebx
004020D7    C2 1000                retn    10


我们跟随 WM_INITDIALOG 消息处理跳转 "je 004020DA" 后,可以看到这样一段代码:
[Asm] 纯文本查看 复制代码
004020F6    6A 00                  push    0                                              ; 0 - Disabled, 1 - Enabled
004020F8    8B35 A0E24000          mov     esi, dword ptr [<&USER32.GetDlgItem>]          ; USER32.GetDlgItem
004020FE    68 EC030000            push    3EC                                            ; "Request" ID
00402103    53                     push    ebx                                            ; hDlg
00402104    FFD6                   call    esi                                            ; call GetDlgItem()
00402106    50                     push    eax                                            ; Control hwnd
00402107    FF15 98E24000          call    dword ptr [<&USER32.EnableWindow>]             ; USER32.EnableWindow


这段代码就是在 CrackMe 启动时将 "Request" 按钮的状态改为 "Disabled" 状态的。

我们再回到 DlgProc(),跟随处理 WM_COMMAND 跳转 "je 0040216F",来到其处理框架代码:
[Asm] 纯文本查看 复制代码
0040216F    8B4424 18              mov     eax, dword ptr [esp+18]
00402173    25 FFFF0000            and     eax, 0FFFF
00402178    3D EB030000            cmp     eax, 3EB                                       ; Validate 按钮
0040217D    7F 1B                  jg      short 0040219A
0040217F    74 54                  je      short 004021D5                                 ; 跳转去进行注册验证
00402181    83F8 02                cmp     eax, 2                                         ; WM_CLOSE
00402184    74 37                  je      short 004021BD
00402186    A1 08BE4000            mov     eax, dword ptr [40BE08]
0040218B    50                     push    eax
0040218C    FF15 F4E14000          call    dword ptr [<&GDI32.DeleteObject>]              ; GDI32.DeleteObject
00402192    33C0                   xor     eax, eax
00402194    5F                     pop     edi
00402195    5E                     pop     esi
00402196    5B                     pop     ebx
00402197    C2 1000                retn    10


可以看到,跟随 “ je 004021D5” 后就可以到达注册验证的代码了:
[Asm] 纯文本查看 复制代码
004021D5   > \8B5C24 10                mov     ebx, dword ptr [esp+10]                       ;  Case 3EB of switch 00402178
004021D9   .  53                       push    ebx
004021DA   .  E8 31F1FFFF              call    00401310                                      ;  假的序列号验证,实际取用户名
004021DF   .  83C4 04                  add     esp, 4
004021E2   .  8BF8                     mov     edi, eax                                      ;  eax ===> "solly"
004021E4   .  B9 FFFFFFFF              mov     ecx, -1
004021E9   .  2BC0                     sub     eax, eax
004021EB   .  F2:AE                    repne   scas byte ptr es:[edi]
004021ED   .  F7D1                     not     ecx
004021EF   .  2BF9                     sub     edi, ecx
004021F1   .  8BC1                     mov     eax, ecx
004021F3   .  C1E9 02                  shr     ecx, 2
004021F6   .  8BF7                     mov     esi, edi
004021F8   .  BF 30BF4000              mov     edi, 0040BF30                                 ;  ASCII "solly"
004021FD   .  F3:A5                    rep     movs dword ptr es:[edi], dword ptr [esi]
004021FF   .  8BC8                     mov     ecx, eax
00402201   .  53                       push    ebx
00402202   .  83E1 03                  and     ecx, 3
00402205   .  F3:A4                    rep     movs byte ptr es:[edi], byte ptr [esi]
00402207   .  E8 74F1FFFF              call    00401380                                      ;  假的序列号验证,实际取公司名
0040220C   .  83C4 04                  add     esp, 4
0040220F   .  8BF8                     mov     edi, eax                                      ;  eax ===> "company"
00402211   .  B9 FFFFFFFF              mov     ecx, -1
00402216   .  2BC0                     sub     eax, eax
00402218   .  F2:AE                    repne   scas byte ptr es:[edi]
0040221A   .  F7D1                     not     ecx
0040221C   .  2BF9                     sub     edi, ecx
0040221E   .  8BD1                     mov     edx, ecx
00402220   .  C1E9 02                  shr     ecx, 2
00402223   .  8BF7                     mov     esi, edi
00402225   .  BF E0BD4000              mov     edi, 0040BDE0                                 ;  ASCII "company"
0040222A   .  F3:A5                    rep     movs dword ptr es:[edi], dword ptr [esi]
0040222C   .  8BCA                     mov     ecx, edx
0040222E   .  53                       push    ebx
0040222F   .  83E1 03                  and     ecx, 3
00402232   .  F3:A4                    rep     movs byte ptr es:[edi], byte ptr [esi]
00402234   .  E8 B7F1FFFF              call    004013F0                                      ;  假的序列号验证,实际取序列名
00402239   .  83C4 04                  add     esp, 4
0040223C   .  8BF8                     mov     edi, eax                                      ;  eax ===> "78787878"
0040223E   .  B9 FFFFFFFF              mov     ecx, -1
00402243   .  2BC0                     sub     eax, eax
00402245   .  F2:AE                    repne   scas byte ptr es:[edi]
00402247   .  F7D1                     not     ecx
00402249   .  2BF9                     sub     edi, ecx
0040224B   .  8BD1                     mov     edx, ecx
0040224D   .  C1E9 02                  shr     ecx, 2
00402250   .  8BF7                     mov     esi, edi
00402252   .  BF 28BE4000              mov     edi, 0040BE28                                 ;  ASCII "78787878"
00402257   .  F3:A5                    rep     movs dword ptr es:[edi], dword ptr [esi]
00402259   .  8BCA                     mov     ecx, edx
0040225B   .  83E1 03                  and     ecx, 3
0040225E   .  F3:A4                    rep     movs byte ptr es:[edi], byte ptr [esi]
00402260   .  53                       push    ebx                                           ;  EBX == 0x00B50DE8
00402261   .  68 28BE4000              push    0040BE28                                      ;  ASCII "78787878"
00402266   .  68 E0BD4000              push    0040BDE0                                      ;  ASCII "company"
0040226B   .  68 30BF4000              push    0040BF30                                      ;  ASCII "solly"
00402270   .  E8 7BFAFFFF              call    00401CF0                                      ;  真正的注册码验证位置
00402275   .  83C4 10                  add     esp, 10
00402278   .  66:833D 20BE4000 28      cmp     word ptr [40BE20], 28                         ; 是否成功!
00402280   .  75 1E                    jnz     short 004022A0                                ; [40BE20] == 0x28 表示成功!
00402282   .  6A 00                    push    0                                             ; /lParam = NULL
00402284   .  A1 F8BE4000              mov     eax, dword ptr [40BEF8]                       ; |
00402289   .  68 A0254000              push    004025A0                                      ; |DlgProc = [url=mailto:Torn@do_.004025A0]Torn@do_.004025A0[/url]
0040228E   .  53                       push    ebx                                           ; |hOwner
0040228F   .  6A 68                    push    68                                            ; |pTemplate = 68
00402291   .  50                       push    eax                                           ; |hInst => NULL
00402292   .  FF15 E0E24000            call    dword ptr [<&user32.DialogBoxParamA>          ; \DialogBoxParamA
00402298   .  33C0                     xor     eax, eax
0040229A   .  5F                       pop     edi
0040229B   .  5E                       pop     esi
0040229C   .  5B                       pop     ebx
0040229D   .  C2 1000                  retn    10
004022A0   >  66:A1 74A04000           mov     ax, word ptr [40A074]
004022A6   .  66:40                    inc     ax
004022A8   .  66:A3 74A04000           mov     word ptr [40A074], ax
004022AE   .  66:3D 0300               cmp     ax, 3                                         ; 尝试3次
004022B2   .  75 32                    jnz     short 004022E6
004022B4   .  6A 00                    push    0                                             ; /Enable = FALSE
004022B6   .  8B35 A0E24000            mov     esi, dword ptr [<&user32.GetDlgItem>          ; |USER32.GetDlgItem
004022BC   .  68 EB030000              push    3EB                                           ; |/ControlID = 3EB (1003.)
004022C1   .  53                       push    ebx                                           ; ||hWnd
004022C2   .  FFD6                     call    esi                                           ; |\GetDlgItem
004022C4   .  50                       push    eax                                           ; |hWnd
004022C5   .  8B3D 98E24000            mov     edi, dword ptr [<&user32.EnableWindow>        ; |USER32.EnableWindow
004022CB   .  FFD7                     call    edi                                           ; \EnableWindow
004022CD   .  68 68A04000              push    0040A068                                      ; /Text = "TRY AGAIN!"
004022D2   .  68 EE030000              push    3EE                                           ; |ControlID = 3EE (1006.)
004022D7   .  53                       push    ebx                                           ; |hWnd
004022D8   .  FF15 F8E24000            call    dword ptr [<&user32.SetDlgItemTextA>          ; \SetDlgItemTextA
004022DE   .  66:A1 74A04000           mov     ax, word ptr [40A074]
004022E4   .  EB 0C                    jmp     short 004022F2
004022E6   >  8B3D 98E24000            mov     edi, dword ptr [<&user32.EnableWindow>        ;  USER32.EnableWindow
004022EC   .  8B35 A0E24000            mov     esi, dword ptr [<&user32.GetDlgItem>          ;  USER32.GetDlgItem
004022F2   >  66:A3 74A04000           mov     word ptr [40A074], ax
004022F8   .  66:3D 0300               cmp     ax, 3                                         ; 尝试3次
004022FC   .  7E 21                    jle     short 0040231F
004022FE   .  6A 00                    push    0
00402300   .  68 EB030000              push    3EB
00402305   .  53                       push    ebx
00402306   .  FFD6                     call    esi
00402308   .  50                       push    eax
00402309   .  FFD7                     call    edi
0040230B   .  6A 40                    push    40                                            ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040230D   .  68 98A74000              push    0040A798                                      ; |Title = "Message from TORN@DO"
00402312   .  68 10A74000              push    0040A710                                      ; |Text = "You're using a window editing tool like THE CUSTOMISER!",LF,"You have had 3 chances for entering the right code!",LF,"Do you think that's fair?"
00402317   .  6A 00                    push    0                                             ; |hOwner = NULL
00402319   .  FF15 DCE24000            call    dword ptr [<&user32.MessageBoxA>]             ; \MessageBoxA
0040231F   >  33C0                     xor     eax, eax
00402321   .  5F                       pop     edi
00402322   .  5E                       pop     esi
00402323   .  5B                       pop     ebx
00402324   .  C2 1000                  retn    10

从上面的我的注释中,可以看到,前面三次都是没有用的验证,迷惑用的,实际用途只是取界面上输入的三个字符串。直正的验证是如下代码处:
[Asm] 纯文本查看 复制代码
00402260   .  53                       push    ebx                                           ;  EBX == 0x00B50DE8
00402261   .  68 28BE4000              push    0040BE28                                      ;  ASCII "78787878"
00402266   .  68 E0BD4000              push    0040BDE0                                      ;  ASCII "company"
0040226B   .  68 30BF4000              push    0040BF30                                      ;  ASCII "solly"
00402270   .  E8 7BFAFFFF              call    00401CF0                                      ;  真正的注册码验证位置
00402275   .  83C4 10                  add     esp, 10
00402278   .  66:833D 20BE4000 28      cmp     word ptr [40BE20], 28                         ; 是否成功!
00402280   .  75 1E                    jnz     short 004022A0                                ; [40BE20] == 0x28 表示成功!

上面的 call 00401CF0 才是真正的验证代码,其代码下:
[Asm] 纯文本查看 复制代码
00401CF0  /$  53                       push    ebx
00401CF1  |.  56                       push    esi
00401CF2  |.  8B5C24 14                mov     ebx, dword ptr [esp+14]                ;  序列号
00401CF6  |.  57                       push    edi
00401CF7  |.  55                       push    ebp
00401CF8  |.  53                       push    ebx
00401CF9  |.  E8 F2FCFFFF              call    004019F0                               ;  strcmp(),判断是否空串
00401CFE  |.  83C4 04                  add     esp, 4
00401D01  |.  53                       push    ebx                                    ;  ebx ===> SN
00401D02  |.  E8 19FAFFFF              call    00401720                               ;  sn[0]~sn[4],固定字符 "IDC40"
00401D07  |.  83C4 04                  add     esp, 4
00401D0A  |.  83F8 01                  cmp     eax, 1
00401D0D  |.  74 0E                    je      short 00401D1D
00401D0F  |.  66:C705 20BE4000 FFFF    mov     word ptr [40BE20], 0FFFF
00401D18  |.  5D                       pop     ebp
00401D19  |.  5F                       pop     edi
00401D1A  |.  5E                       pop     esi
00401D1B  |.  5B                       pop     ebx
00401D1C  |.  C3                       retn
00401D1D  |>  8B6C24 20                mov     ebp, dword ptr [esp+20]
00401D21  |.  8B7C24 18                mov     edi, dword ptr [esp+18]
00401D25  |.  8B7424 14                mov     esi, dword ptr [esp+14]
00401D29  |.  55                       push    ebp
00401D2A  |.  53                       push    ebx
00401D2B  |.  57                       push    edi
00401D2C  |.  56                       push    esi
00401D2D  |.  E8 EEFCFFFF              call    00401A20                               ;  无用校验
00401D32  |.  83C4 10                  add     esp, 10
00401D35  |.  53                       push    ebx
00401D36  |.  E8 55FAFFFF              call    00401790                               ;  sn[6]~sn[9],固定字符 "ETBL"
00401D3B  |.  83C4 04                  add     esp, 4
00401D3E  |.  83F8 01                  cmp     eax, 1
00401D41  |.  74 0E                    je      short 00401D51
00401D43  |.  66:C705 20BE4000 FFFF    mov     word ptr [40BE20], 0FFFF
00401D4C  |.  5D                       pop     ebp
00401D4D  |.  5F                       pop     edi
00401D4E  |.  5E                       pop     esi
00401D4F  |.  5B                       pop     ebx
00401D50  |.  C3                       retn
00401D51  |>  53                       push    ebx
00401D52  |.  E8 89FAFFFF              call    004017E0                               ;  序列号最后4字符,当前时间校验
00401D57  |.  83C4 04                  add     esp, 4
00401D5A  |.  83F8 01                  cmp     eax, 1
00401D5D  |.  74 0E                    je      short 00401D6D
00401D5F  |.  66:C705 20BE4000 FFFF    mov     word ptr [40BE20], 0FFFF
00401D68  |.  5D                       pop     ebp
00401D69  |.  5F                       pop     edi
00401D6A  |.  5E                       pop     esi
00401D6B  |.  5B                       pop     ebx
00401D6C  |.  C3                       retn
00401D6D  |>  55                       push    ebp
00401D6E  |.  53                       push    ebx
00401D6F  |.  57                       push    edi
00401D70  |.  56                       push    esi
00401D71  |.  E8 FAFDFFFF              call    00401B70                               ;  无用校验
00401D76  |.  83C4 10                  add     esp, 10
00401D79  |.  A1 80C34000              mov     eax, dword ptr [40C380]                ;  FirstInstallDateTime转换成字符串后的长度
00401D7E  |.  50                       push    eax
00401D7F  |.  53                       push    ebx
00401D80  |.  E8 EBFAFFFF              call    00401870                               ;  注册表FirstInstallDateTime验证,但由于的BUG,变成固定数字(1702505)的验证
00401D85  |.  83C4 08                  add     esp, 8
00401D88  |.  83F8 01                  cmp     eax, 1
00401D8B  |.  74 0E                    je      short 00401D9B
00401D8D  |.  66:C705 20BE4000 FFFF    mov     word ptr [40BE20], 0FFFF
00401D96  |.  5D                       pop     ebp
00401D97  |.  5F                       pop     edi
00401D98  |.  5E                       pop     esi
00401D99  |.  5B                       pop     ebx
00401D9A  |.  C3                       retn
00401D9B  |>  55                       push    ebp
00401D9C  |.  53                       push    ebx
00401D9D  |.  57                       push    edi
00401D9E  |.  56                       push    esi
00401D9F  |.  E8 8CFEFFFF              call    00401C30                               ;  无用校验
00401DA4  |.  83C4 10                  add     esp, 10
00401DA7  |.  53                       push    ebx                                    ;  ebx ===> sn
00401DA8  |.  E8 63FBFFFF              call    00401910                               ;  注册信息验证,包括注册表的 RegisteredOwner、输入的用户名和公司名验证
00401DAD  |.  83C4 04                  add     esp, 4
00401DB0  |.  83F8 01                  cmp     eax, 1
00401DB3  |.  74 0E                    je      short 00401DC3
00401DB5  |.  66:C705 20BE4000 FFFF    mov     word ptr [40BE20], 0FFFF
00401DBE  |.  5D                       pop     ebp
00401DBF  |.  5F                       pop     edi
00401DC0  |.  5E                       pop     esi
00401DC1  |.  5B                       pop     ebx
00401DC2  |.  C3                       retn
00401DC3  |>  55                       push    ebp
00401DC4  |.  E8 97F6FFFF              call    00401460                               ;  设置成功状态
00401DC9  |.  83C4 04                  add     esp, 4
00401DCC  |.  5D                       pop     ebp
00401DCD  |.  5F                       pop     edi
00401DCE  |.  5E                       pop     esi
00401DCF  |.  5B                       pop     ebx
00401DD0  \.  C3                       retn


这里説明一下,从上面代码中可以看到,有一个时间验证(call 004017E0),代码如下:
[Asm] 纯文本查看 复制代码
004017E0  /$  83EC 04                  sub     esp, 4
004017E3  |.  33C9                     xor     ecx, ecx
004017E5  |.  8D4424 01                lea     eax, dword ptr [esp+1]
004017E9  |.  56                       push    esi
004017EA  |.  8B5424 0C                mov     edx, dword ptr [esp+C]                            ;  edx ===> SN
004017EE  |.  57                       push    edi
004017EF  |.  8BFA                     mov     edi, edx                                          ;  edi ===> SN
004017F1  |.  884C24 08                mov     byte ptr [esp+8], cl
004017F5  |.  66:8908                  mov     word ptr [eax], cx
004017F8  |.  8848 02                  mov     byte ptr [eax+2], cl
004017FB  |.  B9 FFFFFFFF              mov     ecx, -1
00401800  |.  2BC0                     sub     eax, eax
00401802  |.  F2:AE                    repne   scas byte ptr es:[edi]
00401804  |.  F7D1                     not     ecx                                               ;  ecx = len(sn)+1
00401806  |.  8BFA                     mov     edi, edx
00401808  |.  2BC0                     sub     eax, eax
0040180A  |.  8A4C11 FB                mov     cl, byte ptr [ecx+edx-5]                          ;  sn[len-4]
0040180E  |.  884C24 08                mov     byte ptr [esp+8], cl
00401812  |.  B9 FFFFFFFF              mov     ecx, -1
00401817  |.  F2:AE                    repne   scas byte ptr es:[edi]
00401819  |.  F7D1                     not     ecx                                               ;  ecx = len(sn)+1
0040181B  |.  8BFA                     mov     edi, edx
0040181D  |.  8A4411 FC                mov     al, byte ptr [ecx+edx-4]                          ;  sn[len-3]
00401821  |.  B9 FFFFFFFF              mov     ecx, -1
00401826  |.  884424 09                mov     byte ptr [esp+9], al
0040182A  |.  2BC0                     sub     eax, eax
0040182C  |.  F2:AE                    repne   scas byte ptr es:[edi]
0040182E  |.  F7D1                     not     ecx                                               ;  ecx = len(sn)+1
00401830  |.  8BFA                     mov     edi, edx
00401832  |.  2BC0                     sub     eax, eax
00401834  |.  8A4C11 FD                mov     cl, byte ptr [ecx+edx-3]                          ;  sn[len-2]
00401838  |.  884C24 0A                mov     byte ptr [esp+A], cl
0040183C  |.  B9 FFFFFFFF              mov     ecx, -1
00401841  |.  F2:AE                    repne   scas byte ptr es:[edi]
00401843  |.  F7D1                     not     ecx                                               ;  ecx = len(sn)+1
00401845  |.  8D4424 08                lea     eax, dword ptr [esp+8]
00401849  |.  8A5411 FE                mov     dl, byte ptr [ecx+edx-2]                          ;  sn[len-1]
0040184D  |.  885424 0B                mov     byte ptr [esp+B], dl
00401851  |.  50                       push    eax
00401852  |.  E8 291C0000              call    00403480                                          ;  atoi(sn[len-4][len-3][len-2][len-1])
00401857  |.  83C4 04                  add     esp, 4
0040185A  |.  8BF0                     mov     esi, eax                                          ;  esi = 0
0040185C  |.  E8 3FFEFFFF              call    004016A0                                          ;  GetLocalTime
00401861  |.  2BC6                     sub     eax, esi                                          ;  eax = 0x0000081C = 2076
00401863  |.  5F                       pop     edi
00401864  |.  5E                       pop     esi
00401865  |.  83F8 01                  cmp     eax, 1
00401868  |.  1BC0                     sbb     eax, eax
0040186A  |.  83C4 04                  add     esp, 4
0040186D  |.  F7D8                     neg     eax
0040186F  \.  C3                       retn

其中又有一个调用(call 004016A0),就是根据当前时间生成一段注册验证,对注册码最后4个数字进行验证:
[Asm] 纯文本查看 复制代码
004016A0  /$  83EC 10                  sub     esp, 10
004016A3  |.  8D4424 00                lea     eax, dword ptr [esp]
004016A7  |.  56                       push    esi
004016A8  |.  50                       push    eax                                               ; /pLocaltime
004016A9  |.  FF15 6CE24000            call    dword ptr [<&kernel32.GetLocalTime>]              ; \GetLocalTime
004016AF  |.  33D2                     xor     edx, edx
004016B1  |.  33C0                     xor     eax, eax
004016B3  |.  66:8B5424 06             mov     dx, word ptr [esp+6]                              ;  月份 7
004016B8  |.  33C9                     xor     ecx, ecx
004016BA  |.  66:8B4424 0A             mov     ax, word ptr [esp+A]                              ;  日 6
004016BF  |.  0FAFD0                   imul    edx, eax                                          ;  EDX = 0x2A
004016C2  |.  66:8B4C24 0E             mov     cx, word ptr [esp+E]                              ;  分钟,cx = 0x09
004016C7  |.  8B4424 0C                mov     eax, dword ptr [esp+C]                            ;  eax = 0x00090003
004016CB  |.  25 FFFF0000              and     eax, 0FFFF                                        ;  小时 eax = 3
004016D0  |.  0FAFC1                   imul    eax, ecx                                          ;  eax == 0x1B
004016D3  |.  0FBE0D 60BF4000          movsx   ecx, byte ptr [40BF60]                            ;  RegisteredOwner[0],注册表项字符串的第1个字符的 ASCII 值。
004016DA  |.  03D0                     add     edx, eax                                          ;  edx = 0x2A + 0x1B
004016DC  |.  8B4424 04                mov     eax, dword ptr [esp+4]                            ;  ax = 2019
004016E0  |.  2BD1                     sub     edx, ecx                                          ;  ecx == RegisteredOwner[0]
004016E2  |.  25 FFFF0000              and     eax, 0FFFF
004016E7  |.  8D3402                   lea     esi, dword ptr [edx+eax]                          ;  esi = edx + eax + 0x45 + 0x7E3 = 69 + 2019 = 2088
004016EA  |.  56                       push    esi
004016EB  |.  E8 A0FBFFFF              call    00401290                                          ;  检查 SoftICE (Win9x) 调试
004016F0  |.  83C4 04                  add     esp, 4
004016F3  |.  85C0                     test    eax, eax
004016F5  |.  74 06                    je      short 004016FD
004016F7  |.  81C6 43010000            add     esi, 143
004016FD  |>  56                       push    esi
004016FE  |.  E8 CDFBFFFF              call    004012D0                                          ;  检查 SoftICE (NT) 调试
00401703  |.  83C4 04                  add     esp, 4
00401706  |.  85C0                     test    eax, eax
00401708  |.  74 06                    je      short 00401710
0040170A  |.  81C6 71020000            add     esi, 271
00401710  |>  8BC6                     mov     eax, esi
00401712  |.  5E                       pop     esi
00401713  |.  83C4 10                  add     esp, 10
00401716  \.  C3                       retn


也就是説,其验证时间精准到了分钟,生成的序列号有效时间最多60秒,如果注册机生成序列号与你输入序列号不是在同一分钟数字时(不是指1分钟内)序列号就是无效的,也就是説当输入序列号时,只要秒钟跨过了第59秒,就得重新生成序列号。
注册码前面两段是固定的,由 call 00401720 和 call 00401790 实现的,比较简单,这里不对其进行分析。
call 00401870 是对注册表中的一个值进行验证,这样,序列号与具体机器有关,不是通用的了,必须要有注册机才能搞定注册。这个调用是处理注册表中  FirstInstallDateTime 这个值的,不过这个值只有在 Windows 9x 系统下才有,Win NT 系列,如 Windows 10 下就没有这个注册表项。另外 CrackMe 还要用到一个注册表项: RegisteredOwner,这个也只有在 Windows 9x 下才有。这个调用的主要代码如下(其前面有一段代码中没有用的,迷惑用的,不贴上来了):
[Asm] 纯文本查看 复制代码
00401870  /$  83EC 64                  sub     esp, 64
00401873  |.  53                       push    ebx
00401874  |.  56                       push    esi
00401875  |.  57                       push    edi
00401876  |.  33DB                     xor     ebx, ebx                                          ;  int i = 0;
00401878  |.  8D7C24 0D                lea     edi, dword ptr [esp+D]
0040187C  |.  55                       push    ebp
0040187D  |.  33C0                     xor     eax, eax
0040187F  |.  B9 18000000              mov     ecx, 18
00401884  |.  885C24 10                mov     byte ptr [esp+10], bl                             ;  sn_time[0] = '\0'
00401888  |.  F3:AB                    rep     stos dword ptr es:[edi]                           ;  len 0x63
0040188A  |.  66:AB                    stos    word ptr es:[edi]
0040188C  |.  AA                       stos    byte ptr es:[edi]
0040188D  |.  33F6                     xor     esi, esi                                          ;  int j = 0;
0040188F  |.  8B6C24 7C                mov     ebp, dword ptr [esp+7C]                           ;  FirstInstallDateTime 转换成字符串后的长度 len(FirstInstallDateTime) = 7
00401893  |.  3BE8                     cmp     ebp, eax
00401895  |.  74 24                    je      short 004018BB
00401897  |.  8B5424 78                mov     edx, dword ptr [esp+78]                           ;  edx ===> SN
0040189B  |>  8BFA                     /mov     edi, edx
0040189D  |.  B9 FFFFFFFF              |mov     ecx, -1
004018A2  |.  2BC0                     |sub     eax, eax
004018A4  |.  F2:AE                    |repne   scas byte ptr es:[edi]
004018A6  |.  F7D1                     |not     ecx
004018A8  |.  49                       |dec     ecx                                              ;  len(sn)
004018A9  |.  46                       |inc     esi                                              ;  j ++
004018AA  |.  2BCD                     |sub     ecx, ebp                                         ;  len(sn) - len(company)
004018AC  |.  03CB                     |add     ecx, ebx                                         ;  c = len(sn) - len(company) + i
004018AE  |.  43                       |inc     ebx                                              ;  i++
004018AF  |.  3BF5                     |cmp     esi, ebp                                         ;  j<len(company)
004018B1  |.  8A4411 FB                |mov     al, byte ptr [ecx+edx-5]                         ;  sn[c-5]
004018B5  |.  884434 0F                |mov     byte ptr [esp+esi+F], al
004018B9  |.^ 72 E0                    \jb      short 0040189B
004018BB  |>  8D4424 10                lea     eax, dword ptr [esp+10]                           ;  sn_time == sn[installtime]段
004018BF  |.  50                       push    eax
004018C0  |.  E8 BB1B0000              call    00403480                                          ;  atoi(FirstInstallTime) = 0x0019FA69 = 1702505
004018C5  |.  83C4 04                  add     esp, 4
004018C8  |.  8BF0                     mov     esi, eax
004018CA  |.  A1 FCBE4000              mov     eax, dword ptr [40BEFC]                           ;  [0x0040BEFC] == 0x0019FA74 == 1702516, FirstInstallTime
004018CF  |.  894424 10                mov     dword ptr [esp+10], eax                           ;  eax == 1702516
004018D3  |.  C74424 14 00000000       mov     dword ptr [esp+14], 0
004018DB  |.  DF6C24 10                fild    qword ptr [esp+10]
004018DF  |.  D9C0                     fld     st
004018E1  |.  E8 731C0000              call    00403559                                          ;  tanh(1702516) = 1.0000
004018E6  |.  DC0D 20904000            fmul    qword ptr [409020]                                ;  1.0 * 11.00
004018EC  |.  DEE9                     fsubp   st(1), st                                         ;  1702516-11=1702505
004018EE  |.  E8 590D0000              call    0040264C
004018F3  |.  2BC6                     sub     eax, esi                                          ;  eax = 0x0019FA69 = 1702505
004018F5  |.  5D                       pop     ebp
004018F6  |.  5F                       pop     edi
004018F7  |.  83F8 01                  cmp     eax, 1
004018FA  |.  1BC0                     sbb     eax, eax
004018FC  |.  5E                       pop     esi
004018FD  |.  F7D8                     neg     eax
004018FF  |.  5B                       pop     ebx
00401900  |.  83C4 64                  add     esp, 64
00401903  \.  C3                       retn

就是将 FirstInstallDateTime 进行简单计算后,与输入的序列号相关字段进行比较,相等即通过。
还有一个调用(call 00401910)就是对我们在界面上输入的用户名和公司名进行校验,当中还包括注册表项 RegisteredOwner 的验证,如下:
[Asm] 纯文本查看 复制代码
00401910  /$  83EC 64                  sub     esp, 64
00401913  |.  33C0                     xor     eax, eax
00401915  |.  B9 18000000              mov     ecx, 18                                           ;  ecx == 0x18 == 24
0040191A  |.  56                       push    esi
0040191B  |.  C64424 04 00             mov     byte ptr [esp+4], 0
00401920  |.  57                       push    edi
00401921  |.  8D7C24 09                lea     edi, dword ptr [esp+9]
00401925  |.  F3:AB                    rep     stos dword ptr es:[edi]
00401927  |.  66:AB                    stos    word ptr es:[edi]
00401929  |.  BE 0C000000              mov     esi, 0C                                           ;  int i = 12
0040192E  |.  B9 FFFFFFFF              mov     ecx, -1
00401933  |.  AA                       stos    byte ptr es:[edi]
00401934  |.  8B5424 70                mov     edx, dword ptr [esp+70]                           ;  edx ===> SN
00401938  |.  2BC0                     sub     eax, eax
0040193A  |.  8BFA                     mov     edi, edx                                          ;  edi ===> SN
0040193C  |.  F2:AE                    repne   scas byte ptr es:[edi]
0040193E  |.  F7D1                     not     ecx
00401940  |.  49                       dec     ecx                                               ;  ecx = len(sn) = 0x21 = 33
00401941  |.  2B0D 80C34000            sub     ecx, dword ptr [40C380]                           ;  FirstInstallDateTime 转换成字符串后的长度
00401947  |.  83E9 05                  sub     ecx, 5                                            ;  5 (当前时间的长度 "-nnnn")
0040194A  |.  3BCE                     cmp     ecx, esi                                          ;  len(sn) - 12 <= 12
0040194C  |.  76 24                    jbe     short 00401972
0040194E  |>  8A4432 FF                /mov     al, byte ptr [edx+esi-1]                         ;  sn[i-1]
00401952  |.  46                       |inc     esi                                              ;  i++
00401953  |.  8BFA                     |mov     edi, edx                                         ;  edi ====> sn
00401955  |.  B9 FFFFFFFF              |mov     ecx, -1
0040195A  |.  884434 FB                |mov     byte ptr [esp+esi-5], al                         ;  tmp[i-12] = sn[i-1]
0040195E  |.  2BC0                     |sub     eax, eax
00401960  |.  F2:AE                    |repne   scas byte ptr es:[edi]
00401962  |.  F7D1                     |not     ecx
00401964  |.  49                       |dec     ecx
00401965  |.  2B0D 80C34000            |sub     ecx, dword ptr [40C380]                          ;  FirstInstallDateTime 转换成字符串后的长度
0040196B  |.  83E9 05                  |sub     ecx, 5                                           ;  5 (当前时间的长度 "-nnnn")
0040196E  |.  3BCE                     |cmp     ecx, esi
00401970  |.^ 77 DC                    \ja      short 0040194E
00401972  |>  8D4424 08                lea     eax, dword ptr [esp+8]                            ;  eax ===> "398378258"
00401976  |.  50                       push    eax
00401977  |.  E8 041B0000              call    00403480                                          ;  atoi()
0040197C  |.  83C4 04                  add     esp, 4
0040197F  |.  8BF8                     mov     edi, eax                                          ;  eax == 0x17BEC512 == 398378258
00401981  |.  E8 0AFCFFFF              call    00401590                                          ;  RegisteredOwner索引check
00401986  |.  8BF0                     mov     esi, eax                                          ;  eax == 0x14 == 20
00401988  |.  E8 B3FBFFFF              call    00401540                                          ;  RegisteredOwner内容check
0040198D  |.  33F0                     xor     esi, eax                                          ;  eax == 0x01BA == 442, esi = 0x01AE == 430
0040198F  |.  68 E0BD4000              push    0040BDE0                                          ;  ASCII "ite company"
00401994  |.  68 30BF4000              push    0040BF30                                          ;  ASCII "solly88"
00401999  |.  E8 42FCFFFF              call    004015E0                                          ;  注册名和公司名  checkcode
0040199E  |.  83C4 08                  add     esp, 8
004019A1  |.  03C6                     add     eax, esi                                          ;  long a = checkcode + regOwner_check
004019A3  |.  8D0CC0                   lea     ecx, dword ptr [eax+eax*8]                        ;  ecx == a * 9
004019A6  |.  8D14C8                   lea     edx, dword ptr [eax+ecx*8]                        ;  edx == a * 73
004019A9  |.  8D0C52                   lea     ecx, dword ptr [edx+edx*2]                        ;  ecx == a * 219 = 778983
004019AC  |.  C1E1 02                  shl     ecx, 2                                            ;  ecx == a * 876
004019AF  |.  2BC8                     sub     ecx, eax                                          ;  ecx == a * 875
004019B1  |.  C1E1 06                  shl     ecx, 6                                            ;  ecx == a * 875*64 = a * 56000
004019B4  |.  2BC8                     sub     ecx, eax                                          ;  ecx == a * 55999
004019B6  |.  03C9                     add     ecx, ecx                                          ;  ecx == a * 111998
004019B8  |.  894C24 08                mov     dword ptr [esp+8], ecx                            ;  ecx == 0x17BEBFB6 = 398376886
004019BC  |.  C74424 0C 00000000       mov     dword ptr [esp+C], 0
004019C4  |.  DF6C24 08                fild    qword ptr [esp+8]
004019C8  |.  D9C0                     fld     st
004019CA  |.  D9FE                     fsin                                                      ;  sin(398376886) = -0.6866350580165284495
004019CC  |.  DC0D 28904000            fmul    qword ptr [409028]                                ;  [0x00409029] = 1999.0000, sin()*1999 = -1372.5834809750404020
004019D2  |.  DEE9                     fsubp   st(1), st                                         ;  st == 398378258.58348095420 = 398376886 - (-1372.5834809750404020)
004019D4  |.  E8 730C0000              call    0040264C                                          ;  eax == 0x17BEC512 == 398378258
004019D9  |.  2BC7                     sub     eax, edi                                          ;  edi = atoi()
004019DB  |.  5F                       pop     edi
004019DC  |.  5E                       pop     esi
004019DD  |.  83F8 01                  cmp     eax, 1
004019E0  |.  1BC0                     sbb     eax, eax
004019E2  |.  83C4 64                  add     esp, 64
004019E5  |.  F7D8                     neg     eax
004019E7  \.  C3                       retn

其中,对用户名和公司名处理的调用(call 004015E0)如下所示:
[Asm] 纯文本查看 复制代码
004015E0  /$  83EC 08                  sub     esp, 8
004015E3  |.  33D2                     xor     edx, edx                                          ;  long sum = 0;
004015E5  |.  B9 FFFFFFFF              mov     ecx, -1
004015EA  |.  53                       push    ebx
004015EB  |.  66:BB 0100               mov     bx, 1                                             ;  int i = 1
004015EF  |.  56                       push    esi
004015F0  |.  8B7424 14                mov     esi, dword ptr [esp+14]                           ;  esi ===> "solly"
004015F4  |.  57                       push    edi
004015F5  |.  8BFE                     mov     edi, esi                                          ;  edi ===> "solly"
004015F7  |.  2BC0                     sub     eax, eax
004015F9  |.  F2:AE                    repne   scas byte ptr es:[edi]
004015FB  |.  F7D1                     not     ecx
004015FD  |.  49                       dec     ecx                                               ;  ecx == 用户名长度
004015FE  |.  83F9 01                  cmp     ecx, 1
00401601  |.  76 2F                    jbe     short 00401632
00401603  |>  0FBFC3                   /movsx   eax, bx                                          ;  i
00401606  |.  0FBE4430 FF              |movsx   eax, byte ptr [eax+esi-1]                        ;  eax == name[i-1]
0040160B  |.  8BC8                     |mov     ecx, eax                                         ;  ecx == name[i-1]
0040160D  |.  C1E0 02                  |shl     eax, 2                                           ;  eax == name[i-1] * 4
00401610  |.  66:43                    |inc     bx                                               ;  i++
00401612  |.  8BFE                     |mov     edi, esi                                         ;  edi ===> "solly"
00401614  |.  8D04C0                   |lea     eax, dword ptr [eax+eax*8]                       ;  eax == name[i-1] * 36,   (4*8+4)
00401617  |.  8D0CC1                   |lea     ecx, dword ptr [ecx+eax*8]                       ;  ecx == name[i-1] * 289,  (36*8+1)
0040161A  |.  8D04C9                   |lea     eax, dword ptr [ecx+ecx*8]                       ;  eax == name[i-1] * 2601, (289*9)
0040161D  |.  B9 FFFFFFFF              |mov     ecx, -1
00401622  |.  03D0                     |add     edx, eax                                         ;  sum += eax;
00401624  |.  2BC0                     |sub     eax, eax
00401626  |.  F2:AE                    |repne   scas byte ptr es:[edi]
00401628  |.  0FBFC3                   |movsx   eax, bx                                          ;  i
0040162B  |.  F7D1                     |not     ecx
0040162D  |.  49                       |dec     ecx                                              ;  len(solly)
0040162E  |.  3BC8                     |cmp     ecx, eax                                         ;  i<len(name)
00401630  |.^ 77 D1                    \ja      short 00401603                                   ;  sum = 0x00118ACA
00401632  |>  66:BB 0100               mov     bx, 1                                             ;  int i = 1
00401636  |.  8B7424 1C                mov     esi, dword ptr [esp+1C]                           ;  esi ===> "company"
0040163A  |.  8BFE                     mov     edi, esi                                          ;  edi ===> "company"
0040163C  |.  B9 FFFFFFFF              mov     ecx, -1
00401641  |.  2BC0                     sub     eax, eax
00401643  |.  F2:AE                    repne   scas byte ptr es:[edi]
00401645  |.  F7D1                     not     ecx
00401647  |.  49                       dec     ecx                                               ;  len(company)
00401648  |.  83F9 01                  cmp     ecx, 1
0040164B  |.  76 21                    jbe     short 0040166E
0040164D  |>  0FBFC3                   /movsx   eax, bx                                          ;  i
00401650  |.  66:43                    |inc     bx                                               ;  i++
00401652  |.  8BFE                     |mov     edi, esi                                         ;  edi ===> "company"
00401654  |.  0FBE4C30 FF              |movsx   ecx, byte ptr [eax+esi-1]                        ;  company[i-1]
00401659  |.  03D1                     |add     edx, ecx                                         ;  sum += company[i-1]
0040165B  |.  B9 FFFFFFFF              |mov     ecx, -1
00401660  |.  2BC0                     |sub     eax, eax
00401662  |.  F2:AE                    |repne   scas byte ptr es:[edi]
00401664  |.  0FBFC3                   |movsx   eax, bx                                          ;  i
00401667  |.  F7D1                     |not     ecx
00401669  |.  49                       |dec     ecx                                              ;  len(company)
0040166A  |.  3BC8                     |cmp     ecx, eax                                         ;  i<len(company)
0040166C  |.^ 77 DF                    \ja      short 0040164D                                   ;  sum == 0x00118D48
0040166E  |>  8D0492                   lea     eax, dword ptr [edx+edx*4]                        ;  eax = sum * 5
00401671  |.  8D0C42                   lea     ecx, dword ptr [edx+eax*2]                        ;  ecx = sum * 11
00401674  |.  894C24 0C                mov     dword ptr [esp+C], ecx                            ;  ecx == 0x00C11218 == 12653080
00401678  |.  C74424 10 00000000       mov     dword ptr [esp+10], 0
00401680  |.  DF6C24 0C                fild    qword ptr [esp+C]
00401684  |.  D9FA                     fsqrt                                                     ;  sqrt(12653080) == 3557.1168100021682220
00401686  |.  E8 C10F0000              call    0040264C                                          ;  eax == 0x0DE5 == 3557
0040168B  |.  5F                       pop     edi
0040168C  |.  5E                       pop     esi
0040168D  |.  5B                       pop     ebx
0040168E  |.  83C4 08                  add     esp, 8
00401691  \.  C3                       retn

另外对 RegisteredOwner 的验证有两次,比较简单,见注册机,不在此分析。另外,前面时间验证中,也用到了 RegisteredOwner 字符串的第1个字符(RegisteredOwner[0])的 ASCII 码值。

因为其有对注册表项进行验证,所以其需要读取注册表中的数据,不过,其在读取 FirstInstallDateTime 有问题,并没有取得这个值,而是取得保存这个值的地址,将这个地址参与了序列号的计算,这段取注册表信息的代码如下:
[Asm] 纯文本查看 复制代码
00401E59  |.  68 F8A64000              push    0040A6F8                                          ;  ASCII "FirstInstallDateTime"
00401E5E  |.  68 CCA64000              push    0040A6CC                                          ;  ASCII "SOFTWARE\Microsoft\Windows\CurrentVersion"
00401E63  |.  68 02000080              push    80000002
00401E68  |.  E8 43F6FFFF              call    004014B0                                          ;  读注册表,返回结果是一个地址,存于 EAX 并返回。
00401E6D  |.  83C4 0C                  add     esp, 0C
00401E70  |.  8B2D B4E24000            mov     ebp, dword ptr [<&user32.wsprintfA>]              ;  USER32.wsprintfA
00401E76  |.  50                       push    eax                                               ; /<%lu>,这里有Bug,传入的不是读取的时间,而是指向时间的地址指针,固定为 0x0019FA74
00401E77  |.  68 C8A64000              push    0040A6C8                                          ; |Format = "%lu",此格式是将返回地址当作一个无符号长整数进行操作
00401E7C  |.  68 90BF4000              push    0040BF90                                          ; |s = [url=mailto:Torn@do_.0040BF90]Torn@do_.0040BF90[/url]
00401E81  |.  FFD5                     call    ebp                                               ; \wsprintfA
00401E83  |.  83C4 0C                  add     esp, 0C
00401E86  |.  BF 90BF4000              mov     edi, 0040BF90                                     ;  ASCII "1702516"
00401E8B  |.  68 90BF4000              push    0040BF90                                          ;  ASCII "1702516"
00401E90  |.  E8 EB150000              call    00403480                                          ;  atoi(pointer)
00401E95  |.  83C4 04                  add     esp, 4
00401E98  |.  B9 FFFFFFFF              mov     ecx, -1
00401E9D  |.  A3 FCBE4000              mov     dword ptr [40BEFC], eax                           ;  保存 0x0019FA74,实际是一个地址指针,不是注册表的 FirstInstallDateTime
00401EA2  |.  2BC0                     sub     eax, eax
00401EA4  |.  F2:AE                    repne   scas byte ptr es:[edi]
00401EA6  |.  F7D1                     not     ecx
00401EA8  |.  49                       dec     ecx                                               ;  前面timestamp字符串的长度
00401EA9  |.  68 B8A64000              push    0040A6B8                                          ;  ASCII "RegisteredOwner"
00401EAE  |.  68 CCA64000              push    0040A6CC                                          ;  ASCII "SOFTWARE\Microsoft\Windows\CurrentVersion"
00401EB3  |.  890D 80C34000            mov     dword ptr [40C380], ecx                           ;  保存时间字符串的长度
00401EB9  |.  68 02000080              push    80000002
00401EBE  |.  E8 EDF5FFFF              call    004014B0                                          ;  读注册表

问题出在调用 wsprintf() 这个函数的参数,因为 Call 004014B0 这个函数读取注册表信息后,返回的是一个地址,而 wsprintf()中,引用的是这个地址,所以转换成字符串也是一个地址值,不是真正的 FirstInstallDateTime的值,如果要修改这个 Bug,可以进行以下修改,如下图所示:
31.png
将 0x00401E6D处的 add esp, 0C 改成 mov eax, [eax],然后在下面 0x00401E83 处的 add esp, 0C 改成 add esp, 18,这样堆栈也平衡了,Bug也消除了。

基本的注册验证过程分析到这里,用注册机生成注册码,并抓紧时间输入(粘贴),校验正确时,显示如下:
40.png
一定要注意时间,最好在当前分钟的前 0~30秒内生成序列号,后30秒来输入注册码并验证,不然可能序列号就过期了。

另外,在 Windows 10 之类的新版 Windows 下,缺少注册表项,需要导入以下信息,不然也通不过 CrackMe 的注册验证,64位系统如下:
[HTML] 纯文本查看 复制代码
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion]
"FirstInstallDateTime"=hex:c1,b1,98,4c
"RegisteredOrganization"="ite"
"RegisteredOwner"="solly"
"ProductId"="51163-030-0389753-07447"

32位系统如下:
[HTML] 纯文本查看 复制代码
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion]
"FirstInstallDateTime"=hex:c1,b1,98,4c
"RegisteredOrganization"="ite"
"RegisteredOwner"="solly"
"ProductId"="51163-030-0389753-07447"

当然,键值可以改成自己的,键名不能改动。

分析完毕,下面是注册机源码,使用 Dev-C++调试通过:
[Asm] 纯文本查看 复制代码
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <windows.h>

union CBData{
        DWORD n;
        byte buffer[256];
};

CBData readKey(HKEY hKey, char * path, char * key);
void getRegInfo();
void getPart1();
void getPart2();
long getRegTimeStamp(int index);
long getCheckRegOwner();
long getCheck(char * name, char * company, int index); 
void getCurrDateTime(int index);

bool testSoftICE95();
bool testSoftICENT();

char sn[48];
CBData data;
long nFirstInstallDateTime = 0;
long nLenOfFirstInstallDateTime = 0;
char sFirstInstallDateTime[128];
char RegisteredOwner[128];
char RegisteredOrganization[128];
char ProductId[128];

int main(int argc, char** argv) {
        memset(sn, 0, 48);
        memset(sFirstInstallDateTime, 0, 128);
        memset(RegisteredOwner, 0, 128);
        memset(RegisteredOrganization, 0, 128);
        memset(ProductId, 0, 128);
        
        getRegInfo();
        
        getPart1();
        sn[5] = '-';

        getPart2();
        sn[10] = '-';
        
        char name[]    = "solly88";
        char company[] = "ite company";
        int n = getCheck(name, company, 11);

    sn[10+n+1] = '-';

        int m = getRegTimeStamp(10+n+2); 
        
        sn[10+n+2+m] = '-';
        
        /// 最后4字节为当前时间检查 
        getCurrDateTime(10+n+3+m);
        
        printf("\n SN = %s\n", sn);
        
        return 0;
}

void getPart1() {
    sn[1] = 0x0D ^ 0x49;
    sn[2] = 0x07 ^ 0x44;
    sn[3] = 0x0D ^ 0x39;
    sn[0] = 0x1D ^ 0x54;
    sn[4] = 0x09 ^ 0x39;
} 

void getPart2() {
        sn[7] = 0x06 ^ 0x52;
        sn[8] = 0x07 ^ 0x45;
        sn[9] = 0x1F ^ 0x53;
        sn[6] = 0x11 ^ 0x54;
}

/**

***/
/// FirstInstallTime 
long getRegTimeStamp(int index) {
        /// 0040BF90:  1702516
    //long a = 1702505;
    ////
    //long FirstInstallDateTime = 1702516; /// 实际上是一个指向保存FirstInstallDateTime的内存地址 Win10
    //long FirstInstallDateTime = 6617404; /// 实际上是一个指向保存FirstInstallDateTime的内存地址 Win98
    //long FirstInstallDateTime = 6682940; /// 实际上是一个指向保存FirstInstallDateTime的内存地址 Win98_unpacked
    long FirstInstallDateTime = nFirstInstallDateTime; /// 正常时是一个 Timestamp 
    
    long a = FirstInstallDateTime - tanh(FirstInstallDateTime) * 11.0;  /// 当在win10下取的是地址时,这里是固定值 1702505 
             
    //char str_a[8];
    sprintf(sFirstInstallDateTime, "%d", a);
    long n = strlen(sFirstInstallDateTime);
    for(int i=0; i<n; i++ ) {
            sn[index + i] = sFirstInstallDateTime[i];
        }
        
        return n;
}

long getCheckRegOwner() {  // Proc_00401590 和 Proc_00401540 
        long sum1 = 0;
        long sum2 = 0;
        long n = strlen(RegisteredOwner);
        for(int i=1; i<n; i++) {
                sum1 += i*2;
                sum2 += RegisteredOwner[i-1];
        }
        //printf("check reg owner: %d - %d\n", sum1, sum2);
        
        return sum1 ^ sum2;
}

long getCheck(char * name, char * company, int index) {  /// Proc_004015E0

        long checkbase = getCheckRegOwner();
        
        long sum = 0;
        int n = strlen(name);
        for(int i=0; i<n-1; i++) {
                sum += name[i] * 2601;
        }
        int m = strlen(company);
        for(int i=0; i<m-1; i++) {
                sum += company[i];
        }
        
        double x = sum * 11;
        int code1 = (long)sqrt(x);
        ////
        //printf("check code1: %d, %d\n", sum, code1);
        long a = code1 + checkbase;
        long c = a * 111998;
        double y = c - sin(c) * 1999.0;
        long code2 = (long)y;
        
        //printf("check code2: %d\n", code2);
        char code_str[12];
        sprintf(code_str, "%d", code2);
        int len = strlen(code_str);
        for(int i=0; i<len; i++) {
                sn[index+i] = code_str[i];
        }
        
        return len;
}

bool testSoftICE95() {
        HANDLE h = CreateFile("\\\\.\\SICE", 
                              GENERIC_READ|GENERIC_WRITE, 
                                                  FILE_SHARE_READ|FILE_SHARE_WRITE, 
                                                  NULL, OPEN_EXISTING, 
                                                  FILE_ATTRIBUTE_NORMAL, NULL);
        if(h != INVALID_HANDLE_VALUE) {
                CloseHandle(h);
                return true;
        }
        
        return false;
} 

bool testSoftICENT() {
        HANDLE h = CreateFile("\\\\.\\NTICE", 
                              GENERIC_READ|GENERIC_WRITE, 
                                                  FILE_SHARE_READ|FILE_SHARE_WRITE, 
                                                  NULL, OPEN_EXISTING, 
                                                  FILE_ATTRIBUTE_NORMAL, NULL);
        if(h != INVALID_HANDLE_VALUE) {
                CloseHandle(h);
                return true;
        }
        
        return false;
} 

/// Current date and time
void getCurrDateTime(int index) {
        long a = RegisteredOwner[0];
        time_t timer;
        struct tm * st;
        time(&timer);
        st = localtime(&timer);
        long t = (st->tm_year + 1900) + ((st->tm_mon + 1) * st->tm_mday - a) + st->tm_hour * st->tm_min; 
        
        ///// SoftICE 检查,修正时间检查值(基本无用) 
        bool isExistsSICE95 = testSoftICE95();
        bool isExistsSICENT = testSoftICENT();
        
        if (isExistsSICE95) {
                t += 0x143;
        }
        if (isExistsSICENT) {
                t += 0x271;
        }

        char str_t[12];
        itoa(t, str_t, 10);
        sn[index] = str_t[0];
        sn[index+1] = str_t[1]; 
        sn[index+2] = str_t[2]; 
        sn[index+3] = str_t[3]; 
        ///
        //printf("time: %d-%d-%d %d:%d\n", st->tm_year+1900, st->tm_mon+1, st->tm_mday, st->tm_hour, st->tm_min)        ;
}

CBData readKey(HKEY hKey, char * path, char * key) {
        HKEY h = (HKEY)-1; 
        DWORD cbData;
        DWORD regType = -1;

        data.n = 1;
        
        long s = RegOpenKeyEx(hKey, path, 0, KEY_READ, &h);
        if( s != ERROR_SUCCESS) {
                data.n = -1;
                return data;
        }
        
        s = RegQueryValueEx(h, key, NULL, NULL, NULL, &cbData);
        if(s == ERROR_SUCCESS) {
                RegQueryValueEx(h, key, NULL, & regType, data.buffer, &cbData);
        }
        
        RegCloseKey(h);
        
        return data; 
}

void getRegInfo() {
        char subKey[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion";
        char key1[] = "FirstInstallDateTime";
        char key2[] = "RegisteredOwner";
        char key3[] = "RegisteredOrganization";
        char key4[] = "ProductId";
        CBData cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key1);
        nFirstInstallDateTime = cb.n;
        struct tm * tm_reg = localtime((time_t *)&nFirstInstallDateTime);
        sprintf(sFirstInstallDateTime, "%lu", nFirstInstallDateTime);
        nLenOfFirstInstallDateTime = strlen(sFirstInstallDateTime);
        printf(" DateTime: %d-%d-%d %d:%d:%d\n", tm_reg->tm_year + 1900, tm_reg->tm_mon + 1, 
                                tm_reg->tm_mday, tm_reg->tm_hour, tm_reg->tm_min, tm_reg->tm_sec);
        printf("Timestamp: %d,  len=%d\n", nFirstInstallDateTime, nLenOfFirstInstallDateTime);
        ////
        cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key2);
        strcpy(RegisteredOwner, (char *)cb.buffer);
        ////
        cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key3);
        strcpy(RegisteredOrganization, (char *)cb.buffer);
        ////
        cb = (CBData)readKey(HKEY_LOCAL_MACHINE, subKey, key4);
        strcpy(ProductId, (char *)cb.buffer);
        
        printf("             ProductId: %s\n", ProductId);
        printf("       RegisteredOwner: %s\n", RegisteredOwner);
        printf("RegisteredOrganization: %s\n", RegisteredOrganization);
}


41.png

免费评分

参与人数 5吾爱币 +7 热心值 +4 收起 理由
HackerWen + 1 + 1 用心讨论,共获提升!
py看考场 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
天空藍 + 1 + 1 谢谢@Thanks!
pk8900 + 3 + 1 谢谢楼主的帖子,学到了不少东西。
xtuuqtbl + 1 恭喜楼主还差一个CM就超神了

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| solly 发表于 2019-7-15 02:27

160 个 CrackMe 之 078 - fireworx.10 注册算法中的变量初始化 BUG 分析

本帖最后由 solly 于 2019-8-5 22:51 编辑

CrackMe 078 是一个 Delphi 编译的 CrackMe,也是加壳的,OD 加载后,入口代码是以下4行代码:
[Asm] 纯文本查看 复制代码
00429318 >  90                       nop
00429319    90                       nop
0042931A    90                       nop
0042931B    75 00                    jnz     short 0042931D
0042931D  - E9 DE5C0400              jmp     0046F000

最后的跳转指令是跳转到壳代码入口,如下所示,解壳代码也简单:
[Asm] 纯文本查看 复制代码
0046F000    60                       pushad
0046F001    E8 00000000              call    0046F006
0046F006    5D                       pop     ebp
0046F007    81ED EAA84300            sub     ebp, 0043A8EA
0046F00D    B8 E4A84300              mov     eax, 0043A8E4
0046F012    03C5                     add     eax, ebp
0046F014    2B85 78AD4300            sub     eax, dword ptr [ebp+43AD78]
0046F01A    8985 84AD4300            mov     dword ptr [ebp+43AD84], eax
0046F020    80BD 6EAD4300 00         cmp     byte ptr [ebp+43AD6E], 0
0046F027    75 15                    jnz     short 0046F03E
0046F029    FE85 6EAD4300            inc     byte ptr [ebp+43AD6E]
0046F02F    E8 1D000000              call    0046F051
0046F034    E8 73020000              call    0046F2AC
0046F039    E8 0A030000              call    0046F348
0046F03E    8B85 70AD4300            mov     eax, dword ptr [ebp+43AD70]
0046F044    0385 84AD4300            add     eax, dword ptr [ebp+43AD84]
0046F04A    894424 1C                mov     dword ptr [esp+1C], eax
0046F04E    61                       popad
0046F04F    FFE0                     jmp     eax

在 0x0046F04F jmp eax 处,按 F4 就脱壳了,再 F8 就到了 OEP,可以进行脱壳,脱壳后也需要象 159 一样,进行 API 导入表手动修正,就是修正 DefWindowProc() 的引用。
正常启动后,界面如下:
20.png

如果成功注册,会显示以下界面:
38.png
当什么都不输入时,点击“OK”图片,会引发其第一个BUG,如下图所示:
22.png
我们随便输入一些数据,进行验证:
32.png
但是这个 CrackMe 的注册验证中,用到了一个未有效初始化的值,ESI 中的值,这个值应该是一个 Delphi 函数的 Sender 参数值,不过直接将其当作求累加和的基数,得不到正确的注册码。这可能是其第二个 Bug。
其事件处理代码如下:
[Asm] 纯文本查看 复制代码
00423F88   .  53              push    ebx
00423F89   .  56              push    esi
00423F8A   .  57              push    edi
00423F8B   .  83C4 E8         add     esp, -18
00423F8E   .  8BFA            mov     edi, edx
00423F90   .  8BF0            mov     esi, eax                        ; ESI = EAX = Sender,这里初始化的 ESI。
00423F92   .  8BD7            mov     edx, edi
00423F94   .  8BC6            mov     eax, esi
00423F96   .  8B08            mov     ecx, dword ptr [eax]
00423F98   .  FF51 F0         call    dword ptr [ecx-10]
00423F9B   .  F646 40 02      test    byte ptr [esi+40], 2
00423F9F   .  74 09           je      short 00423FAA
00423FA1   .  33D2            xor     edx, edx
00423FA3   .  8BC6            mov     eax, esi
00423FA5   .  E8 8AEAFFFF     call    00422A34
00423FAA   >  F646 44 02      test    byte ptr [esi+44], 2
00423FAE   .  74 3B           je      short 00423FEB
00423FB0   .  66:8366 44 FD   and     word ptr [esi+44], 0FFFD
00423FB5   .  8BD4            mov     edx, esp
00423FB7   .  8B47 08         mov     eax, dword ptr [edi+8]
00423FBA   .  E8 7D25FEFF     call    0040653C
00423FBF   .  FF7424 04       push    dword ptr [esp+4]
00423FC3   .  FF7424 04       push    dword ptr [esp+4]
00423FC7   .  8D5424 10       lea     edx, dword ptr [esp+10]
00423FCB   .  8BC6            mov     eax, esi
00423FCD   .  8B08            mov     ecx, dword ptr [eax]
00423FCF   .  FF51 44         call    dword ptr [ecx+44]
00423FD2   .  8D4424 10       lea     eax, dword ptr [esp+10]    ; |
00423FD6   .  50              push    eax                        ; |pRect
00423FD7   .  E8 9423FEFF     call    <jmp.&user32.PtInRect>     ; \PtInRect
00423FDC   .  85C0            test    eax, eax
00423FDE   .  74 0B           je      short 00423FEB
00423FE0   .  8BC6            mov     eax, esi
00423FE2   .  66:BB ECFF      mov     bx, 0FFEC
00423FE6   .  E8 25EEFDFF     call    00402E10                   ; 这里会间接去 call Image2Click()
00423FEB   >  8BD7            mov     edx, edi
00423FED   .  33C9            xor     ecx, ecx
00423FEF   .  8BC6            mov     eax, esi
00423FF1   .  E8 56FFFFFF     call    00423F4C
00423FF6   .  83C4 18         add     esp, 18
00423FF9   .  5F              pop     edi
00423FFA   .  5E              pop     esi
00423FFB   .  5B              pop     ebx
00423FFC   .  C3              retn


上面是Image控件的事件处理框架代码,通过 call 00402E10 调用Click处理代码,进行注册验证,验证代码如下:
[Asm] 纯文本查看 复制代码
00453E94  /.  55              push    ebp
00453E95  |.  8BEC            mov     ebp, esp
00453E97  |.  6A 00           push    0
00453E99  |.  6A 00           push    0
00453E9B  |.  6A 00           push    0
00453E9D  |.  53              push    ebx
00453E9E  |.  56              push    esi
00453E9F  |.  57              push    edi
00453EA0  |.  8BF8            mov     edi, eax                    ;  Sender 参数
00453EA2  |.  33C0            xor     eax, eax
00453EA4  |.  55              push    ebp                         ;  指向本函数返回地址
00453EA5  |.  68 B63F4500     push    00453FB6                    ;  SEH
00453EAA  |.  64:FF30         push    dword ptr fs:[eax]          ;  Save old SEH
00453EAD  |.  64:8920         mov     dword ptr fs:[eax], esp     ;  Install new SEH
00453EB0  |.  8D55 FC         lea     edx, dword ptr [ebp-4]      ;  接收指向用户名缓冲区的指针
00453EB3  |.  8B87 C8020000   mov     eax, dword ptr [edi+2C8]    ;  Owner 参数,控件对象实例
00453EB9  |.  E8 5AE9FCFF     call    00422818                    ;  TControl.GetText(), 取得用户名,eax 为长度
00453EBE  |.  33DB            xor     ebx, ebx                    ;  int i = 0
00453EC0  |>  8B45 FC         /mov     eax, dword ptr [ebp-4]     ;  eax ===> 用户名: "solly",最多19位,多出部分无效。
00453EC3  |.  0FB64418 FF     |movzx   eax, byte ptr [eax+ebx-1]  ;  name[i],从delphi字符串长度最高位字节起(0x00),即 name[0], movzx 无符号扩展
00453EC8  |.  03F0            |add     esi, eax                   ;  esi 初始化值等于 0x02308CFC(Win10 64bit),sum += Ord(name[i])
00453ECA  |.  8D55 F8         |lea     edx, dword ptr [ebp-8]     ;  保存返回地址的指针
00453ECD  |.  8BC6            |mov     eax, esi                   ;  只有esi变成负数才有可能转换成11字符的字符串
00453ECF  |.  E8 9437FBFF     |call    00407668                   ;  IntToStr()
00453ED4  |.  8D55 F4         |lea     edx, dword ptr [ebp-C]
00453ED7  |.  8B87 D0020000   |mov     eax, dword ptr [edi+2D0]
00453EDD  |.  E8 36E9FCFF     |call    00422818                   ;  取得注册码假码"7878787878"
00453EE2  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]     ;  eax ===> 输入的注册码
00453EE5  |.  8A00            |mov     al, byte ptr [eax]         ;  sn[0]
00453EE7  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]     ;  edx ===> 计算的注册码
00453EEA  |.  3A02            |cmp     al, byte ptr [edx]         ;  假码第一个字符与name求和字符串第一个字符比较 sn[0] == IntToStr(sum)[0]
00453EEC  |.  0F85 9F000000   |jnz     00453F91
00453EF2  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]     ;  eax ===> 输入的注册码
00453EF5  |.  8A40 01         |mov     al, byte ptr [eax+1]       ;  sn[1]
00453EF8  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]     ;  edx ===> 计算的注册码
00453EFB  |.  3A42 01         |cmp     al, byte ptr [edx+1]
00453EFE  |.  0F85 8D000000   |jnz     00453F91
00453F04  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]     ;  eax ===> 输入的注册码
00453F07  |.  8A40 02         |mov     al, byte ptr [eax+2]       ;  sn[2]
00453F0A  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]     ;  edx ===> 计算的注册码
00453F0D  |.  3A42 02         |cmp     al, byte ptr [edx+2]
00453F10  |.  75 7F           |jnz     short 00453F91
00453F12  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]
00453F15  |.  8A40 03         |mov     al, byte ptr [eax+3]       ;  sn[3]
00453F18  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]
00453F1B  |.  3A42 03         |cmp     al, byte ptr [edx+3]
00453F1E  |.  75 71           |jnz     short 00453F91
00453F20  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]
00453F23  |.  8A40 04         |mov     al, byte ptr [eax+4]       ;  sn[4]
00453F26  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]
00453F29  |.  3A42 04         |cmp     al, byte ptr [edx+4]
00453F2C  |.  75 63           |jnz     short 00453F91
00453F2E  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]
00453F31  |.  8A40 05         |mov     al, byte ptr [eax+5]       ;  sn[5]
00453F34  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]
00453F37  |.  3A42 05         |cmp     al, byte ptr [edx+5]
00453F3A  |.  75 55           |jnz     short 00453F91
00453F3C  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]
00453F3F  |.  8A40 06         |mov     al, byte ptr [eax+6]       ;  sn[6]
00453F42  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]
00453F45  |.  3A42 06         |cmp     al, byte ptr [edx+6]
00453F48  |.  75 47           |jnz     short 00453F91
00453F4A  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]
00453F4D  |.  8A40 07         |mov     al, byte ptr [eax+7]       ;  sn[7]
00453F50  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]
00453F53  |.  3A42 07         |cmp     al, byte ptr [edx+7]
00453F56  |.  75 39           |jnz     short 00453F91
00453F58  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]
00453F5B  |.  8A40 08         |mov     al, byte ptr [eax+8]       ;  sn[8]
00453F5E  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]
00453F61  |.  3A42 08         |cmp     al, byte ptr [edx+8]
00453F64  |.  75 2B           |jnz     short 00453F91
00453F66  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]
00453F69  |.  8A40 09         |mov     al, byte ptr [eax+9]       ;  sn[9]
00453F6C  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]
00453F6F  |.  3A42 09         |cmp     al, byte ptr [edx+9]
00453F72  |.  75 1D           |jnz     short 00453F91
00453F74  |.  8B45 F4         |mov     eax, dword ptr [ebp-C]
00453F77  |.  8A40 0A         |mov     al, byte ptr [eax+A]       ;  sn[10]
00453F7A  |.  8B55 F8         |mov     edx, dword ptr [ebp-8]
00453F7D  |.  3A42 0A         |cmp     al, byte ptr [edx+A]       ;  总共11次字符比较,只有当 ESI 的值为负数(-1000000000以下)可以转换成11位字符串
00453F80  |.  75 0F           |jnz     short 00453F91
00453F82  |.  A1 EC654500     |mov     eax, dword ptr [4565EC]
00453F87  |.  8B00            |mov     eax, dword ptr [eax]
00453F89  |.  8B10            |mov     edx, dword ptr [eax]
00453F8B  |.  FF92 CC000000   |call    dword ptr [edx+CC]         ;  显示成功的消息
00453F91  |>  43              |inc     ebx
00453F92  |.  83FB 13         |cmp     ebx, 13
00453F95  |.^ 0F85 25FFFFFF   \jnz     00453EC0
00453F9B  |.  33C0            xor     eax, eax
00453F9D  |.  5A              pop     edx
00453F9E  |.  59              pop     ecx
00453F9F  |.  59              pop     ecx
00453FA0  |.  64:8910         mov     dword ptr fs:[eax], edx
00453FA3  |.  68 BD3F4500     push    00453FBD
00453FA8  |>  8D45 F4         lea     eax, dword ptr [ebp-C]
00453FAB  |.  BA 03000000     mov     edx, 3
00453FB0  |.  E8 57F8FAFF     call    0040380C
00453FB5  \.  C3              retn
00453FB6   .^ E9 EDF2FAFF     jmp     004032A8
00453FBB   .^ EB EB           jmp     short 00453FA8
00453FBD   .  5F              pop     edi
00453FBE   .  5E              pop     esi
00453FBF   .  5B              pop     ebx
00453FC0   .  8BE5            mov     esp, ebp
00453FC2   .  5D              pop     ebp
00453FC3   .  C3              retn

序列号就是对用户名的所有字符的 ASCII 码值求累加和,并与esi中的值相加,再转换成一个10进制的字符串。
而Bug问题出在 0x00453EC8  add esi, eax 这一行,这里 esi 没有在事件函数内初始化,而是直接引用的函数外传入的值(应该是上一层函数 Sender 对象的地址值),并且在不同的操作系统环境,有没有脱壳等不同情况下,其值不固定,所以这应该算是一个BUG,不然,无论怎么处理也得不到11位注册码来进行校验。根据上面的比较代码,注册码有11位,只有当 esi 为负数时(至少小于-1000000000)才可能通过 IntToStr() 函数转换成11位注册码。但是,地址值 0x80000000 ~ 0xFFFFFFFF 都是操作系统的地址空间,应用程序中不会产生 0x80000000 以上的变量地址值,所以,就算通过内存注册机方式,这个 crackme 基本上也没有可能通过其验证算法。

只有修改 esi 的初始值在 0x80000000 以上、0xC4653600以下时才可能生成11位的序列号,至于怎么改,就不讨论了,这里只指出这可能是一个 bug。
wapj152321 发表于 2019-7-15 08:08
hyhhj 发表于 2019-7-16 20:11
我怎么什么多看不懂啊,有没有基础点的教程啊,,我刚开始学
qazwsx_c 发表于 2019-7-16 20:23

谢谢楼主分享
灵影 发表于 2019-7-17 10:32
学学思路,任重道远啊。自己一上手就蒙了
ABKing 发表于 2019-8-8 14:41
谢谢楼主分享
HackerWen 发表于 2019-8-15 10:08
楼主是把160个CrackMe都制服了啊
zch333333 发表于 2019-11-19 07:10
谢谢楼主分享
ghl32116 发表于 2019-11-20 00:38
多谢楼主教程 积累经验是一切的一切
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 13:35

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表