首页
社区
课程
招聘
[求助]VC6release版本程序的HOOK函数无法实现对导入表中目标API的覆盖
发表于: 2013-4-29 08:02 4806

[求助]VC6release版本程序的HOOK函数无法实现对导入表中目标API的覆盖

2013-4-29 08:02
4806

        根据《windows程序设计》中书上的演示代码,可以实现通过对目标模块导入表的覆盖实现对某AIP的拦截,然后调用自定义的函数。
        在VC++6.0编译器上的debug版本程序能够实现正常覆盖,但是编译成release版本就会出现在hook函数中覆盖掉而且会正确hook掉目标API,但是返回到主函数后就无法实现拦截,而是再次还原成目标API的真实地址,也不会导致崩溃,hook函数返回后能正常调用真正的目标API,这样就没有实现hook函数的功能,为什么会有这种现象?代码是书上的没错,思路也没错,但还是有这种现象,换到XP下运行也有这种现象,不知道是什么问题以及如何解决,请大大们解答下,不胜感激!!!

[ ATTACH ]1.jpg[ /ATTACH ]
[ ATTACH ]2.jpg[ /ATTACH ]

#include <windows.h>
#include <stdio.h>

        // 挂钩指定模块hMod对MessageBoxA的调用
        BOOL SetHook(HMODULE hMod);
       // 定义MessageBoxA函数原型
       typedef int (WINAPI *PFNMESSAGEBOX)(HWND, LPCSTR, LPCSTR, UINT uType);
       // 保存MessageBoxA函数的真实地址
       PROC g_orgProc = (PROC)MessageBoxA;

void main()
{
       // 调用原API函数
       ::MessageBox(NULL, "原函数", "09HookDemo", 0);
       // 挂钩后再调用
       printf("覆盖前主函数MessageBoxA地址:\n%x\n",(PROC)MessageBoxA);
       SetHook(::GetModuleHandle(NULL));
       GetProcAddress(::GetModuleHandle(NULL),);
       ::MessageBox(NULL, "原函数", "09HookDemo", 0);
}

// 用于替换MessageBoxA的自定义函数
int WINAPI MyMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
       return ((PFNMESSAGEBOX)g_orgProc)(hWnd, "新函数", "09HookDemo", uType);
}

BOOL SetHook(HMODULE hMod)
{
       IMAGE_DOS_HEADER* pDosHeader = (IMAGE_DOS_HEADER*)hMod;
       IMAGE_OPTIONAL_HEADER * pOptHeader =
       (IMAGE_OPTIONAL_HEADER *)((BYTE*)hMod + pDosHeader->e_lfanew + 24);
        
       IMAGE_IMPORT_DESCRIPTOR* pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)
       ((BYTE*)hMod + pOptHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
       // 在导入表中查找user32.dll模块。因为MessageBoxA函数从user32.dll模块导出
       while(pImportDesc->FirstThunk)
       {
              char* pszDllName = (char*)((BYTE*)hMod + pImportDesc->Name);
             if(lstrcmpiA(pszDllName, "user32.dll") == 0)
            {
                break;
            }
            pImportDesc++;
        }

        if(pImportDesc->FirstThunk)
        {
            // 一个IMAGE_THUNK_DATA就是一个双字,它指定了一个导入函数
            // 调入地址表其实是IMAGE_THUNK_DATA结构的数组,也就是DWORD数组
            IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)((BYTE*)hMod + pImportDesc->FirstThunk);
        while(pThunk->u1.Function)
        {
            // lpAddr指向的内存保存了函数的地址
            DWORD* lpAddr = (DWORD*)&(pThunk->u1.Function);
            if(*lpAddr == (DWORD)g_orgProc)
            {
                printf("覆盖前自定义函数中保存MessageBoxA地址的地址与MessageBoxA的地址:\n%x %x\n",lpAddr,*lpAddr);

                DWORD dwOldProtect;
                MEMORY_BASIC_INFORMATION mbi;
                VirtualQuery(lpAddr,&mbi,sizeof(mbi));
                VirtualProtect(lpAddr,sizeof(DWORD),PAGE_EXECUTE_READWRITE,&dwOldProtect);

                // 修改IAT表项,使其指向我们自定义的函数,相当于“*lpAddr = (DWORD)MyMessageBoxA;”
DWORD* lpNewProc = (DWORD*)MyMessageBoxA;
                ::WriteProcessMemory(::GetCurrentProcess(),
                lpAddr, &lpNewProc, sizeof(DWORD), NULL);
                printf("覆盖后自定义函数中保存MessageBoxA地址的地址与MessageBoxA的地址:\n%x %x\n",lpAddr,*lpAddr);
                printf("覆盖后自定义函数中MessageBoxA地址:\n%x\n",(PROC)MessageBoxA);
                ::MessageBox(NULL, "原函数", "09HookDemo", 0);
                VirtualProtect(lpAddr,sizeof(DWORD),dwOldProtect,0);
                return TRUE;
            }

            pThunk++;
        }
    }
return TRUE;
}


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (2)
雪    币: 22
活跃值: (453)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
void main()
{
        // 调用原API函数
        ::MessageBox(NULL, "原函数", "09HookDemo", 0);
        // 挂钩后再调用
        printf("覆盖前主函数MessageBoxA地址:\n%x\n",(PROC)MessageBoxA);
       
       
        GetProcessHeap();GetCurrentProcess();GetCurrentThread();GetThreadLocale();
        GetProcessHeap();GetCurrentProcess();GetCurrentThread();GetThreadLocale();
        GetProcessHeap();GetCurrentProcess();GetCurrentThread();GetThreadLocale();
        GetProcessHeap();GetCurrentProcess();GetCurrentThread();GetThreadLocale();
       
        SetHook(::GetModuleHandle(NULL));
        //                        GetProcAddress(::GetModuleHandle(NULL),);
        ::MessageBox(NULL, "原函数", "09HookDemo", 0);
}

具体原因见这个帖子

http://bbs.pediy.com/showthread.php?t=97083
2013-4-29 09:10
0
雪    币: 92
活跃值: (100)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
哈哈,终于弄明白了,原来是导入项被放在了寄存器中,只有加入些垃圾代码才能让程序去读取导入表,这样果然成功了,看来我还得再好好看看它的反汇编代码啊,真心谢谢啦~
2013-4-29 09:43
0
游客
登录 | 注册 方可回帖
返回
//