-
-
[旧帖] [讨论]写了一个APIHook的程序,只能hook到自身进程,无法hook到其他进程,原因未查明,求高人指点 0.00雪花
-
发表于: 2009-12-18 07:53 1125
-
我写了一个程序,想实现对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);
HANDLE mmpid=GetCurrentProcess();
if(mmpid==NULL)
{
::MessageBox(NULL," mmpid OpenProcess fail !!!"," fail ",MB_OK);
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken)) //获得当前进程的访问令牌句柄
{
if(LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid)) //获得访问令牌的本地唯一标识符(Luid),是一个64位的值
{
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //要使能一个权限就设定Attributes为SE_PRIVILEGE_ENABLED
if(AdjustTokenPrivileges(hToken,FALSE,&tp,NULL,NULL,0)) //修改访问令牌权限,将Attributes修改为SE_PRIVILEGE_ENABLED
//printf("AdjustTokenPrivileges successful! \n ");
::MessageBox(NULL," AdjustTokenPrivileges successfull !!!"," AdjustTokenPrivileges ",MB_OK);
else
//printf("AdjustTokenPrivileges fail! \n ");
::MessageBox(NULL," AdjustTokenPrivileges fail !!!"," AdjustTokenPrivileges fail ",MB_OK);
}
}
if(hToken)
CloseHandle(hToken);
mmpid=OpenProcess(PROCESS_ALL_ACCESS, FALSE,0); //系统重要进程的句柄无法直接打开,经过修改访问令牌权限后再重新打开
}
BOOL Temp3=WriteProcessMemory(mmpid,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到其他进程。请高手指教,有急用,跪谢!!!
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);
HANDLE mmpid=GetCurrentProcess();
if(mmpid==NULL)
{
::MessageBox(NULL," mmpid OpenProcess fail !!!"," fail ",MB_OK);
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken)) //获得当前进程的访问令牌句柄
{
if(LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tp.Privileges[0].Luid)) //获得访问令牌的本地唯一标识符(Luid),是一个64位的值
{
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //要使能一个权限就设定Attributes为SE_PRIVILEGE_ENABLED
if(AdjustTokenPrivileges(hToken,FALSE,&tp,NULL,NULL,0)) //修改访问令牌权限,将Attributes修改为SE_PRIVILEGE_ENABLED
//printf("AdjustTokenPrivileges successful! \n ");
::MessageBox(NULL," AdjustTokenPrivileges successfull !!!"," AdjustTokenPrivileges ",MB_OK);
else
//printf("AdjustTokenPrivileges fail! \n ");
::MessageBox(NULL," AdjustTokenPrivileges fail !!!"," AdjustTokenPrivileges fail ",MB_OK);
}
}
if(hToken)
CloseHandle(hToken);
mmpid=OpenProcess(PROCESS_ALL_ACCESS, FALSE,0); //系统重要进程的句柄无法直接打开,经过修改访问令牌权限后再重新打开
}
BOOL Temp3=WriteProcessMemory(mmpid,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到其他进程。请高手指教,有急用,跪谢!!!
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: