使用OllyDbg从零开始Cracking 第四十二章-ACProtect V1.09脱壳(寻找OEP,绕过硬件断...
第四十二章-ACProtect V1.09脱壳(寻找OEP,绕过硬件断点检测,修复Stolen code)本章开始,我们将讨论更加复杂的壳-ACProtect 1.09。我们一步步的来剖析这个壳的保护机制。该例子的名称为UnPackMe_ACProtect 1.09g.f。配合好反反调试插件,用OD加载之。我们直接运行起来,看看会发生什么。.这里我用的是Parcheado_4(西班牙语:Patched_4)这个OD,接着按照下图来配置HideOD 0.12反反调试插件,这样就可以正常运行了,该壳会使用Process32Next这类API函数来检测OD进程,反反调试插件可以绕过。下面我们来定位OEP。前面章节我们介绍了很多定位OEP的方法,比如说可以使用OD自带的跟踪功能就能定位到OEP,打开主菜单项Debugging options-SFX,选择Trace real entry blockwise(inaccurate)。接着重启OD,不一会儿断在了这里。现在的问题是这里是否是真正的OEP,或者说是不是存在stolen bytes。我们来看一看堆栈的情况。现在我们不勾选自动定位OEP的选项,重启OD。我们可以看到比开始的时候多了两个值。一般来说,这样情况存在stolen bytes。下面我们来定位stolen bytes。在定位stolen bytes之前,先来给大家介绍一下如何利用HBP.txt这个脚本来设置硬件断点,这个方法我们在脚本的编写那一章中介绍过了,大家应该还记得吧!通过脚本来设置硬件断点可以绕过很多壳对于硬件断点的检测。假如我们现在想通过设置硬件断点让程序断在OEP处的话,我们会发现程序并不会断下来,我们可以通过HPB.txt这个脚本来解决这个问题。下面就来给大家详细讲解硬件断点为什么不触发的原因,以及HPB.txt脚本如何解决这个问题的。下面我们再次重启OD,分别给KiUserExceptionDispatcher以及其内部调用的ZwContinue处设置断点。下面我们来给OEP处设置一个硬件执行断点。此时在壳的入口处,单击鼠标右键选择-Goto-Expression,输入地址4271B5。在这里我们设置一个硬件执行断点。单击鼠标右键选择Breakpoint-Hardware,on execution,接着运行起来。断了下来,我们来看下堆栈情况。此时断在了KiUserExceptionDispatcher的入口处,堆栈中偏移4的单元中存放了context的指针,下面我们到数据窗口中定位该context。这里我暂时不解释CONTEXT结构体各个字段的含义,等后面用到的时候再解释。在寄存器窗口中,单击鼠标右键选择View debug registers,切换到调试寄存器显示模式,如果没有该选项的话,说明当前已经是调试寄存器显示模式了。这些就是调试寄存器组,Dr0 ~ Dr7。Dr0,Dr1,Dr2,Dr3是用于设置硬件断点的,由于只有4个硬件断点寄存器,所以同时最多只能设置4个硬件断点。产生的异常是STATUS_SINGLE_STEP(单步异常)。Dr4,Dr5是系统保留的。Dr7是一些控制位,用于控制断点的方式,Dr6是用于显示哪个硬件调试寄存器引发的断点,如果是Dr0 ~ Dr3的话,相应位会被置1。即如果是Dr0引发的断点,则Dr6的第0位被置1,如果是Dr1引发的断点,则Dr6的第1位被置1,依次类推。因为硬件断点同时只会触发一个,所以Dr6的低4位最多只有一位被置1,所以在进入单步后,我们可以通过检测Dr6的低4位是否有1的位,就可以判断该单步是否是因为硬件断点被断下的。如果是硬件断点被断下的,进而可以通过Dr6的哪一位为1来判断是由Dr0~Dr3中的哪个断点断下的。调试控制寄存器Dr7比较重要,其32位结构如下:位0 L0和位1 G0:用于控制Dr0是全局断点还是局部断点,如果G0为1则是全局断点,如果L0为1则为局部断点。G0,L0 ~G3,L3分别用于控制Dr1~Dr3。 LE和GE:P6 family和之后的IA32处理器都不支持这两位。当设置时,使得处理器会检测触发数据断点的精确的指令。当其中一个被设置的时候,处理器会放慢执行速度,这样当命令执行的时候可以通知这些数据断点。建议在设置数据断点时需要设置其中一个。切换任务时LE会被清除而GE不会被清除。为了兼容性,Intel建议使用精确断点时把LE和GE都设置为1。 LEN0到LEN3:指定调试地址寄存器DR0到DR3对应断点所下断的长度。如果R/Wx位为0(表示执行断点),则LENx位也必须为0(表示1字节),否则会产生不确定的行为。LEN0到LEN3其可能的取值如下:(1)00 1字节(2)01 2字节
(3)10 保留
(4)11 4字节 R/W0到R/W3:指定各个断点的触发条件。它们对应于DR0到DR3中的地址以及DR6中的4个断点条件标志。可能的取值如下:
(1) 00 只执行
(2) 01 写入数据断点
(3) 10 I/O端口断点(只用于pentium+,需设置CR4的DE位,DE是CR4的第3位 )
(4) 11 读或写数据断点 GD位:用于保护DRx,如果GD位为1,则对Drx的任何访问都会导致进入1号调试陷阱(int 1)。即IDT的对应入口,这样可以保证调试器在必要的时候完全控制Drx。此时Dr0为4271B5,表示4271B5地址处被设置了硬件断点。现在我们来看看CONTEXT结构。这里我们可以看到context结构中Dr0~Dr3寄存器的内容。黄色标注的4271B5是我们设置了硬件断点的地址。其他三个粉红色标注的位零,因为我们只设置了一个硬件断点,所以它们是空的。当异常处理完毕以后,context中的值将被清零,我们一起来看一看,直接运行起来,断在第二个断点处。我们可以看到经过了异常处理以后,Dr0被清零了,我们可以编写脚本来恢复它。这里我们有两种方案,第一种方案:在断在KiUserExceptionDispatcher入口处时将context中调试寄存器的值保存一份。当断在下面的ZwContinue的调用处时将调试寄存器的值恢复。第二种方案:在context中定位到程序的返回地址,在返回地址处设置一个断点,当断在返回地址处时恢复硬件断点,相当于重新设置了一次硬件断点。好,这里我们采用第二种方案,但是现在的问题是程序的返回地址保存在context结构中的哪里呢?Context的起始地址偏移0B8地址处就保存了返回地址,我的机器上是:12FC8C + 0B8 = 12FD4412FD44内存单元中就保存着程序的返回地址,在脚本中可以对返回地址设置一个断点,当程序返回以后,再次设置硬件断点,我们来看一看脚本是怎么写的。 脚本的开头我们定义一个变量var命令是用来声明一个变量,这个变量RetAddr我们用来保存由异常返回的地址。这就是恢复硬件断点的一部分,首先将ESP寄存器的值保存到RetAddr变量中。此时RetAddr保存ESP寄存器的值,接着再取其内容,也就是context结构的首地址,我这里context的首地址为12FC8C,接着加上0B8等于12FD44,12FD44内存单元中就保存了异常的返回地址。最后再次取内容就得到了异常的返回地址,接着就对该返回地址设置断点。然后运行起来。这里是判断断下来的地址是KiUserExceptionDispatcher的入口处,还是ZwContinue的调用处,还是异常的返回地址。这里是删除异常返回地址处的断点,接着重新设置硬件断点。好了,下面我们来看看脚本执行的效果,重启程序。我们通过这个脚本来断到OEP处。我们现在来运行脚本,不要忘了设置KiUserExceptionDispatcher入口处以及下面ZwContinue调用处的断点,还要记得将忽略异常的选项都勾选上。这里我们可以看到断在了硬件断点处,我们选择NO,不继续。好,我们现在断在了OEP处。有些壳会通过一些方法来清除硬件断点,现在我们就可以很完美的给stolen bytes设置硬件断点了。首先我们来看看有没有异常,我们从最后一次异常处开始跟踪。在日志窗口中我们可以看到在到达OEP之前产生了一次异常,我们可以看到类型是Access violation when reading。我们来清空掉相应的异常忽略选项。禁用掉脚本中用到的断点。现在我们重新启动,然后运行起来。断在了最后一次异常处,给当前区段设置内存访问断点,让其断在异常处理程序中。按Shift + F9忽略异常运行起来。按F7键单步几下到达异常处理函数的RET处。接着运行起来,我们返回到了这里下面我们可以对OEP处设置断点,因为此时壳已经解密完毕了。现在我们就可以从471090处开始跟踪了,不一会儿跟踪完毕了,我们现在到达了OEP处。我们来看一看跟踪的指令列表。这里跟踪的指令的最后几行,这里我们可以搜索PUSH EBP,一般是从上往下搜索,但这里前面位于系统DLL中的PUSH EBP过多,所以这里我们从下往下搜索。(PS:由于这里记录的TXT又几十M,所以这里我使用的是EditPlus)这里我们可以看到stolen bytes,接着是NOP指令,然后使用PUSHAD指令保存寄存器环境,那么在跳往假的OEP之前会使用POPAD指令来恢复寄存器环境的。这里我们可以看到stolen bytes的数值部分是被保存在栈中的。EBP寄存器可能在其间会赋予一个随机值,但是随后通过MOV EBP,ESP指令又可以修正。我们可以看到记录文件中显示EBP的值为12FFC0,该值刚好与假OEP处的EBP的值相等。说明我们定位到的stolen bytes是正确的。好了,这里我们就找到了stolen bytes,关于前面的通过脚本设置硬件断点的技巧我们将在下一章节中使用。 本系列文章汉化版转载看雪论坛
感谢原作者:RicardoNarvaja(西班牙人) 原作者个人主页:http://www.ricardonarvaja.info/
感谢热心翻译的朋友:1~3章译者:BGCoder4~58章译者:安于此生
全集配套程序下载地址:链接: http://pan.baidu.com/s/1eQzTWfo 密码: vytv
大佬大佬,连接挂了 学习中 我也需要,感谢分享 恒大,可以补下链接吗这个 [吾爱汇编论坛52HB.COM]-支持一下,希望楼主做的更好,加油!感谢楼主分享,支持一下! 感谢分享,正好需要,,,, 收藏,留个脚印,下次好找 这个很实用,谢谢分享。 大佬太强了
页:
[1]
2