首页
社区
课程
招聘
[旧帖] [求助]求教:写了一个APIHook的程序,只能hook到自身进程,无法hook到其他进程,原因未查明 0.00雪花
发表于: 2009-12-18 08:03 1574

[旧帖] [求助]求教:写了一个APIHook的程序,只能hook到自身进程,无法hook到其他进程,原因未查明 0.00雪花

2009-12-18 08:03
1574
我写了一个程序,想实现对VirtualQueryEx函数的调用监控,想达到任何进程调用此函数就提示我的目的。目前只能监控到自身进程的调用,其他进程调用却监控不到。我用的修改IAT的方法,SetWindowsHookEx最后一个参数是NULL,按照全局钩子设置的,但不知道为什么不能hook到其他进程对函数VirtualQueryEx的调用,请各位大侠赐教,先谢过了。代码如下:

1、APIHook_DLL.cpp的代码(生成DLL文件):

#include "windows.h"
#include<ImageHlp.h>
#include<tlhelp32.h>
#include "APIHook_Dll.h"
#pragma comment(lib,"ImageHlp")//定义全局共享数据段
#pragma data_seg("Shared")
HINSTANCE hmodDll=NULL ;
HHOOK        hHook=NULL ;
#pragma data_seg()
#pragma comment(linker,"/Section:Shared,rws")

MODULEENTRY32                me={sizeof(MODULEENTRY32)};
PROCESSENTRY32                stProcess={sizeof(PROCESSENTRY32)};
//HANDLE                        TokenHandle;
HANDLE                                hToken;
TOKEN_PRIVILEGES        tp;

///////////////////////////////////// DllMain 函数 /////////////////////////////////////////
//dll的入口点
BOOL APIENTRY DllMain(HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
        switch(ul_reason_for_call)
        {
        case DLL_PROCESS_ATTACH:                                //调用SetWindowsHookEX时会运行此处
                break;
        case DLL_PROCESS_DETACH:                                //调用UnhookWindowsHookEx时会运行此处
                UnInstallHook();
                break;
        }
        hmodDll=hModule;
        return TRUE;
}

///////////////////////////////////// HookOneAPI 函数 /////////////////////////////////////////
//进行IAT转换的关键函数,其参数含义:
//pszCalleeModuleName:需要hook的模块名(dll名)
//pfnOriginApiAddress:要替换的自己API函数的地址(要钩的函数在所在dll中的地址)
//pfnDummyFuncAddress:需要hook的模块名的地址(新的替换函数的地址)
//hModCallerModule:我们要查找的模块名称,如果没有被赋值,将会被赋值为枚举的程序所有调用的模块
void WINAPI HookOneAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,PROC pfnDummyFuncAddress,HMODULE hModCallerModule)
{
        ULONG size;
        //获取指向PE文件中的Import中IMAGE_DIRECTORY_DESCRIPTOR数组的指针
        PIMAGE_IMPORT_DESCRIPTOR pImportDesc=(PIMAGE_IMPORT_DESCRIPTOR)
                ImageDirectoryEntryToData(hModCallerModule,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);
        if(pImportDesc==NULL)
                return;
        //查找记录,看看有没有我们想要的DLL
        for(;pImportDesc->Name;pImportDesc++)
    {
        LPSTR pszDllName=(LPSTR)((PBYTE)hModCallerModule+pImportDesc->Name);
        if(lstrcmpiA(pszDllName,pszCalleeModuleName)==0)
        break ;
    }
    if(pImportDesc->Name==NULL)
    {
        return ;
    }
        //寻找我们想要的函数
        PIMAGE_THUNK_DATA pThunk=(PIMAGE_THUNK_DATA)((PBYTE)hModCallerModule+pImportDesc->FirstThunk);
    for(;pThunk->u1.Function;pThunk++)
    {
                //ppfn记录了与IAT表相应的地址
                PROC*ppfn=(PROC*)&pThunk->u1.Function ;
        if(*ppfn==pfnOriginApiAddress)
        {
                        DWORD dwOldProtect;
            //修改内存包含属性
            VirtualProtect(ppfn, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
                  WriteProcessMemory(GetCurrentProcess(),ppfn,&(pfnDummyFuncAddress),sizeof(pfnDummyFuncAddress),NULL);
            return ;
        }
    }
}

BOOL WINAPI HookAllAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,PROC pfnDummyFuncAddress,HMODULE hModCallerModule)
{
    if(pszCalleeModuleName==NULL)
    {
        return FALSE ;
    }
    if(pfnOriginApiAddress==NULL)
    {
        return FALSE ;
    }
   
    //如果没传进来要挂钩的模块名称,枚举被挂钩进程的所有引用的模块并对这些模块进行传进来的相应函数名称的查找
    if(hModCallerModule==NULL)
        {
                MEMORY_BASIC_INFORMATION mInfo;
        HMODULE                                hModHookDLL=NULL;
                HANDLE                                hSnapshot;
                VirtualQuery(HookOneAPI,&mInfo,sizeof(mInfo));
                hModHookDLL=(HMODULE)mInfo.AllocationBase;
                if(hModHookDLL==NULL)
                        ::MessageBox(NULL," hModHookDLL fail !!!","   hModHookDLL  ",MB_OK);
                else
                        ::MessageBox(NULL," hModHookDLL successful !!!","   hModHookDLL  ",MB_OK);
               
                        hSnapshot=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);
                        BOOL bOk=Module32First(hSnapshot,&me);
                        while(bOk)
                        {
                                if(me.hModule!=hModHookDLL)
                                {
                                        hModCallerModule=me.hModule;        //赋值               
                                        //me.hModule:指向当前被挂钩进程的每一个模块
                                        HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,pfnDummyFuncAddress,hModCallerModule);
                                }
                                bOk=Module32Next(hSnapshot,&me);
                        }
                        CloseHandle(hSnapshot);
                return TRUE;
        }
        else
        {
                HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,pfnDummyFuncAddress,hModCallerModule);
                return TRUE;
        }
        return FALSE;
}

/////////////////////////////////// UnhookAllAPIHooks 函数 /////////////////////////////////////
//通过使pfnDummyFuncAddress与pfnOriginApiAddress互相调换的方法,取消对IAT的修改

BOOL WINAPI UnhookAllAPIHooks(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,PROC pfnDummyFuncAddress,HMODULE hModCallerModule)
{
        PROC temp;
        temp=pfnOriginApiAddress;
        pfnOriginApiAddress=pfnDummyFuncAddress;
        pfnDummyFuncAddress=temp;
        return HookAllAPI(pszCalleeModuleName,pfnOriginApiAddress,pfnDummyFuncAddress,hModCallerModule);
}

////////////////////////////////// GetMsgProc 函数 ////////////////////////////////////////
//钩子子程。与其它钩子子程不大相同,没做什么有意义的事情,继续调用下一个钩子子程,形成循环

LRESULT CALLBACK GetMsgProc(int code,WPARAM wParam,LPARAM lParam)
{
        return CallNextHookEx(hHook,code,wParam,lParam);
}

//////////////////////////////////// InstallHook 函数 /////////////////////////////////////
//安装或卸载钩子,BOOL IsHook参数是标志位
//对要钩哪个API函数进行初始化
//我们这里装的钩子类型是WH_GETMESSAGE
void __declspec(dllexport)WINAPI InstallHook(BOOL IsHook,DWORD dwThreadId)
{
        if(IsHook)
        {
                hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgProc,hmodDll,0);
                HookAllAPI("Kernel32.dll",GetProcAddress(GetModuleHandle("Kernel32.dll"),"VirtualQueryEx"),(PROC)&H_VirtualQueryEx,NULL);
        }
        else
        {
                UnInstallHook();
                UnhookAllAPIHooks("Kernel32.dll",GetProcAddress(GetModuleHandle("Kernel32.dll"),"VirtualQueryEx"),(PROC)&H_VirtualQueryEx,NULL);
        }
}

///////////////////////////////////// UnInstallHook 函数 ////////////////////////////////////
//卸载钩子

BOOL WINAPI UnInstallHook()
{
        UnhookWindowsHookEx(hHook);
        return TRUE;
}

///////////////////////////////////// H_VirtualQueryEx 函数 /////////////////////////////////////////
//我们的替换函数,可以在里面实现我们所要做的功能
//这里我做的是显示一个对话框,指明是替换了哪个函数
BOOL WINAPI H_VirtualQueryEx(HDC hdc,int nXStart,int nYStart,LPCWSTR lpString,int cbString)
{
        MessageBox(NULL,"有程序调用VirtualQueryEx函数","APIHook_Dll ---VirtualQueryEx",MB_OK);
        //返回原来的函数,以显示字符
        return TRUE;
}

2、调用程序test.cpp(做了个MFC程序,点击按钮调用,此处光写按钮下调用的代码)
//开始挂钩,这里我们挂的是自身这个APIHook_EXE这个程序
void CAdaexeDlg::OnButtonBegin()
{
        InstallHook(TRUE,0);
}

//取消挂钩
void CAdaexeDlg::OnButtonStop()
{
        InstallHook(FALSE,0);       
}
//调用VirtualQueryEx函数
void CAdaexeDlg::OnButton3()
{
         DWORD                                                        add=0,ret=1;
        HANDLE                                                        mpid=NULL;
        MEMORY_BASIC_INFORMATION                MemoryInfo;
        mpid=OpenProcess(PROCESS_ALL_ACCESS, FALSE,5608);
        while(ret)
        {
            if(VirtualQueryEx(mpid,(LPCVOID)add,&MemoryInfo,sizeof(MemoryInfo))!=sizeof(MemoryInfo))                    //查询指定进程的指定的地址空间的内存信息,看是否提交状态
                break;
            ::MessageBox(NULL,"VirtualQueryEx Successful !!!","haha   APIHook_Dll ---rivershan",MB_OK);
            add+=MemoryInfo.RegionSize;
            if(add>100000)
                ret=0;
        }
        CloseHandle(mpid);
}

3、问题:
目前我在当前进程下能够监测到VirtualQueryEx 的调用情况,但是其他进程调用次函数,我却无法监测到。我的SetWindowsHookEk函数第四个参数设置为NULL,应该是系统全局钩子,不知道为什么无法hook到其他进程。请高手指教,有急用,跪谢!!!

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 38
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
参考 Greg Hoglund 写的rootkit一书中第4章钩子的艺术,里面对全局性钩子和局部钩子的区别有详尽的描述。
简单的讲你所使用的api属于某个特定的dll,dll被载入4G逻辑地址空间之后,我们称其为模块,windows为了降低载入模块
的overhead,给一些系统dll,比如kernel.dll,为每个进程指定了相同的的载入地址。也就是说你只需要在这个位置挂上钩子即可。

问题在于你挂上的貌似是IAT表,把你需要的系统api想象成小姐,那么IAT表就相当于老鸨,对所有的进程来说小姐始终是那个
小姐,但是每个进程有自己的老鸨(相当与某种代理,使用调试器去跟踪一下就明白了,应该是类似jmp指令的东西,loader
在载入进程的时候动态写入的),所以我猜想,你只是去告诉自己的老鸨A,如果以后有谁想找小姐如花,叫他来找我,我给他
吃"生活"。而问题在于只有你自己通过老鸨A,其他进程都有自己的专属老鸨,所以没有受到影响。

在Greg Hoglund的书中,他给出的全局钩子应该是用驱动来实现的(如果没记错的话)。

在google中输入:
intitle:"index of" rootkits subverting the windows kernel chm -filetype:htm -filetype:html
随便找个目录把书下来看看第4章。

ps: 多年后再次看到匈牙利命名法,照样头晕。
2009-12-18 16:51
0
雪    币: 7
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢phthisis,我再试试看
2009-12-18 17:12
0
游客
登录 | 注册 方可回帖
返回
//