欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  网络运营

时间限制,看我怎样突破你

程序员文章站 2022-03-16 16:32:39
 本篇文章源自《黑客防线》2007年10月刊转载请注明版权 文/图 Hokkien=================================== Okoker Brains...

 
本篇文章源自《黑客防线》2007年10月刊
转载请注明版权

文/图 Hokkien
===================================
Okoker Brains Practicer 1.9是一款益智游戏,小巧而精灵,很适合在工作之余小玩一把。但它是一款共享软件,不注册时有时间限制,只能玩2分钟。2分钟?呵呵,未免太不人道啦!那咱们今天就来玩玩它。
                        脱壳
查壳显示为“ASPack 2.12 -> Alexey Solodovnikov”,呵呵,这么简单的壳啊,那就用工具脱吧。试了一下,居然不行,脱不了啊。看来,这可能是个变形壳,那只有手脱啦。下面是手工脱壳过程。
用OD载入软件,停在下面的入口处。

00523001 >  60  PUSHAD
00523002  E8 03000000  CALL Brains_P.0052300A
00523007  - E9 EB045D45  JMP 45AF34F7

第一条语句是“PUSHAD”,在下面周围看看有没有“POPAD”,很遗憾,没有。那单步跟踪吧,呵呵,什么时候才到尽头啊。怎么办?不妨先看一下各个寄存器的值,如图1所示。
 
              图1
   根据堆栈平衡的原理,既然有“PUSHAD”,那么必然有类似“POPAD”的操作,从而达到堆栈平衡。先单步运行“PUSHAD”,此时观察堆栈情况,如图2所示,可以看到0012FFB0的值刚好是ESP的值,因而可以根据著名的“ESP定律”来脱了。我们下硬件访问断点,即在工具栏输入“hr 0012FFB0”,F9运行后,程序被断在下面的地方。
  
                                图2

005233A7 0BC9  OR ECX,ECX
005233A9 8985 A8030000  MOV DWORD PTR SS:[EBP+3A8],EAX
005233AF 61  POPAD
005233B0 75 08  JNZ SHORT Brains_P.005233BA
;断在这里
005233B2 B8 01000000  MOV EAX,1
005233B7 C2 0C00  RETN 0C

终于看到了熟悉的“POPAD”啦!再单步执行几步后,程序有个段间跳转,会来到下面的代码处。

004DCBEC 55  PUSH EBP
004DCBED 8BEC   MOV EBP,ESP
004DCBEF 83C4 F0  ADD ESP,-10
004DCBF2 53  PUSH EBX

这是很典型的函数入口,那就DUMP下来吧,呵呵,查壳显示“Borland Delphi 6.0 - 7.0”。看来脱壳圆满成功。下面开始分析。
                        算法分析
用OD载入,查找一下字符串,没发现任何有用的信息。那就请出伟大的DeDe吧,分析后我们定位到下面的关键点。

004C53E4  55  push  ebp
004C53E5  8BEC  mov  ebp, esp

为了让OD读取DeDe的分析结果,我们可以导出map文件,如图3所示。导出map文件后,用OD的插件LoadMap加载就可以啦。之后用OD动态调试,来到下面的关键位置。
  
                               图3

* Reference to: Controls.TControl.GetText(TControl):TCaption;|
004C5429 E85A36FAFF  call  00468A88
004C542E 8B45F8  mov   eax, [ebp-$08]
* Reference to: SysUtils.StrToInt(AnsiString):Integer;|
004C5431 E86632F4FF  call  0040869C
;把输入的注册码转换为整数
004C5436 B9B9060000  mov  ecx, $000006B9
004C543B 99  cdq
004C543C F7F9  idiv  ecx ;除6B9
004C543E 81FAE0020000  cmp  edx, $000002E0
;余数是否为2E0
004C5444 756A  jnz  004C54B0  ;不是出错
004C5446 A140F74D00  mov  eax, dword ptr [$004DF740]
004C544B 8B00  mov   eax, [eax]
004C544D 8B8058050000  mov  eax, [eax+$0558]
004C5453 33D2  xor  edx, edx

天啊,不会这么简单吧?输入注册码模6B9应该为2E0。那就根据这个随便找个注册码试试,好的,成功啦!如图4所示。
   
                                图4
试用一下,没有限制。那是不是成功啦?我们重启一下,天啊,又计时!如图5所示。看来没这么简单,软件把验证的不同部分分别放在不同地方验证。因为学习比较忙,没有时间跟踪它的验证代码。但我们可以爆破它,其实爆破也不是那么容易的,不信大家试试,呵呵。
  
                                            图5
                       突破时间限制
首先,想要找到时间限制关键点并不那么容易,我从中走了不少弯路,曾经考虑到API断点,包括注册表函数等等,但效果很不明显。其他弯路篇幅有限,就不一一列举啦。还是请出DeDe,如图6所示。

                                  
                                  图6
来到这里你会发现好多函数,而跟计时器有关的函数有13个之多,我们要从中找到关键点谈何容易啊!不过,到了这个份上,就一个一个下断吧。最终,我们可以定位到以下地方。
004DC09C >/. 55  PUSH EBP
; <-TForm1@Timer13Timer
004DC09D |. 8BEC  MOV EBP,ESP
004DC09F |. 6A 00  PUSH 0
004DC0A1 |. 53  PUSH EBX
004DC0A2 |. 56  PUSH ESI
004DC0A3 |. 8BD8  MOV EBX,EAX
004DC0A5 |. 33C0  XOR EAX,EAX
004DC0A7 |. 55  PUSH EBP
004DC0A8 |. 68 4DC14D00  PUSH <ss.->System.@HandleFinally;>
004DC0AD |. 64:FF30  PUSH DWORD PTR FS:[EAX]
004DC0B0 |. 64:8920  MOV DWORD PTR FS:[EAX],ESP
004DC0B3 |. 83BB 6C060000>CMP DWORD PTR DS:[EBX+66C],0
004DC0BA   7C 7B  JL SHORT ss.004DC137
;关键跳转
004DC0BC |. B2 01  MOV DL,1
004DC0BE >|. 8B83 58050000 MOV EAX,DWORD PTR DS:[EBX+558]
; *Label17:TLabel
004DC0C4 >|. E8 DFC8F8FF  CALL ss.004689A8
; ->Controls.TControl.SetVisible(TControl;Boolean);
004DC0C9 |. FF8B 6C060000 DEC DWORD PTR DS:[EBX+66C]
004DC0CF |. 8BB3 6C060000 MOV ESI,DWORD PTR DS:[EBX+66C]
004DC0D5 |. 83FE FF  CMP ESI,-1
004DC0D8 |. 75 12  JNZ SHORT ss.004DC0EC
004DC0DA |. BA 64C14D00  MOV EDX,ss.004DC164; 0
004DC0DF >|. 8B83 58050000 MOV EAX,DWORD PTR DS:[EBX+558]
; *Label17:Tlabel

面对这么多代码,我开始有点迷茫。但不要忘记,我们是在动态分析,经过多次的失败尝试后,可以定位到“004DC0BA 7C 7B JL SHORT ss.004DC137”这个关键语句,只要改“JL”为“JG”,时间限制就自然突破了!保存文件运行一下,呵呵,成功啦!
破解Delphi软件最好用DeDe配合OD使用,可以事半功倍!还有,脱壳的时候要注意一些基本概念的运用,比如“堆栈平衡”等,只有这样,破解的时候才能游刃有余