把断点 断在 SetUnhandledExceptionFilter 的异常处理函数上 !!!
一、问题来源
在做题的时候发现了一个奇怪的异常处理函数:
SetUnhandledExceptionFilter
微软给出的定义是这样的:
使应用程序能够取代进程的每个线程的顶级异常处理程序。
调用此函数后,如果在未调试的进程中发生异常,并且异常会将其设置为未处理的异常筛选器,
该筛选器将调用 lpTopLevelExceptionFilter 参数指定的异常筛选器函数
也就是说,当我们使用OD或者IDA甚至VS进行调试的时候,我们是断不到异常处理函数中的,就算指定让程序接管异常也并不可以,程序会直接奔溃,停止运行(在没有其他异常接管处理程序的情况下)

那我们该如何处理呢
这里,我找到了两个方法,让我一一细细道来
二、利用Frida Hook NtQueryInformationProcess 函数
Hook NtQueryInformationProcess 函数的原因,下面会慢慢揭晓
经过查阅资料发现 UnhandledExceptionFilter 函数是检测调试器从而决定要不要走异常处理的关键函数,微软呀对他的定义如下:
如果正在调试进程,则应用程序定义的函数将未经处理的异常传递给调试器。 否则,它可以选择显示 应用程序错误消息 框,并导致执行异常处理程序。 只能从异常处理程序的筛选器表达式中调用此函数。
而该函数内部又调用了BasepIsDebugPortPresent 函数进行调试器附加的检查

BasepIsDebugPortPresent函数内部实际上是调用了 NtQueryInformationProcess 函数

那么,我们只需要Hook 掉NtQueryInformationProcess 函数,就可以欺骗 UnhandledExceptionFilter 函数的调试器检查了
实现脚本如下:
# 针对 SetUnhandledExceptionFilter 函数实现的反调试进行处理 import frida import sys # 0x41193B JsScrip_Hook_and_xch_arg = ''' var pUnhandledExceptionFilter = Module.findExportByName("ntdll.dll", 'NtQueryInformationProcess'); // KernelBase console.log(pUnhandledExceptionFilter); var flag = 0; Interceptor.attach(pUnhandledExceptionFilter, { onEnter: function (args) { if (args[1].toInt32() == 7){ flag = 1; } }, onLeave: function(retval){ if (flag == 1){ retval.replace(0xffffffff); console.log("Hook_Success_!!!"); } } }); ''' local = frida.get_local_device() session = local.attach("matrix.exe") script = session.create_script(JsScrip_Hook_and_xch_arg) script.load() sys.stdin.read()
或者
# 针对 SetUnhandledExceptionFilter 函数实现的反调试进行处理 # 这里采用条件断点的方式,多线程执行frida Hook函数(不然IDA会卡死) import frida import sys import threading # 0x41193B def Frida_Hook(): JsScrip_Hook_and_xch_arg = ''' var pUnhandledExceptionFilter = Module.findExportByName("ntdll.dll", 'NtQueryInformationProcess'); // KernelBase //console.log(pUnhandledExceptionFilter); var flag = 0; Interceptor.attach(pUnhandledExceptionFilter, { onEnter: function (args) { if (args[1].toInt32() == 7){ flag = 1; } }, onLeave: function(retval){ if (flag == 1){ retval.replace(0xffffffff); console.log("Hook_Success_!!!"); } } }); ''' local = frida.get_local_device() session = local.attach("matrix.exe") script = session.create_script(JsScrip_Hook_and_xch_arg) script.load() print("Hook_Success_!!!") sys.stdin.read() if __name__ == "__main__": thread = threading.Thread(target = Frida_Hook) thread.start() print("111")
经过测试,成功断到了异常处理函数上!!!

三、在异常处理函数上Patch 出循环后,用调试器attach
实现流程如下:

我们直接把这里的memset函数patch成循环:

在循环上下好断点
点击运行

程序就会被断到这里,之后使用IDA 进行Attach就可以了

程序成功断到了断点上!!
四、总结
对于这两种方法,我个人更倾向于用frida 处理,比较简单、方便,一个脚本可以应对无数次这种情况,而Patch循环这种方法则显的比较麻烦,我们需要在断到循环的位置后恢复被Patch的代码块,每次运行都需要恢复,比较麻烦。但都是可行的方法

浙公网安备 33010602011771号