前两天看Intel网站上贴了一篇关于设置HOOK的文章,讲到在多核CPU上,由于执行代码可能存在CPU CACHE里,因此当更改了函数起始6字节后,CPU CACHE里的对应内容并没有被修改,所以需要调用 FlushInstructionCache() 函数来更新CACHE。
更新后的代码如下,增加的代码以粗体标出了。
/** 通过地址来设置某个函数的钩子函数
@param HANDLE hApiHook - 由ApiHook_Init()函数生成的句柄
@param DWORD dwSrcFuncAddr - 源函数地址
@param DWORD dwNewFuncAddr - 钩子函数地址
@return INT (by default) - -1表示失败,>=0表示在hook数组中的序号
*/
INT ApiHook_SetByAddr(HANDLE hApiHook, DWORD dwSrcFuncAddr, DWORD dwNewFuncAddr)
{
DWORD dwOldProtect;
DWORD dwNewProtect;
DWORD lpSrcFunc;
DWORD lppNewFunc;
UINT i;
INT nAlreadyFlag = 0;
APIHOOK *pApiHook = (APIHOOK *)hApiHook;
if ( NULL == hApiHook )
{
return -1;
}
lpSrcFunc = dwSrcFuncAddr;
/* 查找是否已被设置了钩子 */
for ( i = 0; i < pApiHook->uMaxFunctions; i++ )
{
if ( pApiHook->pHookData[i].dwSrcFuncAddr == lpSrcFunc )
{
/* 如果已经被设置了钩子,仅仅改变. */
nAlreadyFlag = 1;
break;
}
}
/* 如果没有设置源函数的钩子函数,在表中找出一个可供记录的位置. */
if ( i == pApiHook->uMaxFunctions )
{
for ( i = 0; i < pApiHook->uMaxFunctions; i++ )
{
if (pApiHook->pHookData[i].wFlag == 0 )
{
break;
}
}
if ( i == pApiHook->uMaxFunctions )
{
return -1;
}
}
/* 将新的钩子函数地址记录到表中 */
pApiHook->pHookData[i].dwNewFuncAddr = dwNewFuncAddr;
/* 以下这段代码将源函数头部6个字节保存到表中 */
lppNewFunc = (DWORD)(&(pApiHook->pHookData[i].dwNewFuncAddr) );
if ( !nAlreadyFlag )
{
/* 将源函数起始处6个字节保存到 byHeaderCode.中 */
memcpy( pApiHook->pHookData[i].byHeaderCode, (const void *)lpSrcFunc, 6);
}
/* 以下这段代码将源函数首部6个字节改成为一条跳转到新函数地址的指令 */
if ( VirtualProtect( (LPVOID)lpSrcFunc,
6,
PAGE_EXECUTE_READWRITE,
&dwOldProtect ) == 0 )
{
/*
* Failure.
*/
return -1;
}
*(unsigned char *)lpSrcFunc = (unsigned char)0xff;
*(((unsigned char *)lpSrcFunc)+1) = (unsigned char)0x25;
memcpy( (void *)(lpSrcFunc+2),
(const void *)&lppNewFunc,
4 ); /* address */
if ( VirtualProtect( (LPVOID)lpSrcFunc,
6,
dwOldProtect,
&dwNewProtect) == 0 ) {
/*
* Failure.
*/
return -1;
};
pApiHook->pHookData[i].wFlag = 1;
pApiHook->pHookData[i].dwSrcFuncAddr = lpSrcFunc;
/* 使用以下FlushInstructionCache调用来支持多核CPU上的CACAHE的更新,
* 上面的代码只更改了内存里的地址,没有更改CPU CACHE里的对应内容。
*/
FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
return (INT)i;
}
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1209218