OllyDbg 使用教程 (十三)


 

参考

书:《加密与解密》

视频:小甲鱼 解密系列 视频

 

示例程序下载地址:http://pan.baidu.com/s/1hqBrJWo

 

方法一:内嵌补丁

 

加载程序,按F9运行,点击Enter Reg.Code 输入name,key等,先不要按OK ,到OD中 按Ctrl+N打开输入输出表,搜索KillTimer,设置断点。再点击注册窗口的OK,我们可以看见:

(也可以通搜索注册失败时弹出窗口中的“The registration code seems to be not valid” 来找到下面代码)

004DC19D   > \83F8 03       cmp     eax, 3
004DC1A0   .  75 1E         jnz     short 004DC1C0
004DC1A2   .  8B57 1C       mov     edx, dword ptr [edi+1C]          ;  Case 3 of switch 004DBDA4
004DC1A5   .  50            push    eax                              ; /TimerID
004DC1A6   .  52            push    edx                              ; |hWnd
004DC1A7   .  FF15 B4575E00 call    dword ptr [<&USER32.KillTimer>]  ; \KillTimer
004DC1AD   .  6A 00         push    0
004DC1AF   .  6A 00         push    0
004DC1B1   .  68 5C666400   push    0064665C                         ;  ASCII "The registration code seems to be not valid.",LF,"Please check if you didn't made any mistake."
004DC1B6   .  E8 919D0D00   call    005B5F4C
004DC1BB   .  E9 B7000000   jmp     004DC277
004DC1C0   >  83F8 04       cmp     eax, 4
004DC1C3   .  75 1E         jnz     short 004DC1E3
004DC1C5   .  50            push    eax                              ; /TimerID; Case 4 of switch 004DBDA4
004DC1C6   .  8B47 1C       mov     eax, dword ptr [edi+1C]          ; |
004DC1C9   .  50            push    eax                              ; |hWnd
004DC1CA   .  FF15 B4575E00 call    dword ptr [<&USER32.KillTimer>]  ; \KillTimer
004DC1D0   .  6A 00         push    0
004DC1D2   .  6A 00         push    0
004DC1D4   .  68 FC656400   push    006465FC                         ;  ASCII "Thank you for your support!",LF,"Please Exit the Software and start it again to validate the code."
004DC1D9   .  E8 6E9D0D00   call    005B5F4C
004DC1DE   .  E9 94000000   jmp     004DC277
004DC1E3   >  83F8 05       cmp     eax, 5
004DC1E6   .  75 15         jnz     short 004DC1FD
004DC1E8   .  8B4F 1C       mov     ecx, dword ptr [edi+1C]          ;  Case 5 of switch 004DBDA4
004DC1EB   .  50            push    eax                              ; /TimerID
004DC1EC   .  51            push    ecx                              ; |hWnd
004DC1ED   .  FF15 B4575E00 call    dword ptr [<&USER32.KillTimer>]  ; \KillTimer
004DC1F3   .  6A FF         push    -1                               ; /ExitCode = FFFFFFFF
004DC1F5   .  FF15 D0545E00 call    dword ptr [<&KERNEL32.ExitProces>; \ExitProcess
004DC1FB   .  EB 7A         jmp     short 004DC277
004DC1FD   >  83F8 06       cmp     eax, 6
004DC200   .  75 0D         jnz     short 004DC20F
004DC202   .  8B57 1C       mov     edx, dword ptr [edi+1C]          ;  Case 6 of switch 004DBDA4
004DC205   .  50            push    eax                              ; /TimerID
004DC206   .  52            push    edx                              ; |hWnd
004DC207   .  FF15 B4575E00 call    dword ptr [<&USER32.KillTimer>]  ; \KillTimer
004DC20D   .  EB 68         jmp     short 004DC277
004DC20F   >  83F8 0A       cmp     eax, 0A
004DC212   .  75 2D         jnz     short 004DC241
004DC214   .  50            push    eax                              ; /TimerID; Case A of switch 004DBDA4
004DC215   .  8B47 1C       mov     eax, dword ptr [edi+1C]          ; |
004DC218   .  50            push    eax                              ; |hWnd
004DC219   .  FF15 B4575E00 call    dword ptr [<&USER32.KillTimer>]  ; \KillTimer
004DC21F   .  8B17          mov     edx, dword ptr [edi]
004DC221   .  8BCF          mov     ecx, edi
004DC223   .  FF92 C0000000 call    dword ptr [edx+C0]
004DC229   .  85C0          test    eax, eax
004DC22B   .  74 4A         je      short 004DC277
004DC22D   .  8BC8          mov     ecx, eax
004DC22F   .  E8 772D0E00   call    005BEFAB
004DC234   .  85C0          test    eax, eax
004DC236   .  74 3F         je      short 004DC277
004DC238   .  8BC8          mov     ecx, eax
004DC23A   .  E8 F13EFEFF   call    004C0130
004DC23F   .  EB 36         jmp     short 004DC277
004DC241   >  83F8 0B       cmp     eax, 0B
004DC244   .  75 31         jnz     short 004DC277
004DC246   .  50            push    eax                              ; /TimerID; Case B of switch 004DBDA4
004DC247   .  8B47 1C       mov     eax, dword ptr [edi+1C]          ; |
004DC24A   .  50            push    eax                              ; |hWnd
004DC24B   .  FF15 B4575E00 call    dword ptr [<&USER32.KillTimer>]  ; \KillTimer
004DC251   .  E8 F3570E00   call    005C1A49
004DC256   .  8B40 04       mov     eax, dword ptr [eax+4]
004DC259   .  6A 00         push    0
004DC25B   .  68 B03C6400   push    00643CB0                         ;  ASCII "ResetToolbars"
004DC260   .  68 1CF16300   push    0063F11C                         ;  ASCII "Settings"
004DC265   .  8BC8          mov     ecx, eax
004DC267   .  E8 255C0E00   call    005C1E91
004DC26C   .  85C0          test    eax, eax
004DC26E   .  74 07         je      short 004DC277
004DC270   .  8BCF          mov     ecx, edi
004DC272   .  E8 99190000   call    004DDC10
004DC277   >  8BCF          mov     ecx, edi                         ;  Default case of switch 004DBDA4
004DC279   .  E8 51040D00   call    005AC6CF
004DC27E   .  8B4D F4       mov     ecx, dword ptr [ebp-C]
004DC281   .  5F            pop     edi
004DC282   .  5E            pop     esi
004DC283   .  5B            pop     ebx
004DC284   .  64:890D 00000>mov     dword ptr fs:[0], ecx
004DC28B   .  8BE5          mov     esp, ebp
004DC28D   .  5D            pop     ebp
004DC28E   .  C2 0400       retn    4

 

 

这些代码其实是 swith,现在代码eax为3,正要运行case 3 处的代码。观察每个case,可以发现 case 4 中的"Thank you for your support!",我们可以知道可能case 4 就是注册成功。我们就要想办法把swith 3 改成 swith 4。

 

我们先前看看,看看swith开始的代码

 

 

004DBD80   .  55            push    ebp
004DBD81   .  8BEC          mov     ebp, esp
004DBD83   .  6A FF         push    -1
004DBD85   .  68 17B85D00   push    005DB817                         ;  SE 处理程序安装
004DBD8A   .  64:A1 0000000>mov     eax, dword ptr fs:[0]
004DBD90   .  50            push    eax
004DBD91   .  64:8925 00000>mov     dword ptr fs:[0], esp
004DBD98   .  81EC 68010000 sub     esp, 168
004DBD9E   .  8B45 08       mov     eax, dword ptr [ebp+8]
004DBDA1   .  53            push    ebx
004DBDA2   .  56            push    esi
004DBDA3   .  57            push    edi
004DBDA4   .  83F8 01       cmp     eax, 1                           ;  Switch (cases 1..B)
004DBDA7   .  8BF9          mov     edi, ecx
004DBDA9   .  75 53         jnz     short 004DBDFE
004DBDAB   .  50            push    eax                              ; /TimerID; Case 1 of switch 004DBDA4
004DBDAC   .  8B47 1C       mov     eax, dword ptr [edi+1C]          ; |
004DBDAF   .  50            push    eax                              ; |hWnd
004DBDB0   .  FF15 B4575E00 call    dword ptr [<&USER32.KillTimer>]  ; \KillTimer
004DBDB6   .  E8 8E5C0E00   call    005C1A49

 

 

在004DBD80   下断点,删除前面KillTimer设置的断点,重新运行程序。多按几次F9(下断点处的地方,在程序界面产生前就调用了,所以多按几次F9),可以看到程序的界面,打开注册窗口,输入信息,点击OK,发现程序断在前面下断点的地方。

按F8单步运行, 可以发现 mov     eax, dword ptr [ebp+8] ,就是设置swith中eax的值。可以尝试把它改成mov eax ,4,但是我们可以发现原来的代码占用3个字节,改后的代码占用5个字节,后面的代码push    ebx, push    esi被覆盖了。

 

这时我们可以用内嵌补丁,先把mov     eax, dword ptr [ebp+8]改成jmp xxx到空白的代码处,再在空白的代码处写上要执行的代码,再跳回来。

 

这里我们可以把mov     eax, dword ptr [ebp+8]  改成jmp     005E47CC

再在005E47CC 写上下面的代码

 

005E47CB      00            db      00
005E47CC      B8 04000000   mov     eax, 4
005E47D1   .  53            push    ebx
005E47D2   .  56            push    esi
005E47D3   .^ E9 CB75EFFF   jmp     004DBDA3
005E47D8      00            db      00

 

 

复制到可执行程序,正常运行程序,可以发现,程序打开时一直弹出"Thank you for your support!"的窗口。调试改后的程序,我们可以发现原来程序一直在循环的执行swith,因为我们改成了switch 4,所以一直弹出"Thank you for your support!"的窗口。其实这个程序只是因为过期后前面有一个让我们输入key的nag窗口而不可以使用,我们只要让这个nag窗口不出现就可以了。我们可以让他switc  0B,0b既不会弹出“The registration code seems to be not valid” 窗口,也不会弹出"Thank you for your support!"的窗口。把  mov     eax, 4  改成  mov     eax, 0b 复制到可执行程序,再正常运行程序,可以发现程序可以正常运行。

 

 

方法二: 查看调用堆栈

 

此程序,因为产生了一个不可以跳过的nag窗口而不能使用,可以通过改变跳转,使程序不执行nag窗口的代码,来破解。

 

查找产生nag窗口的代码

 

重新加载程序,删掉前面设置的断点,按F9运行程序,看到nag窗口出现时,暂停程序,按 alt+K 查看堆栈调用,


图片1

点击最下面的 ”调用来自“。查看代码(点击 函数过程 是看函数的具体代码,点击 调用来自 是看call)

 

在这个call上下断点,重新运行程序,

图片2

 

可以发现真是这个call产生了nag窗口。

 

查找这段代码的开头(即找push ebp)

图片3

在push ebp 下断点重新运行程序,按F9运行,来到断点处。

按F8单步运行,变按边注意跳转,改变寄存器 ,使程序跳过call    005ABE4D。

 

可以发现只要使 jnz     short 004DBDE6 不跳转即可以实现跳过call    005ABE4D。