首页
社区
课程
招聘
[原创]再探 CrackMe001 By飘云[PYG](二)[原创]
发表于: 2008-1-19 00:31 5259

[原创]再探 CrackMe001 By飘云[PYG](二)[原创]

petnt 活跃值
12
2008-1-19 00:31
5259
【文章标题】: 再探 CrackMe001 By飘云[PYG](二)
【文章作者】: petnt
【作者邮箱】: petnt@sohu.com
【软件名称】: CrackMe001 By飘云[PYG]
【下载地址】: 自己搜索下载
【加壳方式】: FSG2.0
【保护方式】: 壳\注册码
【使用工具】: OD\UltraEdit-32\ImportREC.exe
【操作平台】: XpSp2
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
书接上回:

【正    文】

  第三幕 Kill Timer
  
  此CrackMe要求去除启动时的延时,就是干掉那个在数秒的计时器。bp SetTimer,断下后返回程序领空,我们来看看整个函数的样子。

00428770      55            push    ebp
00428771  |.  8BEC          mov     ebp, esp
00428773  |.  6A 00         push    0
00428775  |.  53            push    ebx
00428776  |.  56            push    esi
00428777  |.  8BD8          mov     ebx, eax
00428779  |.  33C0          xor     eax, eax
0042877B  |.  55            push    ebp
0042877C  |.  68 EF874200   push    004287EF
00428781  |.  64:FF30       push    dword ptr fs:[eax]
00428784  |.  64:8920       mov     dword ptr fs:[eax], esp
00428787  |.  6A 01         push    1                           ; /TimerID = 1
00428789  |.  8B43 34       mov     eax, dword ptr [ebx+34]     ; |
0042878C  |.  50            push    eax                         ; |hWnd
0042878D  |.  E8 EEDDFDFF   call    <jmp.&user32.KillTimer>     ; \KillTimer
00428792  |.  8B73 30       mov     esi, dword ptr [ebx+30]
00428795  |.  85F6          test    esi, esi
00428797  |.  74 40         je      short 004287D9
00428799  |.  807B 40 00    cmp     byte ptr [ebx+40], 0
0042879D  |.  74 3A         je      short 004287D9
0042879F  |.  66:837B 3A 00 cmp     word ptr [ebx+3A], 0
004287A4      74 33         je      short 004287D9
004287A6  |.  6A 00         push    0                           ; /Timerproc = NULL
004287A8  |.  56            push    esi                         ; |Timeout
004287A9      6A 01         push    1
004287AB  |.  8B43 34       mov     eax, dword ptr [ebx+34]     ; |
004287AE  |.  50            push    eax                         ; |hWnd
004287AF  |.  E8 24DFFDFF   call    <jmp.&user32.SetTimer>      ; \SetTimer
004287B4  |.  85C0          test    eax, eax
004287B6  |.  75 21         jnz     short 004287D9
004287B8  |.  8D55 FC       lea     edx, dword ptr [ebp-4]
004287BB  |.  A1 D0AA4600   mov     eax, dword ptr [46AAD0]
004287C0  |.  E8 E3D1FDFF   call    004059A8
004287C5  |.  8B4D FC       mov     ecx, dword ptr [ebp-4]
004287C8  |.  B2 01         mov     dl, 1
004287CA  |.  A1 F4154100   mov     eax, dword ptr [4115F4]
004287CF  |.  E8 7C2BFEFF   call    0040B350
004287D4  |.  E8 AFB0FDFF   call    00403888
004287D9  |>  33C0          xor     eax, eax
004287DB  |.  5A            pop     edx
004287DC  |.  59            pop     ecx
004287DD  |.  59            pop     ecx
004287DE  |.  64:8910       mov     dword ptr fs:[eax], edx
004287E1  |.  68 F6874200   push    004287F6
004287E6  |>  8D45 FC       lea     eax, dword ptr [ebp-4]
004287E9  |.  E8 5EB6FDFF   call    00403E4C
004287EE  \.  C3            retn
004287EF   .^ E9 5CB0FDFF   jmp     00403850
004287F4   .^ EB F0         jmp     short 004287E6
004287F6   .  5E            pop     esi
004287F7   .  5B            pop     ebx
004287F8   .  59            pop     ecx
004287F9   .  5D            pop     ebp
004287FA   .  C3            retn
  
  这个函数居然先进行了KillTimer,估计KillTimer时也是调用这个函数了。我没有仔细跟踪程序,估计就是不管3721先KillTimer,然后判断一些标志,还没有Set过Timer就SetTimer,设置一些标志等等一些事情,我们关心的是Timer的处理程序,Timerproc = NULL,MSDN上说这样就会定时向程序的消息队列送WM_TIMER(113h)消息。好了,我们试试运气,查找->常量 113,嘿嘿,居然被我们发现了,典型的消息处理函数。

004286FC   .  55            push    ebp
004286FD   .  8BEC          mov     ebp, esp
004286FF   .  51            push    ecx
00428700   .  53            push    ebx
00428701   .  56            push    esi
00428702   .  57            push    edi
00428703   .  8BDA          mov     ebx, edx
00428705   .  8945 FC       mov     dword ptr [ebp-4], eax
00428708   .  8B33          mov     esi, dword ptr [ebx]
0042870A   .  81FE 13010000 cmp     esi, 113                       ; 被我们发现的位置
00428710   .  75 3F         jnz     short 00428751                 ; 不是WM_TIMER就跳走,默认处理
00428712   .  33C0          xor     eax, eax
00428714   .  55            push    ebp
00428715   .  68 36874200   push    00428736
0042871A   .  64:FF30       push    dword ptr fs:[eax]
0042871D   .  64:8920       mov     dword ptr fs:[eax], esp
00428720   .  8B45 FC       mov     eax, dword ptr [ebp-4]
00428723   .  66:BE EFFF    mov     si, 0FFEF
00428727   .  E8 CCABFDFF   call    004032F8                       ; 做坏事的函数
0042872C   .  33C0          xor     eax, eax
0042872E   .  5A            pop     edx
0042872F   .  59            pop     ecx
00428730   .  59            pop     ecx
00428731   .  64:8910       mov     dword ptr fs:[eax], edx
00428734   .  EB 33         jmp     short 00428769
00428736   .^ E9 61AEFDFF   jmp     0040359C
0042873B   .  A1 90A94600   mov     eax, dword ptr [46A990]
00428740   .  8B00          mov     eax, dword ptr [eax]
00428742   .  8B55 FC       mov     edx, dword ptr [ebp-4]
00428745   .  E8 FEAE0200   call    00453648
0042874A   .  E8 B5B1FDFF   call    00403904
0042874F   .  EB 18         jmp     short 00428769
00428751   >  8B43 08       mov     eax, dword ptr [ebx+8]
00428754   .  50            push    eax                              ; /lParam
00428755   .  8B43 04       mov     eax, dword ptr [ebx+4]           ; |
00428758   .  50            push    eax                              ; |wParam
00428759   .  56            push    esi                              ; |Message
0042875A   .  8B45 FC       mov     eax, dword ptr [ebp-4]           ; |
0042875D   .  8B40 34       mov     eax, dword ptr [eax+34]          ; |
00428760   .  50            push    eax                              ; |hWnd
00428761   .  E8 82DBFDFF   call    <jmp.&user32.DefWindowProcA>     ; \DefWindowProcA
00428766   .  8943 0C       mov     dword ptr [ebx+C], eax
00428769   >  5F            pop     edi
0042876A   .  5E            pop     esi
0042876B   .  5B            pop     ebx
0042876C   .  59            pop     ecx
0042876D   .  5D            pop     ebp
0042876E   .  C3            retn

  我们跟进那个做坏事的Call,几次跋山涉水之后,发现做实事的是下面的函数。

0046868C  /.  55            push    ebp
0046868D  |.  8BEC          mov     ebp, esp
0046868F  |.  6A 00         push    0
00468691  |.  53            push    ebx
00468692  |.  8BD8          mov     ebx, eax
00468694  |.  33C0          xor     eax, eax
00468696  |.  55            push    ebp
00468697  |.  68 0C874600   push    0046870C
0046869C  |.  64:FF30       push    dword ptr fs:[eax]
0046869F  |.  64:8920       mov     dword ptr fs:[eax], esp
004686A2  |.  FF0D 14BC4600 dec     dword ptr [46BC14]              ; 公共计数-1
004686A8  |.  8D55 FC       lea     edx, dword ptr [ebp-4]
004686AB  |.  A1 14BC4600   mov     eax, dword ptr [46BC14]         
004686B0  |.  E8 AFF6F9FF   call    00407D64                        ; 计数转换成字符
004686B5  |.  8B55 FC       mov     edx, dword ptr [ebp-4]
004686B8  |.  8B83 00030000 mov     eax, dword ptr [ebx+300]
004686BE  |.  E8 19B7FCFF   call    00433DDC                        ; 设置按钮标题
004686C3  |.  833D 14BC4600>cmp     dword ptr [46BC14], 0           ; 计数结束了吗?
004686CA      75 2A         jnz     short 004686F6                  ; 没有就跳走返回
004686CC  |.  33D2          xor     edx, edx                        ; 计时结束继续向下
004686CE  |.  8B83 1C030000 mov     eax, dword ptr [ebx+31C]
004686D4  |.  E8 2301FCFF   call    004287FC                        ; 干掉计数器
004686D9  |.  B2 01         mov     dl, 1
004686DB  |.  8B83 00030000 mov     eax, dword ptr [ebx+300]
004686E1  |.  8B08          mov     ecx, dword ptr [eax]
004686E3  |.  FF51 64       call    dword ptr [ecx+64]              ; 恢复按钮可用
004686E6  |.  BA 20874600   mov     edx, 00468720
004686EB  |.  8B83 00030000 mov     eax, dword ptr [ebx+300]
004686F1  |.  E8 E6B6FCFF   call    00433DDC                        ; 设置按钮标题
004686F6  |>  33C0          xor     eax, eax
004686F8  |.  5A            pop     edx
004686F9  |.  59            pop     ecx
004686FA  |.  59            pop     ecx
004686FB  |.  64:8910       mov     dword ptr fs:[eax], edx
004686FE  |.  68 13874600   push    00468713
00468703  |>  8D45 FC       lea     eax, dword ptr [ebp-4]
00468706  |.  E8 41B7F9FF   call    00403E4C
0046870B  \.  C3            retn
0046870C   .^ E9 3FB1F9FF   jmp     00403850
00468711   .^ EB F0         jmp     short 00468703
00468713   .  5B            pop     ebx
00468714   .  59            pop     ecx
00468715   .  5D            pop     ebp
00468716   .  C3            retn

  分析到这里,我们整理下如何干掉计数器的思路。第一种方案,在调用KillTimer和SetTimer函数(上面第一个)里直接调用 恢复按钮可用和设置按钮标题的函数,替换掉Timer。第二种方案,更改关键跳转,让其只要执行到Timer的消息处理函数,就恢复按钮可用。我想第一种方案应该比较简单适用,但是小菜我对delphi的 先 mov eax,dword ptr [ebx+XXX]再进行Call的方式不太了解,所以不得不转而求其次,使用第二种方案。

  关键跳转通过分析很容易确定在:004686CA| 75 2A| jnz  short 004686F6。将其Nop 或改成je均可。保存,看看效果。

  可恶的是效果并不怎么样,我们还有1秒钟的延时。原因可以想到,就是触发WM_TIMER时间需要1秒钟。怎么办,同样两种方案,第一,将延时缩短为1毫秒,估计可能感觉不出延时。第二,可以在SetTimer之后,截获其他消息,让其处理,不再等到WM_TIMER触发。

  由于第一种方案有种治标不治本的感觉,所以选择第二种方案,我们先看看他可不可行。下断00428770 和004286FC,重新载入程序。

  我们首先断在了 00428770 处,F9,断在了004286FC处,观察堆栈,传来的是代号为1C的消息,F9,又一个1C,F9,113终于传来了。看来我们的第二种方案可行,动手。

0042870A      83FE 1C            cmp     esi, 1C                          ;  ******原来的113改为1C
0042870D      90                 nop
0042870E      90                 nop
0042870F      90                 nop
00428710   .  75 3F              jnz     short 00428751
00428712   .  33C0               xor     eax, eax
00428714   .  55                 push    ebp
00428715   .  68 36874200        push    00428736
0042871A   .  64:FF30            push    dword ptr fs:[eax]
0042871D   .  64:8920            mov     dword ptr fs:[eax], esp
00428720   .  8B45 FC            mov     eax, dword ptr [ebp-4]
00428723   .  66:BE EFFF         mov     si, 0FFEF
00428727   .  E8 CCABFDFF        call    004032F8                        
0042872C   .  33C0               xor     eax, eax
0042872E   .  5A                 pop     edx
0042872F   .  59                 pop     ecx
00428730   .  59                 pop     ecx
00428731   .  64:8910            mov     dword ptr fs:[eax], edx
00428734      EB 1B              jmp     short 00428751                   ; *******送回默认处理程序
00428736   .^ E9 61AEFDFF        jmp     0040359C
0042873B   .  A1 90A94600        mov     eax, dword ptr [46A990]
00428740   .  8B00               mov     eax, dword ptr [eax]
00428742   .  8B55 FC            mov     edx, dword ptr [ebp-4]
00428745   .  E8 FEAE0200        call    00453648
0042874A   .  E8 B5B1FDFF        call    00403904
0042874F   .  EB 18              jmp     short 00428769
00428751   >  8B43 08            mov     eax, dword ptr [ebx+8]
00428754   .  50                 push    eax                              ; /lParam
00428755   .  8B43 04            mov     eax, dword ptr [ebx+4]           ; |
00428758   .  50                 push    eax                              ; |wParam
00428759   .  56                 push    esi                              ; |Message
0042875A   .  8B45 FC            mov     eax, dword ptr [ebp-4]           ; |
0042875D   .  8B40 34            mov     eax, dword ptr [eax+34]          ; |
00428760   .  50                 push    eax                              ; |hWnd
00428761   .  E8 82DBFDFF        call    <jmp.&user32.DefWindowProcA>     ; \DefWindowProcA

  保存,再运行。嗯,效果不错。代号1C的消息为WM_ACTIVATEAPP,可怜我的菜机了,每次要多执行一段代码了。看来有得必有失啊。

  第四幕  Remove NAG

  其实,这个做起来也有点复杂,因为NAG虽然只是个简单的MessageBox显示,却不是通过简单调用API来实现的。好像是自己写了个全新的MessageBox(只是猜测),所以定位到这段数据花了我很长一段时间。用翻山越岭,跋山涉水来形容绝对不过分。我无法用代码和文字来描述完整的过程,只大概说一下思路:
  再按钮的消息处理函数中下断,然后一步一步的跟踪,看见Call就在Call的上下都下上断,防止跑飞,直至发现哪个Call产生这个MessageBox,再跟进跟踪。最终发现如下代码:

004501C5      8B45 FC            mov     eax, dword ptr [ebp-4]
004501C8  |.  33D2               xor     edx, edx
004501CA  |.  8990 4C020000      mov     dword ptr [eax+24C], edx
004501D0  |>  A1 DCBB4600        /mov     eax, dword ptr [46BBDC]
004501D5  |.  E8 DA310000        |call    004533B4
004501DA  |.  A1 DCBB4600        |mov     eax, dword ptr [46BBDC]
004501DF  |.  80B8 9C000000 00   |cmp     byte ptr [eax+9C], 0
004501E6  |.  74 0F              |je      short 004501F7
004501E8  |.  8B45 FC            |mov     eax, dword ptr [ebp-4]
004501EB  |.  C780 4C020000 0200>|mov     dword ptr [eax+24C], 2
004501F5  |.  EB 14              |jmp     short 0045020B
004501F7  |>  8B45 FC            |mov     eax, dword ptr [ebp-4]
004501FA  |.  83B8 4C020000 00   |cmp     dword ptr [eax+24C], 0
00450201  |.  74 08              |je      short 0045020B
00450203  |.  8B45 FC            |mov     eax, dword ptr [ebp-4]
00450206  |.  E8 1DFDFFFF        |call    0044FF28
0045020B  |>  8B45 FC            |mov     eax, dword ptr [ebp-4]
0045020E  |.  8B80 4C020000      |mov     eax, dword ptr [eax+24C]
00450214  |.  85C0               |test    eax, eax
00450216  |.^ 74 B8              \je      short 004501D0
00450218  |.  8945 F8            mov     dword ptr [ebp-8], eax
0045021B  |.  6A 00              push    0

  就是上面这段代码产生了MessageBox的效果,原理我没能力发现。只要跳过这段代码就能过NAG了。更改后如下:

004501C5     /EB 54              jmp     short 0045021B     ;直接跳过即可
004501C7     |90                 nop
004501C8  |. |33D2               xor     edx, edx

  至于程序的算法分析,busheler大侠已经分析得很透彻了,有兴趣地可以参考 http://bbs.pediy.com/showthread.php?threadid=20473 ,再此就不再分析了。

  时间过得真快,又过了0点了,就到这里吧,附件中有原程序和我修改过的程序,有时间我会跟帖附上注册机。

  另有分析不当之处,欢迎指出,谢谢。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年01月19日 00:17:10

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
密切跟踪楼主....
2008-1-19 23:47
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
3
虽然这里这几天比较冷清,但出于对这个板块的热爱,我还是要继续下去。。。。
我顶!
上传的附件:
2008-1-22 23:30
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
对于大虾的热情,唯有顶贴支持
2008-1-23 00:38
0
雪    币: 164
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
写得好,又学了不少东西,谢谢!
2008-1-24 11:19
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
太强大了 看雪论坛藏龙卧虎一点不错
2008-6-17 10:31
0
游客
登录 | 注册 方可回帖
返回
//