吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4717|回复: 1
收起左侧

[原创] 160 个 CrackMe 之 043 -- Ding Boy 之脱壳及patch过程

[复制链接]
solly 发表于 2019-6-16 12:25
本帖最后由 solly 于 2019-6-16 16:32 编辑

160 个 CrackMe 之 043 -- Ding Boy 是一个加了壳的 CrackMe,并且这个壳只能在 Win9x 下运行,因为其壳在搜索第一个API(LoadLibraryA)的入口时,使用了判断API头4个字节特征码的方法,在 Windows NT 系列操作系统上无效,导致取不到API入口。如果取到LoadLibraryA()的入口,则GetProcAddress()取一个固定值(应该只能针对某个版本的Windows)其它API入口,则由GetProcAddress()取得。
脱了壳以后,Crackme可以在Window 10 下正常运行。但跟踪过程是在虚拟win98下进行的。
先看看带壳时的文件信息。
info.png

直接运行会弹出一个”此软件试用期已过。。。”的NAG,然后退出。
000.bmp
看标题是一个叫 PE-lock的壳,找不到相关信息,手动脱壳,用OD载入,如下图:
01.png

第一条指令是 PUSHFD,不过 PUSHAD,ESP定律用不上,三个 jmp后面的代码较乱,应该是加密了的代码数据。
按F8执行,执行三段代码(中间通过jmp衔接),如下:
[Asm] 纯文本查看 复制代码
;程序壳代码的入口:
00419319 >  9C              pushfd
0041931A    55              push    ebp
0041931B    E8 EC000000     call    0041940C
00419320    87D5            xchg    ebp, edx
00419322    5D              pop     ebp
00419323    60              pushad
00419324    87D5            xchg    ebp, edx
00419326    80BD 15274000 0>cmp     byte ptr [ebp+402715], 1
0041932D    74 39           je      short 00419368
0041932F    C685 15274000 0>mov     byte ptr [ebp+402715], 1
00419336    E9 E4000000     jmp     0041941F

;/////////////////////////////////////////////////////////////

0041941F    E8 1B000000     call    0041943F
00419424    8B6424 08       mov     esp, dword ptr [esp+8]
00419428    E8 DFFFFFFF     call    0041940C
0041942D    C685 CC264000 C>mov     byte ptr [ebp+4026CC], 0C3
00419434    E8 4BFFFFFF     call    00419384
00419439  ^ E9 16FFFFFF     jmp     00419354

;/////////////////////////////////////////////////////////////

00419354    8DBD 24264000   lea     edi, dword ptr [ebp+402624]
0041935A    B9 3B000000     mov     ecx, 3B
0041935F    F3:AA           rep     stos byte ptr es:[edi]
00419361    64:67:8F06 0000 pop     dword ptr fs:[0]
00419367    5A              pop     edx
00419368    8B85 0D274000   mov     eax, dword ptr [ebp+40270D]
0041936E    0185 09274000   add     dword ptr [ebp+402709], eax
00419374    61              popad
00419375    9D              popfd
00419376    8B9A 09274000   mov     ebx, dword ptr [edx+402709]
0041937C    898A 09274000   mov     dword ptr [edx+402709], ecx
00419382    FFE3            jmp     ebx                              ; ebx = 0x00419000

最后一条 JMP ebx,ebx = 0x00419000,通过前面程序信息中的节信息,可以看出这是一个代码节(节名“NET”)的起点,跳转过去后如下图所示:
05.png
这里也包括明文代码和加密代码,从 0x00419025 开始的代码是加密的,而明文代码的作用就是解密(解密函数调用 call 00419309)。
解密函数内容如下:
[Asm] 纯文本查看 复制代码
/00419309    60              pushad
|0041930A    03F1            add     esi, ecx
|0041930C    4E              dec     esi
|0041930D    8A06            mov     al, byte ptr [esi]
|0041930F    3246 01         xor     al, byte ptr [esi+1]
|00419312    8806            mov     byte ptr [esi], al
|00419314    4E              dec     esi
|00419315  ^ E2 F6           loopd   short 0041930D
|00419317    61              popad      ; F4 到这里,执行前面的循环
\00419318    C3              retn       ; 返回到 DING_BOY.00419025 来自00419020 call 00419309

解密方法也简单,就是xor下一字节(code[ i ] = code[ i ] xor code[ i+1 ])。
如上图所示,那个call 00419309 需要按 F7 跟入,然后在 00419317 popad 处按  F4 执行解密过程,几个F8返回。解密后的代码如下:
[Asm] 纯文本查看 复制代码
; 下面进入第一阶段的时间检查和解码过程
00419000    55              push    ebp
00419001    57              push    edi
00419002    56              push    esi
00419003    52              push    edx
00419004    51              push    ecx
00419005    53              push    ebx
00419006    E8 00000000     call    0041900B
0041900B    5D              pop     ebp
0041900C    8BD5            mov     edx, ebp
0041900E    81ED 23354000   sub     ebp, 00403523
00419014    BE 3D354000     mov     esi, 0040353D
00419019    03F5            add     esi, ebp
0041901B    B9 E4020000     mov     ecx, 2E4
00419020    E8 E4020000     call    00419309                          ; 必须 F7 进入调用
;-----------------------------------------------------------------------------------
; 上面的调用 retn 到这里,进行时间过期检查,通过则继续解码             
00419025    E8 99000000     call    004190C3                          ; 取得 GetSystemTime, MessageBoxA 等 API 的入口
0041902A    83BD 8F374000 0>cmp     dword ptr [ebp+40378F], 0
00419031    74 4C           je      short 0041907F
00419033    2B95 55364000   sub     edx, dword ptr [ebp+403655]
00419039    83EA 0B         sub     edx, 0B
0041903C    8995 5D364000   mov     dword ptr [ebp+40365D], edx
00419042    BE B7374000     mov     esi, 004037B7
00419047    03F5            add     esi, ebp
00419049    56              push    esi
0041904A    FF95 93374000   call    dword ptr [ebp+403793]                     ; GetSystemTime
00419050    66:83BD B937400>cmp     word ptr [ebp+4037B9], 1                   ; 1月
00419058    72 31           jb      short 0041908B
0041905A    66:81BD B737400>cmp     word ptr [ebp+4037B7], 7D0                 ; 2000年
00419063    72 26           jb      short 0041908B                             ; 必须跳转,必须跳转,必须跳转
00419065    B8 69374000     mov     eax, 00403769
0041906A    03C5            add     eax, ebp
0041906C    BB F9374000     mov     ebx, 004037F9
00419071    03DD            add     ebx, ebp
00419073    6A 00           push    0
00419075    50              push    eax
00419076    53              push    ebx
00419077    6A 00           push    0
00419079    FF95 8F374000   call    dword ptr [ebp+40378F]                     ; 显示过期NAG
0041907F    B8 FFFFFFFF     mov     eax, -1
00419084    5B              pop     ebx
00419085    59              pop     ecx
00419086    5A              pop     edx
00419087    5E              pop     esi
00419088    5F              pop     edi
00419089    5D              pop     ebp
0041908A    C3              retn
0041908B    BE 61364000     mov     esi, 00403661                              ; 没有过期继续解码
00419090    03F5            add     esi, ebp
00419092    833E 00         cmp     dword ptr [esi], 0
00419095    74 16           je      short 004190AD
00419097    8B9D 5D364000   mov     ebx, dword ptr [ebp+40365D]
0041909D    031E            add     ebx, dword ptr [esi]
0041909F    8B4E 04         mov     ecx, dword ptr [esi+4]
004190A2    802B 01         sub     byte ptr [ebx], 1
004190A5    43              inc     ebx
004190A6  ^ E2 FA           loopd   short 004190A2
004190A8    83C6 08         add     esi, 8
004190AB  ^ EB E5           jmp     short 00419092
004190AD    8B85 59364000   mov     eax, dword ptr [ebp+403659]                ; F4 到这里,执行前面的循环
004190B3    8B9D 5D364000   mov     ebx, dword ptr [ebp+40365D]
004190B9    03C3            add     eax, ebx
004190BB    5B              pop     ebx
004190BC    59              pop     ecx
004190BD    5A              pop     edx
004190BE    5E              pop     esi
004190BF    5F              pop     edi
004190C0    5D              pop     ebp004190C1    FFE0            jmp     eax                                        ; eax = 00418000

上面代码中解码的第一条指令 00419025    E8 99000000     call    004190C3, 就是动态查找和填充 API 用的,包用 LoadLibraryA(),GetProcAddress(),GetSystemTime() 和 MessageBoxA() 等函数。如下图所示,已找到 LoadLibraryA()函数:
14.png
以及:
16.png

上面查找完 API 入口地址并返回后,几个 F8 执行到 00419063    jb      short 0041908B 时,必须通过修改 EIP 实现跳转,不然就是显示上面的“本软件试用期已过。。。。”的对话框,然后就会退出CrackMe了。
如下图,修改 EIP 进行跳转:
19.png
在 0x0041908B 这一行上按右键,弹出OD的右键菜单,选择”此处为新 EIP“,会弹出一个如上图所示的消息框,选”是“即可,修改好EIP后的情况如下图所示:
20.png
新的EIP已改为 0x0041908B,这里也是一段解码程序,定位到 0x004190AD 这一行代码,然后按 F4 跳过解码过程,几个 F8 来到 0x004190C1,这里是一个JMP eax 指令,eax = 0x00418000,通过前面的节信息可知,这是另一个代码节的开始地址。
后面几个节的执行过程与 0x00419000这一节的代码完全一样,操作过程也一样,包括 0x00418000, 0x00417000, 0x00416000 这三个节,功能和操作方法完全一样(都要同样修改EIP),当执行到 0x00416000这一节最后面时,如下:
[Asm] 纯文本查看 复制代码
0041608B    BE 61364000     mov     esi, 00403661                              ; 新的EIP,继续解码
00416090    03F5            add     esi, ebp
00416092    833E 00         cmp     dword ptr [esi], 0
00416095    74 16           je      short 004160AD
00416097    8B9D 5D364000   mov     ebx, dword ptr [ebp+40365D]
0041609D    031E            add     ebx, dword ptr [esi]
0041609F    8B4E 04         mov     ecx, dword ptr [esi+4]
004160A2    802B 01         sub     byte ptr [ebx], 1
004160A5    43              inc     ebx
004160A6  ^ E2 FA           loopd   short 004160A2
004160A8    83C6 08         add     esi, 8
004160AB  ^ EB E5           jmp     short 00416092
004160AD    8B85 59364000   mov     eax, dword ptr [ebp+403659]
004160B3    8B9D 5D364000   mov     ebx, dword ptr [ebp+40365D]
004160B9    03C3            add     eax, ebx
004160BB    5B              pop     ebx
004160BC    59              pop     ecx
004160BD    5A              pop     edx
004160BE    5E              pop     esi
004160BF    5F              pop     edi
004160C0    5D              pop     ebp
004160C1    FFE0            jmp     eax                                       ; eax = 0x00414319

EAX = 0x00414319,这个就是壳代码的入口,OD载入Crackme后,就是停留在这个地址。
我们再次执行这里的三段代码,最后的跳转如下:
[Asm] 纯文本查看 复制代码
00414376    8B9A 09274000   mov     ebx, dword ptr [edx+402709]
0041437C    898A 09274000   mov     dword ptr [edx+402709], ecx
00414382    FFE3            jmp     ebx                             ; ebx = 0x00414000

这次不是跳转到 0x00419000了,而是跳转到 0x00414000,然后到了 0x00414000一看,与前面  0x00419000代码也是一样的,用同样的方法执行即可(包括修改EIP)。
0x00414000执行完后,同样跳转到另一个相同代码的过程  0x00413000,按同样操作方式完成  0x00413000代码节的执行,来到最后的跳转处:
[Asm] 纯文本查看 复制代码
004130AD    8B85 59364000   mov     eax, dword ptr [ebp+403659]
004130B3    8B9D 5D364000   mov     ebx, dword ptr [ebp+40365D]
004130B9    03C3            add     eax, ebx
004130BB    5B              pop     ebx
004130BC    59              pop     ecx
004130BD    5A              pop     edx
004130BE    5E              pop     esi
004130BF    5F              pop     edi
004130C0    5D              pop     ebp
004130C1    FFE0            jmp     eax                                        ; eax= 0x004011CB

可以看到,这时 EAX = 0x004011CB,这个地址就是 CrackMe 的 OEP 了。
按F8来到 OEP,下一步就是通过 LordPE 进行 Dump操作了,如下图:
24.png
然后再进行导入表的修正,用 Import REC 完成:
25.png
先选择Crackme进程后,再修改 OEP 为 0x000011CB,然后点击”IAT AutoSearch“,再然后上点击”Get Imports“,看到有导入信息:
26.png

但只有一个  crtdll.dll 的导入信息,没有 Kernal32.dll,User32.dll 等系统DLL的导入信息,这肯定不对。我们前面点击”IAT AutoSearch"时,会弹出一个消息框,説可以按提示修改 RVA 及其 Size 的参数(如果不记得了,可再次点击“IAT AutoSearch”),我们将 RAV 改成  0x00005000, Size 修改成 0x0000047A,然后再次点击“Get Imports",这次出来一大片:
33.png
有一些是无效导入,需要删除,点击右边的”Show Invalid"按钮后,显示如下,无效的导入会选中(蓝色),如下图所示:
34.png
然后在这些选中的项目上按右键,选择“Delete thunk(s)"菜单项,删除这些无用的导入项,如下图所示:
35.png
删完无效的导入项后,有效的导入表如下图所示:
36.png
然后,我们就可以点击”Fix Dump"对 LordPE 程序 Dump 出来的 CrackMe 进行修正了,如下图:
37.png
选中“Dumped.exe"进行修复即可。
脱壳工作到此就完成了。
我们运行脱壳后的 Crackme,显示界面如下:
001.bmp
可以看到”Request"按钮是禁用状态,需要 patch 成可用状态才算完成 Crackme 的破解
这是一个基于 Dialog 的应用程序,我们通过 OEP 向下执行,很快可以找到如下代码:
[Asm] 纯文本查看 复制代码
0040129D  |.  6A 00         push    0                                          ; /lParam = NULL
0040129F  |.  68 B8124000   push    004012B8                                   ; |DlgProc = DING_BOY.004012B8
004012A4  |.  6A 00         push    0                                          ; |hOwner = NULL
004012A6  |.  6A 64         push    64                                         ; |pTemplate = 64
004012A8  |.  57            push    edi                                        ; |hInst
004012A9  |.  E8 0A060000   call    <jmp.&USER32.DialogBoxParamA>              ; \DialogBoxParamA

其中 DlgProc 的地址为:0x004012B8,其代码如下:
[Asm] 纯文本查看 复制代码
004012B8  /.  55            push    ebp
004012B9  |.  89E5          mov     ebp, esp
004012BB  |.  51            push    ecx                                        ; 局部变量 isPatched, Win9x 下,ecx == eax == 0;
004012BC  |.  50            push    eax                                        ; 局部变量 hInstance, WinNt 下,ecx == eax == DlgProc,需要破解
004012BD  |.  C745 FC 00000>mov     dword ptr [ebp-4], 0                       ; win9x下破解: mov dword ptr [ebp-4], 0x01
004012C4  |.  8B45 0C       mov     eax, dword ptr [ebp+C]
004012C7  |.  83F8 10       cmp     eax, 10                                    ;  WM_CLOSE 消息, Switch (cases 10..111)
004012CA  |.  0F84 E1000000 je      004013B1
004012D0  |.  0F8C EA000000 jl      004013C0
004012D6  |.  3D 10010000   cmp     eax, 110                                   ;  WM_INITDIALOG 消息
004012DB  |.  74 0C         je      short 004012E9
004012DD  |.  3D 11010000   cmp     eax, 111                                   ;  WM_COMMAND 消息
004012E2  |.  74 39         je      short 0040131D
004012E4  |.  E9 D7000000   jmp     004013C0
; 以下是初始化主对话框界面(WM_INITDIALOG)
004012E9  |>  837D FC 00    cmp     dword ptr [ebp-4], 0                       ; 变量[ebp-4]的初始值需要patch为非0值
004012ED  |.  75 15         jnz     short 00401304
004012EF  |.  68 2E040000   push    42E                                        ; /ControlID = 42E (1070.)
004012F4  |.  FF75 08       push    dword ptr [ebp+8]                          ; |hWnd
004012F7  |.  E8 EC050000   call    <jmp.&USER32.GetDlgItem>                   ; \GetDlgItem
004012FC  |.  6A 00         push    0                                          ; /Enable = FALSE,破解这里,push 0 改成 push 1
004012FE  |.  50            push    eax                                        ; |hWnd
004012FF  |.  E8 C0050000   call    <jmp.&USER32.EnableWindow>                 ; \EnableWindow
00401304  |>  FF75 14       push    dword ptr [ebp+14]
00401307  |.  FF75 10       push    dword ptr [ebp+10]
0040130A  |.  FF75 08       push    dword ptr [ebp+8]
0040130D  |.  E8 A2FFFFFF   call    004012B4
00401312  |.  83C4 0C       add     esp, 0C
00401315  |.  31C0          xor     eax, eax
00401317  |.  40            inc     eax
00401318  |.  E9 A5000000   jmp     004013C2
; 以下是 WM_COMMAND 消息处理
0040131D  |>  0FB745 10     movzx   eax, word ptr [ebp+10]                     ;  Case 111 (WM_COMMAND) of switch 004012C7
00401321  |.  3D 24040000   cmp     eax, 424                                   ; About 按钮事件,Switch (cases 1..42E)
00401326  |.  74 38         je      short 00401360
00401328  |.  7F 0F         jg      short 00401339
0040132A  |.  83F8 01       cmp     eax, 1                                     ; ID_OK
0040132D  |.  74 13         je      short 00401342
0040132F  |.  83F8 02       cmp     eax, 2                                     ; ID_CANCEL
00401332  |.  74 1D         je      short 00401351
00401334  |.  E9 87000000   jmp     004013C0
00401339  |>  3D 2E040000   cmp     eax, 42E                                   ; Request 按钮事件
0040133E  |.  74 39         je      short 00401379
00401340  |.  EB 7E         jmp     short 004013C0                             ; 转去默认消息处理过程
00401342  |>  6A 01         push    1                                          ; /Result = 1; Case 1 of switch 00401321
00401344  |.  FF75 08       push    dword ptr [ebp+8]                          ; |hWnd
00401347  |.  E8 84050000   call    <jmp.&USER32.EndDialog>                    ; \EndDialog
0040134C  |.  31C0          xor     eax, eax
0040134E  |.  40            inc     eax
0040134F  |.  EB 71         jmp     short 004013C2
00401351  |>  6A 00         push    0                                          ; /Result = 0; Case 2 of switch 00401321
00401353  |.  FF75 08       push    dword ptr [ebp+8]                          ; |hWnd
00401356  |.  E8 75050000   call    <jmp.&USER32.EndDialog>                    ; \EndDialog
0040135B  |.  31C0          xor     eax, eax
0040135D  |.  40            inc     eax
0040135E  |.  EB 62         jmp     short 004013C2
; 下面是"About"按钮事件处理过程
00401360  |>  6A 00         push    0                                          ; /lParam = NULL; Case 424 of switch 00401321
00401362  |.  68 C6134000   push    004013C6                                   ; |DlgProc = DING_BOY.004013C6
00401367  |.  FF75 08       push    dword ptr [ebp+8]                          ; |hOwner
0040136A  |.  6A 65         push    65                                         ; |pTemplate = 65
0040136C  |.  FF75 F8       push    dword ptr [ebp-8]                          ; |hInst
0040136F  |.  E8 44050000   call    <jmp.&USER32.DialogBoxParamA>              ; \DialogBoxParamA
00401374  |.  31C0          xor     eax, eax
00401376  |.  40            inc     eax
00401377  |.  EB 49         jmp     short 004013C2
00401379  |>  837D FC 00    cmp     dword ptr [ebp-4], 0                       ;  Case 42E of switch 00401321
0040137D  |.  75 1C         jnz     short 0040139B
; 下面是破解前request按钮事件处理过程
0040137F  |.  68 2E040000   push    42E                                        ; /ControlID = 42E (1070.)
00401384  |.  FF75 08       push    dword ptr [ebp+8]                          ; |hWnd
00401387  |.  E8 5C050000   call    <jmp.&USER32.GetDlgItem>                   ; \GetDlgItem
0040138C  |.  6A 00         push    0                                          ; /Enable = FALSE
0040138E  |.  50            push    eax                                        ; |hWnd
0040138F  |.  E8 30050000   call    <jmp.&USER32.EnableWindow>                 ; \EnableWindow
00401394  |.  B8 FFFFFFFF   mov     eax, -1
00401399  |.  EB 27         jmp     short 004013C2
; 下面是破解后request按钮事件处理过程
0040139B  |>  6A 00         push    0                                          ; /lParam = NULL
0040139D  |.  68 A1144000   push    004014A1                                   ; |DlgProc = DING_BOY.004014A1
004013A2  |.  FF75 08       push    dword ptr [ebp+8]                          ; |hOwner
004013A5  |.  6A 66         push    66                                         ; |pTemplate = 66
004013A7  |.  FF75 F8       push    dword ptr [ebp-8]                          ; |hInst
004013AA  |.  E8 09050000   call    <jmp.&USER32.DialogBoxParamA>              ; \DialogBoxParamA
004013AF  |.  EB 0F         jmp     short 004013C0
; 下面是 WM_CLOSE 消息处理过程
004013B1  |>  6A 00         push    0                                          ; /Result = 0; Case 10 (WM_CLOSE) of switch 004012C7
004013B3  |.  FF75 08       push    dword ptr [ebp+8]                          ; |hWnd
004013B6  |.  E8 15050000   call    <jmp.&USER32.EndDialog>                    ; \EndDialog
004013BB  |.  31C0          xor     eax, eax
004013BD  |.  40            inc     eax
004013BE  |.  EB 02         jmp     short 004013C2
; 默认消息处理过程,只有下面一条指令 
004013C0  |>  31C0          xor     eax, eax                                   ;  Default case of switch 00401321
; 函数退出,回收资源并返回
004013C2  |>  C9            leave004013C3  \.  C2 1000       retn    10

其中处理 WM_INITDIALOG 消息的代码如下:
[Asm] 纯文本查看 复制代码
; 以下是初始化主对话框界面(WM_INITDIALOG)
004012E9  |>  837D FC 00    cmp     dword ptr [ebp-4], 0                       ; 变量[ebp-4]的初始值需要patch为非0值
004012ED  |.  75 15         jnz     short 00401304
004012EF  |.  68 2E040000   push    42E                                        ; /ControlID = 42E (1070.)
004012F4  |.  FF75 08       push    dword ptr [ebp+8]                          ; |hWnd
004012F7  |.  E8 EC050000   call    <jmp.&USER32.GetDlgItem>                   ; \GetDlgItem
004012FC  |.  6A 00         push    0                                          ; /Enable = FALSE,破解这里,push 0 改成 push 1
004012FE  |.  50            push    eax                                        ; |hWnd
004012FF  |.  E8 C0050000   call    <jmp.&USER32.EnableWindow>                 ; \EnableWindow
00401304  |>  FF75 14       push    dword ptr [ebp+14]
00401307  |.  FF75 10       push    dword ptr [ebp+10]
0040130A  |.  FF75 08       push    dword ptr [ebp+8]
0040130D  |.  E8 A2FFFFFF   call    004012B4
00401312  |.  83C4 0C       add     esp, 0C
00401315  |.  31C0          xor     eax, eax
00401317  |.  40            inc     eax
00401318  |.  E9 A5000000   jmp     004013C2

可见当局部变量[ebp-4]为0时,就将“Request"按钮的状态设置为禁用状态了。
我们只要修改局部变量[ebp-4]的值就可以了,来到 DlgProc的最前面,可以看到如下指令:
[Asm] 纯文本查看 复制代码
004012BD  |.  C745 FC 00000>mov     dword ptr [ebp-4], 0                      ; 初始化为 0

在这里给局部变量[ebp-4]初始化为0了,我们将其改成1即可:
[Asm] 纯文本查看 复制代码
004012BD  |.  C745 FC 00000>mov     dword ptr [ebp-4], 1                       ; win9x下破解,初始值改成 0x01 即可。

这样修改后,再次运行Crackme,界面如下:
003.bmp
可见"Request"按钮已经是可用了。
按”About"可以看About信息如下:
004.bmp
按“Request"按钮,显示如下:
39.png
可以看到,破解成功了!
前面説过,脱壳后,该 Crackme 可以在 Windows 10 下运行,但会有一个 BUG 存在,需要修改,而这个 BUG 在 Windows 98 下不存在。
这个BUG就是 DlgProc中的局部变量的初始化问题,Crackme是通过两个寄存器来初始化其值的,指令如下所示:
[Asm] 纯文本查看 复制代码
004012BB  |.  51                    push    ecx                                        ; 局部变量 isPatched, Win9x 下,ecx == eax == 0;
004012BC  |.  50                    push    eax                                        ; 局部变量 hInstance, WinNt 下,ecx == eax == DlgProc,会引起BUG,需要修复
004012BD  |.  C745 FC 00000000      mov     dword ptr [ebp-4], 0


可以看到,CrackMe 通过 push ecx,  push eax 两条 push 指令,生成并初始化两个局部变量,第一个就是 [ebp-4],另一个是 [ebp-8],其中[ebp-4]就是前说的针对"Request"按钮的patch标志,为 0 表示没有 patch,非0则表示已经 patch 成功。
问题出的[ebp-8],通过两个按钮的事件处理过程可以看到,[ebp-8]是当作 DialogBoxParamA() 调用的第1 个参数(hInstance)用的,在 Windows 9x 下,Windows 回调 DlgProc 时,会将 eax, ecx 清 0,但是,在 Windows NT(至少win10是这样)系统 下,当windows回调 DlgProc 时,eax, ecx 不为 0,都是保存的 DlgProc 本身函数指针,导致调用 DialogBoxParamA() 时,传入到该函数的 hInstance 参数不正确,因此会导致 DialogBoxParamA() 调用失败,不会弹出对话框,具体表现就是,不管是按"About" ,还是按 "Request" ,程序都没有反应,不会弹出对话框。改正此BUG的方法也很简单,就是修改上面三行指令,将[ebp-4]和[ebp-8]初始化成正确的值。修改如下,正好用完这三行代码所占用的字节数:
[Asm] 纯文本查看 复制代码
; 以下是"Request"事件处理的破解,并修正在 WinNT 系列下调用 DialogBoxParamA() 失败的问题。
004012BB      6A 01                  push    1                                    ;  [ebp-04] == 1, "Request"按钮事件分支判断条件改成1
004012BD      66:83E0 00             and     ax, 0                                ;  ax 变为0, 在 NT 系列下将 eax 由 DlgProc 改造成 hInstance
004012C1      50                     push    eax                                  ;  [ebp-08],并初始化为 hInstance(WinNT下) 或者 0(Win9x下)
004012C2      8BC1                   mov     eax, ecx                             ;  恢复 eax,没什么作用,占用字节数



分析完成!!!
下面是脱壳后的文件信息:
info2.png

免费评分

参与人数 5威望 +1 吾爱币 +13 热心值 +4 收起 理由
Hmily + 1 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
AC12138 + 1 用心讨论,共获提升!
15276305588 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
pk8900 + 3 + 1 用心讨论,共获提升!厉害!
天空藍 + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

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

Joduska 发表于 2019-6-17 19:00
论坛大牛
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-15 18:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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