程序使用API SetUnhandledExceptionFilter 来注册一个未处理异常的函数1,如果进程没有被调试,那么会触发一个未处理异常,导致操作系统会将控制权交给函数1。如果进程被调试,则调试器会捕捉这个未处理异常。这样,我们的函数1也就不会被执行了。
这里在触发异常时,则是跳回原来的代码来执行,而不会退出程序。
UnhandledExceptionFilter 这个函数修改了EIP的值,在参数_EXCEPTION_POINTERS中,保存了触发异常的指令地址。所以根据这个指令地址修改寄存器中EIP的值就可以了。
如果写成控制台程序,则这个控制台程序要支持MFC。 我的IDLE是VS2012。
#include "stdafx.h"
#include "ConsoleApplication66.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CWinApp theApp;
using namespace std;
LONG WINAPI UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *pei);
bool UnhandledExceptionFilterApproach();
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(NULL);
if (hModule != NULL)
{
if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
{
_tprintf(_T("错误\n"));
nRetCode = 1;
}
else
{
if(!UnhandledExceptionFilterApproach())
{
puts("Hello World!");
printf("Press any key to continue");
getchar();
}
return 0;
}
}
else
{
_tprintf(_T("错误: GetModuleHandle 失败\n"));
nRetCode = 1;
}
return nRetCode;
}
LONG WINAPI UnhandledExceptionFilter(struct _EXCEPTION_POINTERS *BlackDragon)
{
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)BlackDragon->ContextRecord->Eax);
BlackDragon->ContextRecord->Eip += 2;
//继续执行进程剩余指令
return EXCEPTION_CONTINUE_EXECUTION;
}
bool UnhandledExceptionFilterApproach()//检测调试器
{
SetUnhandledExceptionFilter(UnhandledExceptionFilter);
__asm
{
//初始化
xor eax,eax
//触发异常
div eax
}
return false;
}