麻烦各位看一下我的代码,用钩子拦截api函数的,修改输入表地址

nightlocus 2006-09-25 11:21:22
这段代码编译通过,可是些个测试程序,加载dll,start hook,再弹个messagebox,可是这个messagebox并没有被替换,怎么会事?

#ifndef _HOOK_H_
#define _HOOK_H_
typedef struct tag_HOOKAPI
{
LPCSTR szFun; //被HOOK的函数名称
PROC pNewProc; //新的函数地址
PROC pOldProc; //被替代的函数地址
}HOOKAPI,*LPHOOKAPI;
class AFX_EXT_CLASS CKeyHook: public CObject
{
public:
CKeyHook();
~CKeyHook();
public:
HHOOK Start();
bool Stop();
};
#endif


#include "stdafx.h"
#include <afxdllx.h>
#include "ActiveKey.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static AFX_EXTENSION_MODULE HookDLL = { NULL, NULL };
#pragma data_seg("sharedata")
HHOOK g_Hook=NULL;
#pragma data_seg()
HINSTANCE g_Instance=NULL;
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved);

if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("HOOK.DLL Initializing!\n");

// Extension DLL one-time initialization
if (!AfxInitExtensionModule(HookDLL, hInstance))
{
return 0;
}
new CDynLinkLibrary(HookDLL);
g_Instance = (HINSTANCE)hInstance;
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("HOOK.DLL Terminating!\n");

AfxTermExtensionModule(HookDLL);
}
return 1; // ok
}
CKeyHook m_hook;
//函数声明
static int WINAPI MessageBoxA1(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCation,UINT uType);
extern "C" __declspec(dllexport) HookAPIByName(HMODULE hModule,/*进程模块句柄*/
LPCSTR szImportMod,/*输入库名称*/
LPHOOKAPI pHookApi)/*HOOKAPI结构指针*/;
//键盘钩子处理过程
extern "C" LRESULT WINAPI KeyBoardProc(int nCode,WPARAM wParam,LPARAM lParam)
{
return CallNextHookEx(g_Hook,nCode,wParam,lParam);
}
CKeyHook::CKeyHook()
{
HOOKAPI api;
api.szFun= "MessageBoxA"; //被拦截R的函数名
api.pNewProc = (PROC)MessageBoxA1;//设置替换函数的地址
HookAPIByName(g_Instance,"User32.dll",&api);
}
CKeyHook::~CKeyHook()
{
}
//导出类的启动钩子函数
HHOOK CKeyHook::Start()
{
g_Hook=SetWindowsHookEx(WH_GETMESSAGE,KeyBoardProc,g_Instance,0);
return g_Hook;
}
//停止钩子函数
bool CKeyHook::Stop()
{
if(g_Hook)
{
return UnhookWindowsHookEx(g_Hook);
}
return true;
}
extern "C" __declspec(dllexport)PIMAGE_IMPORT_DESCRIPTOR LocationIAT(HMODULE hModule,
LPCSTR szImportMod)
{
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER) hModule;
//检查是否为DOS程序,如果是返回NULL,因为DOS没有IAT
if( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE )
{
return NULL;
}
//检查是否为NT标志
PIMAGE_NT_HEADERS pNtHeader=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader
+(DWORD)(pDosHeader->e_lfanew));
if(pNtHeader->Signature != IMAGE_NT_SIGNATURE)
{
return NULL;
}
//没有IAT表则返回
if(pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
== 0)
{
return NULL;
}
//定位第一个IAT位置
PIMAGE_IMPORT_DESCRIPTOR pImportDesc=(PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDosHeader
+ (DWORD)pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
//根据输入库名称循环检查所有的IAT,如匹配则返回该IAT地址,否则检测下一个IAT
while(pImportDesc->Name)
{
//获取该IAT描述的输入库名称
PSTR szCurMod = (PSTR)((DWORD)pDosHeader + (DWORD)(pImportDesc->Name));
if(0 == stricmp(szCurMod,szImportMod))
{
break;
}
pImportDesc++;
}
if(NULL == pImportDesc->Name)
{
return NULL;
}
return pImportDesc;
}
//定位被拦截API函数的IAT并修改其内容为替代函数地址
extern "C" __declspec(dllexport) HookAPIByName(HMODULE hModule,/*进程模块句柄*/
LPCSTR szImportMod,/*输入库名称*/
LPHOOKAPI pHookApi)/*HOOKAPI结构指针*/
{
//定位szImportMod输入库在输入数据段中的IAT地址
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = LocationIAT(hModule,szImportMod);
if(pImportDesc == NULL)
{
return FALSE;
}
//第一个Thunk地址
PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule
+ (DWORD)(pImportDesc->OriginalFirstThunk));
//第一个IAT的Thunk地址
PIMAGE_THUNK_DATA pRealThunk = (PIMAGE_THUNK_DATA)((DWORD)hModule
+ (DWORD)(pImportDesc->FirstThunk));
//循环检测被拦截API函数的IAT项,并使用替代函数地址修改其值
while(pOrigThunk->u1.Function)
{
//检测此Thunk是否为IAT项
if((pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
{
PIMAGE_IMPORT_BY_NAME pByName = (PIMAGE_IMPORT_BY_NAME)((DWORD)hModule
+(DWORD)(pOrigThunk->u1.AddressOfData));
if(pByName->Name[0] == '\0')
{
return FALSE;
}
//检测是否为拦截的函数
if(strcmpi(pHookApi->szFun,(char*)pByName->Name) == 0)
{
MEMORY_BASIC_INFORMATION mbi_thunk;
//查询修改页的信息
VirtualQuery(pRealThunk,&mbi_thunk,sizeof(MEMORY_BASIC_INFORMATION));
//改变修改页保护属性为PAGE_READWRITE
VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,PAGE_READWRITE,
&mbi_thunk.Protect);
//保存原来的API函数地址
if(pHookApi->pOldProc == NULL)
{
pHookApi->pOldProc = (PROC)pRealThunk->u1.Function;
}
//修改API函数IAT项内容为替代函数地址
pRealThunk->u1.Function = (PDWORD)pHookApi->pNewProc;
//恢复保护属性
DWORD dwOldProtect;
VirtualProtect(mbi_thunk.BaseAddress,mbi_thunk.RegionSize,mbi_thunk.Protect,
&dwOldProtect);
}
pOrigThunk++;
pRealThunk++;
}
SetLastError(ERROR_SUCCESS);
return TRUE;
}
}
//定义替代函数,拦截MessageBoxA函数
int WINAPI MessageBoxA1(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCation,UINT uType)
{
return MessageBox(hWnd,"Hook API OK!","Hook API",uType);
return 1;
}
...全文
465 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
dic_walter 2006-09-29
  • 打赏
  • 举报
回复
建立全局钩子的作用是,将你的DLL可以注入到所有进程。其实不用在钩子里面做什么事情的。
nightlocus 2006-09-29
  • 打赏
  • 举报
回复
要是我在hookproc里面什么都不做,我怎么来实现挂接api的MessageBoxA的函数呢?
要是想把他作为一个全局的api拦截,那该怎么调整一下,请各位说个思路,谢谢!
nightlocus 2006-09-29
  • 打赏
  • 举报
回复
感谢各位,我现在有一个情况不是很清楚,请指教.
我在dll里面定义一个全局的对象,那么这个对象应该是在dllmain还没有进去的时候就初始化了.
如果dll里面有个hook的处理,那么这个对象是不是在每个进程里面都存在呢?如果是在每个进程里都存在的话,那这个对象是在什么时候开始初始化的?每个进程都有一个对象么?
折腾_苏州 2006-09-29
  • 打赏
  • 举报
回复
这段代码是你写的么? 仔细看了下, 问题有很多:
1. 有一行定义CKeyHook m_hook;,这很不好,你应该到test程序里定义,在这里定义调用构造,此时的g_Instance 为NULL,( 测试时发现),会出现很多预料错误
2. 在定义替代函数,拦截MessageBoxA函数,中又调用MessageBoxA,会造成连锁死拦截
3. 定位被拦截API函数的IAT并修改其内容为替代函数地址,一般是利用Dbghelp.h里的
ImageDirectoryEntryToData枚举到user32入口
4. 若你的程序针对以上大致修改,可以实现本进程hook ::MessageBox(...);(xp+vc6.0测试通过)
至于hook其他进程乃至全局api,则需做更进一步处理
nightlocus 2006-09-28
  • 打赏
  • 举报
回复
无人问津啊,自己顶啊
nightlocus 2006-09-27
  • 打赏
  • 举报
回复
各位,我的修改输入表的我知道了,可是怎么把他跟hook连接起来呢,实现动态的修改???
DentistryDoctor 2006-09-26
  • 打赏
  • 举报
回复
Yes.MessabeBoxA/MessageboxW,
参考Windows核心编程一书,上面有个现在的例子。
fayrount999 2006-09-26
  • 打赏
  • 举报
回复
不光要替換MessageBoxA,還要替換MessageBoxW
一個Asc,一個Unicode。
nightlocus 2006-09-26
  • 打赏
  • 举报
回复
那个例子看了,感觉跟我写的差不多,帮忙看看我的上面哪点有问题?
其实是两个文件,你把他拷贝,放到你的工程里,就可以调试的,谢谢了,真的不知道怎么会事,替换不了.

15,471

社区成员

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

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