模仿《windows核心编程》22章写了一下的代码来拦截UnhandledExceptionFliter函数,但是没成功,求教~
void ReplaceOneModuleIAT(HMODULE hthis,PSTR pModuleName, PROC pOldProc, PROC pNewProc)
{
ULONG ulSize;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
try
{
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hthis,true,IMAGE_DIRECTORY_ENTRY_IMPORT,&ulSize);
}
catch(...)
{
MessageBox(NULL,_T("I can not get import image"),_T("Error"),MB_OK);
return;
} if(pImportDesc == 0)
return; for(;pImportDesc->Name;pImportDesc ++)
{
PSTR pImportModuleName = (PSTR)((PBYTE)hthis + pImportDesc->Name);
if(lstrcmpA(pImportModuleName,pModuleName)==0)
{
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hthis + pImportDesc->FirstThunk);
//PIMAGE_THUNK_DATA pOriThunk = (PIMAGE_THUNK_DATA)((PBYTE)hthis + pImportDesc->OriginalFirstThunk); while(pThunk->u1.Function)
{
//PIMAGE_IMPORT_BY_NAME pMethodInfo = (PIMAGE_IMPORT_BY_NAME)((PBYTE)hthis + pOriThunk->u1.AddressOfData);
//PSTR strMethodName = (PSTR)pMethodInfo->Name;//这里用来查看函数名 PROC *Procthis =(PROC*) &pThunk->u1.Function; if(*Procthis == pOldProc)
{
DWORD dwSize;
if(!WriteProcessMemory(GetCurrentProcess(),Procthis,&pNewProc,sizeof(pNewProc),&dwSize) && ERROR_NOACCESS == GetLastError())
{
DWORD dwOldProctect;
if(VirtualProtect(Procthis,sizeof(pNewProc),PAGE_WRITECOPY,&dwOldProctect))
{
if(!WriteProcessMemory(GetCurrentProcess(),Procthis,&pNewProc,sizeof(pNewProc),&dwSize))
MessageBox(NULL,L"I can not write memory",L"Error",MB_OK);
VirtualProtect(Procthis,sizeof(pNewProc),dwOldProctect,&dwOldProctect);
}
}
}
pThunk ++;
//pOriThunk++;
}
}
}
}void ReplaceAllModuleIAT(PSTR pModuleName, PROC pOldProc, PROC pNewProc)
{
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId()); MODULEENTRY32 me = { sizeof(me) };
if(Module32FirstW(hSnapShot,&me))
{
do
{
ReplaceOneModuleIAT(me.hModule,pModuleName,pOldProc,pNewProc);
}while(Module32NextW(hSnapShot,&me));
}
}LONG WINAPI MyUnhandleExceptionHandler(PEXCEPTION_POINTERS pe)
{
OutputDebugStringA("I catch an exception! \r\n");
MessageBox(NULL,L"I catch an Exception!",L"Msg",MB_OK);
PROC sysExceptionFilter = (PROC) GetProcAddress(GetModuleHandle(L"Kernel32.dll"),"UnhandledExceptionFilter");
return ((ExceptionFliter)sysExceptionFilter)(pe);
}void ReplaceAllUnhandleExceptionHandler()
{
PROC MyProc = (PROC)MyUnhandleExceptionHandler;
PROC sysProc = GetProcAddress(GetModuleHandle(L"Kernel32.dll"),"UnhandledExceptionFilter");
//HANDLE hthis = GetModuleHandle(NULL);
// HANDLE hKernel32 = GetModuleHandle(L"Kernel32.dll");
//PROC MyMethod = GetProcAddress(GetModuleHandle(NULL),"MyUnhandleExceptionHandler"); PSTR pModuleName = "KERNEL32.dll";
ReplaceAllModuleIAT(pModuleName,sysProc,MyProc);
}
void ReplaceOneModuleIAT(HMODULE hthis,PSTR pModuleName, PROC pOldProc, PROC pNewProc)
{
ULONG ulSize;
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
try
{
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hthis,true,IMAGE_DIRECTORY_ENTRY_IMPORT,&ulSize);
}
catch(...)
{
MessageBox(NULL,_T("I can not get import image"),_T("Error"),MB_OK);
return;
} if(pImportDesc == 0)
return; for(;pImportDesc->Name;pImportDesc ++)
{
PSTR pImportModuleName = (PSTR)((PBYTE)hthis + pImportDesc->Name);
if(lstrcmpA(pImportModuleName,pModuleName)==0)
{
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hthis + pImportDesc->FirstThunk);
//PIMAGE_THUNK_DATA pOriThunk = (PIMAGE_THUNK_DATA)((PBYTE)hthis + pImportDesc->OriginalFirstThunk); while(pThunk->u1.Function)
{
//PIMAGE_IMPORT_BY_NAME pMethodInfo = (PIMAGE_IMPORT_BY_NAME)((PBYTE)hthis + pOriThunk->u1.AddressOfData);
//PSTR strMethodName = (PSTR)pMethodInfo->Name;//这里用来查看函数名 PROC *Procthis =(PROC*) &pThunk->u1.Function; if(*Procthis == pOldProc)
{
DWORD dwSize;
if(!WriteProcessMemory(GetCurrentProcess(),Procthis,&pNewProc,sizeof(pNewProc),&dwSize) && ERROR_NOACCESS == GetLastError())
{
DWORD dwOldProctect;
if(VirtualProtect(Procthis,sizeof(pNewProc),PAGE_WRITECOPY,&dwOldProctect))
{
if(!WriteProcessMemory(GetCurrentProcess(),Procthis,&pNewProc,sizeof(pNewProc),&dwSize))
MessageBox(NULL,L"I can not write memory",L"Error",MB_OK);
VirtualProtect(Procthis,sizeof(pNewProc),dwOldProctect,&dwOldProctect);
}
}
}
pThunk ++;
//pOriThunk++;
}
}
}
}void ReplaceAllModuleIAT(PSTR pModuleName, PROC pOldProc, PROC pNewProc)
{
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId()); MODULEENTRY32 me = { sizeof(me) };
if(Module32FirstW(hSnapShot,&me))
{
do
{
ReplaceOneModuleIAT(me.hModule,pModuleName,pOldProc,pNewProc);
}while(Module32NextW(hSnapShot,&me));
}
}LONG WINAPI MyUnhandleExceptionHandler(PEXCEPTION_POINTERS pe)
{
OutputDebugStringA("I catch an exception! \r\n");
MessageBox(NULL,L"I catch an Exception!",L"Msg",MB_OK);
PROC sysExceptionFilter = (PROC) GetProcAddress(GetModuleHandle(L"Kernel32.dll"),"UnhandledExceptionFilter");
return ((ExceptionFliter)sysExceptionFilter)(pe);
}void ReplaceAllUnhandleExceptionHandler()
{
PROC MyProc = (PROC)MyUnhandleExceptionHandler;
PROC sysProc = GetProcAddress(GetModuleHandle(L"Kernel32.dll"),"UnhandledExceptionFilter");
//HANDLE hthis = GetModuleHandle(NULL);
// HANDLE hKernel32 = GetModuleHandle(L"Kernel32.dll");
//PROC MyMethod = GetProcAddress(GetModuleHandle(NULL),"MyUnhandleExceptionHandler"); PSTR pModuleName = "KERNEL32.dll";
ReplaceAllModuleIAT(pModuleName,sysProc,MyProc);
}
int _tmain(int argc, _TCHAR* argv[])
{
ReplaceAllUnhandleExceptionHandler();
int a = 0;
int b = 1/a;
}
你这里不是CreateToolhelp32Snapshot遍历进程吗。你是替换哪个进程失败了,还是所有进程都失败?
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId());遍历了Process下所有的Module
你把日志打出来,看是module有问题还是函数列表有问题。
还有,你要替换的进程有没有调用UnhandledExceptionFliter?如果没调用的话IAT里面是没有的
因为整个Win32进程就那么三行代码:
code=C/C++]int _tmain(int argc, _TCHAR* argv[])
{
ReplaceAllUnhandleExceptionHandler();
int a = 0;
int b = 1/a;
}[[/code]
不过在发生异常的时候,进程还是会调用UnhandledExceptionFliter的吧?
我有断点跟踪过代码的执行过程
DWORD dwSize;
if(!WriteProcessMemory(GetCurrentProcess(),Procthis,&pNewProc,sizeof(pNewProc),&dwSize) && ERROR_NOACCESS == GetLastError())
{
DWORD dwOldProctect;
if(VirtualProtect(Procthis,sizeof(pNewProc),PAGE_WRITECOPY,&dwOldProctect))
{
if(!WriteProcessMemory(GetCurrentProcess(),Procthis,&pNewProc,sizeof(pNewProc),&dwSize))
MessageBox(NULL,L"I can not write memory",L"Error",MB_OK);
VirtualProtect(Procthis,sizeof(pNewProc),dwOldProctect,&dwOldProctect);
}
}
这一段被执行了两次,而且都应该是成功的修改了。但是运行的时候,还是没有进我的函数,不知道是为什么。
你先看一下有没有进入到if(*Procthis == pOldProc)里面
我就是照你这样写的:
ReplaceAllUnhandleExceptionHandler();
int a = 0;
int b = 1/a;
可以进入MyUnhandleExceptionHandler
我就是建立一个多文档MFC工程,然后在OnCreate里面加的。
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// TODO: Delete these three lines if you don't want the toolbar to be dockable
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
EnableDocking(CBRS_ALIGN_ANY);
DockControlBar(&m_wndToolBar); ReplaceAllUnhandleExceptionHandler(); int a = 0;
int b = 1/a; return 0;
}你的那些代码就原封不动的拷在这个函数上面。你可以先这样做试试,要没问题了再移到你的工程里面。
在VS里调试,VS就向我显示发生了一个未处理异常。
在exe文件上双击的话,程序在窗体打开前就关闭了,根本没有看到messagebox,好有压力~
void ReplaceAllUnhandleExceptionHandler()
{
//PROC MyProc = (PROC)MyUnhandleExceptionHandler;
//PROC sysProc = GetProcAddress(GetModuleHandle(L"Kernel32.dll"),"UnhandledExceptionFilter"); PROC MyProc = (PROC)Hook_MessageBoxW;
PROC sysProc = GetProcAddress(GetModuleHandle(L"User32.dll"),"MessageBoxW");
//HANDLE hthis = GetModuleHandle(NULL);
// HANDLE hKernel32 = GetModuleHandle(L"Kernel32.dll");
//PROC MyMethod = GetProcAddress(GetModuleHandle(NULL),"MyUnhandleExceptionHandler"); //PSTR pModuleName = "KERNEL32.dll";
PSTR pModuleName = "USER32.dll"; ReplaceAllModuleIAT(pModuleName,sysProc,MyProc);
}
看样子,Win7对UnHandledExceptionFilter函数和一般函数的处理稍稍有点不同啊