钩子太短,请高手加长!

zhun_yi 2006-04-26 02:54:10
我做了一个全局API钩子,拦截删除文件和重命名文件的操作,但是只能钩住设置钩子的那个程序的操作,请高手帮我看看哪里有错:

//定义全局共享数据段

#pragma data_seg("Shared")
HMODULE hmodDll=NULL;
HHOOK hHook=NULL;

#pragma data_seg()

#pragma comment(linker,"/Section:Shared,rws") //设置全局共享数据段的属性


BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
//if(sHook)
hmodDll=hModule;
break;
case DLL_PROCESS_DETACH:
UnInstallHook();
break;
}

return TRUE;
}

hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgProc,hmodDll,0);

HookAllAPI("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"DeleteFileW"),(PROC)&H_DeleteFileW,NULL);
HookAllAPI("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"DeleteFileA"),(PROC)&H_DeleteFileA,NULL);
//MoveFile
HookAllAPI("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"MoveFileW"),(PROC)&H_MoveFileW,NULL);
HookAllAPI("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"MoveFileA"),(PROC)&H_MoveFileA,NULL);


//.def文件
LIBRARY APIHook_Dll.dll
EXPORT
InstallHook @1



//安装钩子的应用程序
InstallHook(TRUE,0);//第2个参数是线程ID号,设为0就是全局钩子,否则只钩住本线程.
...全文
327 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhun_yi 2006-04-28
  • 打赏
  • 举报
回复
还是要靠自己解决,知道问题所在了。
zhun_yi 2006-04-27
  • 打赏
  • 举报
回复
我们来一步一步分析.
1.应用程序调用DLL
InstallHook(TRUE,0);
//TRUE,代表是安装而不是卸载;第二个参数是主线程号,0代表是挂钩所有进程,否则只挂钩本进程.

2.DLL中InstallHook(BOOL IsHook,DWORD dwThreadId)安装钩子
SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgProc,hmodDll,dwThreadId);
//第三个参数hmodDll是本DLL的实例句柄,放在了共享数据段中.
//第四个参数是要挂钩的进程,dwThreadId==0代表挂钩所有进程

3.查找所挂钩的进程所应用的dll模块
HookAllAPI("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"DeleteFileW"),(PROC)&H_DeleteFileA,NULL);
最后一个参数代表要挂钩的模块名称,NULL代表枚举被挂钩进程(这里是所有进程)的所有引用的模块,并对这些模块进行传进来的相应函数名称的查找

4.进行IAT转换
HookOneAPI()
zhun_yi 2006-04-27
  • 打赏
  • 举报
回复
我确实很菜,刚才看了一下核心编程,这是原话:"使用Wr i t e P r o c e s s M e m o r y函数,而不是
I n t e r l o c k e d E x c h a n g e P o i n t e r函数是因为Wr i t e P r o c e s s M e m o r y能够改变字节,而不管这些字节拥
有什么页面保护属性。例如,如果页面拥有PA G E _ R E A D O N LY保护属性,那么I n t e r l o c k e d
E x c h a n g e P o i n t e r函数将会引发访问违规,而Wr i t e P r o c e s s M e m o r y函数则能够处理页面保护属性
的所有变更,并且仍然能够正常运行。"
但是我调试发现确实有时Wr i t e P r o c e s s M e m o r y返回失败,也就是0.
xhzxlqt 2006-04-27
  • 打赏
  • 举报
回复
我已经告诉你了,是你没有看懂我说的
你好像对它运行的机理根本就不了解哦
zhun_yi 2006-04-27
  • 打赏
  • 举报
回复
gao_ming77(小明) 说的对,我是下载源程序再修改的,但不知道出自哪里.
"看你的程序也就只是挂接了钩子所在进程的所有deletefile, movefile函数呀",为什么这么说?我的HookAllAPI函数不是挂接了所有进程吗?我跟踪测试了一下,一个挂了96个.
可能是你说的没有修改页属性,你能告诉我应该怎样修改吗?
bluesky23 2006-04-27
  • 打赏
  • 举报
回复
UP MARK
gao_ming77 2006-04-27
  • 打赏
  • 举报
回复
楼主的程序来自于Jeff Richer的windows核心编程中的APIHook吧。
看你的程序也就只是挂接了钩子所在进程的所有deletefile, movefile函数呀。没见到你怎么挂接所有应用程序的。
是不是你想用SetWindowHookEx用消息来将你的挂接dll加载到其他进程中?

还有就是楼主的这段代码由问题。
WriteProcessMemory(GetCurrentProcess(),ppfn,&(pfnDummyFuncAddress),
sizeof(pfnDummyFuncAddress),NULL);

因为有可能失败的。
你可能需要修改这片virtual memory的protect属性。
需要调用virutalquery + virtualprotectex。
zhun_yi 2006-04-27
  • 打赏
  • 举报
回复
以上说的都不是原因啊,干脆给出源程序让大家帮我找找原因吧.我调用InstallHook(TRUE,0)安装钩子.
APIHook_Dll.cpp ////////////////////////////////////////
// rivershan写于
////////////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "APIHook_Dll.h"
#include "Dbghelp.h"
#include "Tlhelp32.h"

#pragma comment(lib,"ImageHlp") //定义全局共享数据段

#pragma data_seg("Shared")
HMODULE hmodDll=NULL;
HHOOK hHook=NULL;

#pragma data_seg()

#pragma comment(linker,"/Section:Shared,rws") //设置全局共享数据段的属性

///////////////////////////////////// DllMain 函数 /////////////////////////////////////////
//dll的入口点
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
hmodDll=hModule;
break;
case DLL_PROCESS_DETACH:
//UnInstallHook();
break;
}
hmodDll=hModule;
return TRUE;
}

///////////////////////////////////// HookOneAPI 函数 /////////////////////////////////////////
//进行IAT转换的关键函数,其参数含义:
//pszCalleeModuleName:需要hook的模块名
//pfnOriginApiAddress:要替换的自己API函数的地址
//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);//IAT
for (;pThunk->u1.Function;pThunk++)
{
//ppfn记录了与IAT表项相应的函数的地址

PROC * ppfn= (PROC *)&pThunk->u1.Function;
if (*ppfn == pfnOriginApiAddress)
{
//如果地址相同,也就是找到了我们想要的函数,进行改写,将其指向我们所定义的函数

WriteProcessMemory(GetCurrentProcess(),ppfn,&(pfnDummyFuncAddress),
sizeof(pfnDummyFuncAddress),NULL);
return;
}
}
}

//查找所挂钩的进程所应用的dll模块的

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;
HANDLE hSnapshot;
MODULEENTRY32 me = {sizeof(MODULEENTRY32)};
//MODULEENTRY32:描述了一个被指定进程所应用的模块的struct

VirtualQuery(HookOneAPI,&mInfo,sizeof(mInfo));
hModHookDLL=(HMODULE)mInfo.AllocationBase;

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);
}
return TRUE;
}
//如果传进来了,进行查找
else
{
HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,
pfnDummyFuncAddress,hModCallerModule);
return TRUE;
}
return FALSE;
}

//通过使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);
}

//钩子子程。与其它钩子子程不大相同,没做什么有意义的事情,继续调用下一个钩子子程,形成循环
LRESULT CALLBACK GetMsgProc(int code,WPARAM wParam,LPARAM lParam)
{
return CallNextHookEx(hHook,code,wParam,lParam);
}

//安装或卸载钩子,BOOL IsHook参数是标志位
//对要钩哪个API函数进行初始化
//我们这里装的钩子类型是WH_GETMESSAGE
void __declspec(dllexport) WINAPI InstallHook(BOOL IsHook,DWORD dwThreadId)
{
if(IsHook)
{
//hmodDll = ::LoadLibrary("APIHook_Dll.dll");
hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgProc,hmodDll,0);//dwThreadId);

//DeleteFile
HookAllAPI("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"DeleteFileW"),(PROC)&H_DeleteFileW,NULL);
HookAllAPI("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"DeleteFileA"),(PROC)&H_DeleteFileA,NULL);
//MoveFile
HookAllAPI("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"MoveFileW"),(PROC)&H_MoveFileW,NULL);
HookAllAPI("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"MoveFileA"),(PROC)&H_MoveFileA,NULL);
}
else
{
UnInstallHook();
//DeleteFile
UnhookAllAPIHooks("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"DeleteFileW"),(PROC)&H_DeleteFileW,NULL);
UnhookAllAPIHooks("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"DeleteFileA"),(PROC)&H_DeleteFileA,NULL);

//MoveFile
UnhookAllAPIHooks("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"MoveFileW"),(PROC)&H_MoveFileW,NULL);
UnhookAllAPIHooks("kernel32.dll",GetProcAddress(GetModuleHandle("kernel32.dll"),
"MoveFileA"),(PROC)&H_MoveFileA,NULL);
}
}

//卸载钩子
BOOL WINAPI UnInstallHook()
{
UnhookWindowsHookEx(hHook);
return TRUE;
}

BOOL WINAPI H_DeleteFileA(LPCTSTR cbString)
{
MessageBox(NULL,cbString,"DeleteFileA",MB_OK);
//DeleteFileA(cbString);//返回原来的函数,以显示字符
return TRUE;
}

BOOL WINAPI H_DeleteFileW(LPCWSTR cbString)
{
MessageBox(NULL,(LPCTSTR)cbString,"DeleteFileW",MB_OK);
//DeleteFileW((LPCWSTR)cbString);//返回原来的函数,以显示字符
return TRUE;
}
BOOL WINAPI H_MoveFileA(LPCTSTR szOldName , LPCTSTR szNewName)
{
MessageBox(NULL,szOldName,"MoveFileA",MB_OK);
//DeleteFileA(cbString);//返回原来的函数,以显示字符
return TRUE;
}
BOOL WINAPI H_MoveFileW(LPCWSTR szOldName , LPCWSTR szNewName)
{
MessageBox(NULL,(LPCTSTR)szOldName,"MoveFileW",MB_OK);
//DeleteFileW((LPCWSTR)cbString);//返回原来的函数,以显示字符
return TRUE;
}
化外之民 2006-04-27
  • 打赏
  • 举报
回复
mark
zhun_yi 2006-04-27
  • 打赏
  • 举报
回复
u.................p
xhzxlqt 2006-04-26
  • 打赏
  • 举报
回复
HookAllAPI时需要在目标进程里进行,即DLL应与被HOOK的进程具体相同的私有4G空间。
因此需要先将DLL注入到目标进程。

“只能钩住设置钩子的那个程序的操作”就是因为如上原因
xiao2004 2006-04-26
  • 打赏
  • 举报
回复
设置钩子要在DLL进入点MainDLL中啊....

写在外面根本不进去的.
goodboyws 2006-04-26
  • 打赏
  • 举报
回复
HookAllAPI写的不对,需要改成递归式调用检查PE入口,你这样只能找到直接调用kernel32.dll的程序
化外之民 2006-04-26
  • 打赏
  • 举报
回复
up up
zhun_yi 2006-04-26
  • 打赏
  • 举报
回复
VC版的人气怎么咋就这么高呢?我刚发的贴就沉下来了,UP!
zhun_yi 2006-04-26
  • 打赏
  • 举报
回复
去掉UnInstallHook();也是一样的
而且我还发现只能钩住VC6 DEBUG版的操作,就是本来我这个测试应用程序还是能拦住的,但是一编译成发布版的或者用.NET2003编译就拦截不住.
帮我看看是哪里设置不对.
goodboyws 2006-04-26
  • 打赏
  • 举报
回复
UnInstallHook();不能放在DLL_PROCESS_DETACH里

15,466

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧