模仿《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);
}

解决方案 »

  1.   

    你没有权限替换系统进程的IAT的
      

  2.   

    我没有替换系统进程的IAT啊,我是在一个Win32的控制台程序中,使用了这个函数:
    int _tmain(int argc, _TCHAR* argv[])
    {
        ReplaceAllUnhandleExceptionHandler();
    int a = 0;
    int b = 1/a;
    }
      

  3.   


    你这里不是CreateToolhelp32Snapshot遍历进程吗。你是替换哪个进程失败了,还是所有进程都失败?
      

  4.   

    我使用的是
    HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,GetCurrentProcessId());遍历了Process下所有的Module
      

  5.   

    if(lstrcmpA(pImportModuleName,pModuleName)==0)这里lstrcmpA改成lstrcmpiA试试。
    你把日志打出来,看是module有问题还是函数列表有问题。
    还有,你要替换的进程有没有调用UnhandledExceptionFliter?如果没调用的话IAT里面是没有的
      

  6.   

    进程里没有主动调用UnhandledExceptionFliter,
    因为整个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);
    }
    }
    这一段被执行了两次,而且都应该是成功的修改了。但是运行的时候,还是没有进我的函数,不知道是为什么。
      

  7.   

    我是说被替换进程有没有调用UnhandledExceptionFliter,如果没有的话,是替换不了的。WIN32进程都有个默认顶级异常处理例程,但这个并不是用UnhandledExceptionFliter设置的。程序员用UnhandledExceptionFliter是来设置自己的顶级异常处理例程。
    你先看一下有没有进入到if(*Procthis == pOldProc)里面
      

  8.   

    我把你的代码在我这里试了一下,成功了的,进入了MyUnhandleExceptionHandler
    我就是照你这样写的:
    ReplaceAllUnhandleExceptionHandler();
    int a = 0;
    int b = 1/a;
    可以进入MyUnhandleExceptionHandler
      

  9.   


    我就是建立一个多文档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;
    }你的那些代码就原封不动的拷在这个函数上面。你可以先这样做试试,要没问题了再移到你的工程里面。
      

  10.   

      不行啊,我MFC项目建成多文档也好,对话框也好,都进不去。
       在VS里调试,VS就向我显示发生了一个未处理异常。
       在exe文件上双击的话,程序在窗体打开前就关闭了,根本没有看到messagebox,好有压力~
      

  11.   

        和OS和工具会有关系么? 我用的Win7+VS2008。
      

  12.   

    恩,我们公司的工作机全部是Win7的,就是测试机倒是有XP的,不过不知道是哪台了
      

  13.   

    找了台XP的测试机,把Debug版的exe文件挪了过去,还是不行啊,没有弹出我写的那个Messagebox
      

  14.   

      恩,在自己的电脑上试了下,将HOOK的目标改成了MessageBoxW,可以成功:
      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函数和一般函数的处理稍稍有点不同啊
      

  15.   

    又尝试了HOOK UnHandledExceptionFilter的底层函数,RtlUnHandledExceptionFliter,还是没起效果。
      

  16.   

    算了,这边的尝试先放放,去试试CrashRpt,能不能行