使用OllyDbg从零开始Cracking 第二十二章-OllyDbg反调试之UnhandledExceptionFilte...
第二十二章-OllyDbg反调试之UnhandledExceptionFilter,ZwQueryInformationProcess本章我们继续讨论反调试技术,我们将介绍反调试的另外两个小技巧,由于其中一个可以配合另一个来使用,所以我们两个一起介绍。本章我们使用上一章打过补丁的OllyDbg,也就是Nvp11,其中HideDebugger插件的配置如下:这里我们可以看到其中有一个Unhandled exception tricks的选项。接下来我们将学习Unhandled exception和另一个API函数ZwQueryInformationProcess检测调试器的工作原理。这里我们实验的对象叫做sphynx。如果你勾选上了HideDebugger插件的Unhandled exception tricks就可以正常运行起来了,但是使用插件之前我们还是来介绍一下它的实现原理。另外说一点,我们现在暂时不解决这个CrackMe,我们只是来看看该CrackMe是如何检测OD的。我们使用Nvp11(打过补丁的OllyDbg)加载该CrackMe,并且确保HideDebugger1.23插件的配置如第一幅图所示,接着将Debugging options-Exceptions选项中忽略的异常选项全部勾选上。运行起来。出现了CrackMe的主窗口,那么反调试体现在哪里呢?我们随便输入一个错误的序列号然后点击Check按钮。OD的左下方提示存在不可处理的异常,程序将关闭,我们继续运行。好了,我们不用OLLYDBG加载该CrackMe,它是不会关闭的,我们可以尝试输入不同的序列号,同样也不会关闭。好了,现在我们重新启动该CrackMe,看看其使用了哪些API函数。我们记得HideDebugger插件中有绕过该反调试的选项。我们设置该选项前先来学习一下如何手工绕过该反调试以及其原理。我们先来看看MSDN中关于SetUnhandledExceptionFilter的说明。该函数的唯一一个参数为异常处理函数指针。当程序发生异常是,且程序不处于调试模式(在VS或者其他调试器里运行)则首先调用该异常处理函数。因此,程序可以主动抛出一个异常来判断当前程序是否正在被调试,嘿嘿,这里我们并不需要使用ZwQueryInformationProcess。我们回到OD中,看到SetUnhandledExceptionFilter的调用处。正如你所看到的,只有一个参数,在程序执行过程中会抛出一个异常,如果当前程序没有被调试,那么就会调用该参数指定的异常处理函数,嘿嘿。这里该异常处理函数入口地址为401108,如果当前程序正在被调试的话,程序最终将终止运行。这是我们看到的该程序安装的其中一个异常处理函数,当有异常发生并且当前程序没有被调试的情况下,该异常处理函数将得以执行。好了,我们现在给SetUnhandledExceptionFilter,UnhandledExceptionFilter这两个函数设置断点。我们运行起来。断在了SetUnhandledExceptionFilter的入口处。我们看下堆栈的情况。正如你所看到的异常处理函数入口地址为401108,我们在命令栏中输入BP401108给该函数设置断点。我们运行起来,可以看到又断在SetUnhandledExceptionFilter的入口处,这个调用来至一个shellext.dll。我们对这处调用不感兴趣,异常处理函数前面已经设置过了,所以我们将对SetUnhandledExceptionFilter设置的断点删除掉。现在,我们随便输入一个错误的序列号,然后单击Check按钮,将会断在系统默认的异常处理函数入口处,因为程序有异常发生,并且当前程序正在被调试,所以,并不会首先调用程序之前设置的入口为401108的异常处理函数,而异常转交给调试器处理了,而调试器也无法处理该异常,所以最终调用系统默认的异常处理函数UnhandledExceptionFilter来处理,嘿嘿。这个API函数用来检测当前程序是否正在被调试,我们F8键单步看看该函数是如何实现检测调试器的。这里是我们今天要介绍的第二个反调试知识点,这个函数也可以单独用来检测调试器只需要把InfoClass设置为7。该函数通过将InfoClass参数设置为7,将可以获取到当前进程是否被调试的信息,该信息将保存在Buffer参数指向的缓冲区中。我们在数据窗口中定位到给缓冲区。我们可以看到该缓冲区的大小为4个字节,如果该缓冲区返回的是FFFFFFFF的话表示当前程序正在被调试,如果返回的是0的话,表示当前程序没有被调试,我们按F8键单步执行该函数,看看缓冲区中返回的是什么。我们可以看到返回值为FFFFFFFF,表示当前程序正在被调试,嘿嘿。可以看到现在判断该值是否为零,当前EDI为零。这里,JE条件跳转将不会发生。所以说该缓冲区中的值不为零的话,JE条件跳转将不会执行,程序最终将终止执行。我们可以看到OD下方的提示:调试器遇到不可处理的异常,程序将终止。现在重启OD,重复上面的步骤,直到调用完ZwQueryInformationProcess,然后我们来修改其返回的结果。我们来到这里我们在数据窗口中定位缓冲区。我们按F8键单步执行该API函数。缓冲区中返回的值跟上次一样,也是FFFFFFFF,我们将其修改为零。将其修改为零。接着还是进行比较。现在两者都为零。好了,现在JE条件跳转将实现。我们运行起来。断在了401108地址处,我们看到下面的关键部分。这里验证序列号是否正确以决定是否弹出正确的消息框。如果我们修改跳转,让其跳转不实现,将会弹出序列号正确的消息框。运行起来。好了,我们前面已经提到过,通过HideDebugger插件就可以绕过UnhandledExceptionTricks的反调试。我们勾选上UnhandledExceptionTricks选项以后,重启OD,可以看到运行的很正常。好了,那么不考虑UnhandledExceptionFilter,如何单独绕过ZwQueryInformationProcess这个函数的检测呢。当然,我们可以手工将其返回值修改为零,那么有自动绕过的插件吗?当然有,那就是HideOD这款插件。我们可以看到很多HideDebugger插件中没有的选项,我们和HideDebugger配合起来用,有一点很重要,就是别忘了勾选上Auto Run HideOD这个选项,这样我们就不必每次启动OllyDbg的时候配置该插件了。这里我们不勾选上UnhandledExceptionFilter,因为该选项最后也会绕过ZwQueryInformationProcess的反调试。我们现在只使用右边的单独绕过ZwQueryInformationProcess检测调试器的选项。好了,本章我们学会了如何绕过UnhandledExceptionFilter以及ZwQueryInformationProcess的反调试原理,我们配合使用HideOD和HideDebugger两款插件让OD更加健壮了,嘿嘿。本系列文章汉化版转载看雪论坛
感谢原作者:RicardoNarvaja(西班牙人) 原作者个人主页:http://www.ricardonarvaja.info/
感谢热心翻译的朋友:1~3章译者:BGCoder4~58章译者:安于此生
全集配套程序下载地址:链接: http://pan.baidu.com/s/1eQzTWfo 密码: vytv
[快捷回复]-感谢楼主热心分享! 这么厉害!必须给个红包鼓励下~ [吾爱汇编论坛52HB.COM]-感谢楼主热心分享!做的不错哦,楼主加油,期待更好的作品! 体验一下谢谢~
页:
[1]
2