关于hook设置函数如何支持多核CPU的一个说明

来源:互联网 发布:喜欢同性知乎 编辑:程序博客网 时间:2024/04/30 02:26

前两天看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


原创粉丝点击