⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 2_4 实例:hook管理功能的实现 - 《多任务下的数据结构与算法》 - 免费试读 - book_csdn_net.htm

📁 主要介绍了多任务下面的一些数据结构和算法,比如树和图的一些遍历
💻 HTM
📖 第 1 页 / 共 3 页
字号:
          if(szType==1)
            loc="http://book.csdn.net/book/morelz.aspx?key="+escape(document.getElementById("txtTopKey").value);
          else
             loc="http://club.book.csdn.net/book/s.aspx?key="+escape(document.getElementById("txtTopKey").value);
          
          self.location=loc;
        
      } 
    }
  </SCRIPT>

<DIV id=booknavbottom2>
<DIV class=hotleft><A href="http://book.csdn.net/subject/allbook.htm" 
target=_blank>全部图书</A> <FONT color=red>推荐</FONT>:<A 
href="http://club.book.csdn.net/book/s.aspx?key=asp.net">ASP.NET</A> <A 
href="http://club.book.csdn.net/book/s.aspx?key=ajax">Ajax</A> <A 
href="http://club.book.csdn.net/book/s.aspx?key=spring">Spring</A> <A 
href="http://club.book.csdn.net/book/s.aspx?key=Hibernate">Hibernate</A> <A 
href="http://club.book.csdn.net/book/s.aspx?key=Java">Java</A></DIV>
<DIV class=hotright><SELECT id=listSearchType name=aa> <OPTION value=2 
  selected>书友会</OPTION> <OPTION value=1>连载</OPTION></SELECT><INPUT 
onkeypress=if(event.keyCode==13){SearchBook_Top();} id=txtTopKey maxLength=25><INPUT onclick=SearchBook_Top(); type=button value=搜索 name=提交></DIV></DIV></DIV>
<DIV class=area>
<SCRIPT 
src="2_4 实例:HOOK管理功能的实现 - 《多任务下的数据结构与算法》 - 免费试读 - book_csdn_net.files/BookDetailAd.js" 
type=text/javascript></SCRIPT>

<DIV class=col1>
<DIV class=lineBlue></DIV><!-- title -->
<DIV class=arcTitle>
<H1><A href="http://book.csdn.net/bookfiles/65">多任务下的数据结构与算法 </A></H1>
<DIV style="FONT-SIZE: 15px; TEXT-ALIGN: center"><A 
href="http://book.csdn.net/bookfiles/65/100651880.shtml">2.4 实例:HOOK管理功能的实现 
</A></DIV>
<DIV style="FONT-SIZE: 15px; TEXT-ALIGN: center"><A class=url 
href="http://book.csdn.net/">http://book.csdn.net/</A> 2006-7-14 18:04:00 </DIV>
<DIV class=clear></DIV>
<DIV 
style="BORDER-RIGHT: #0b5f98 1px solid; BORDER-TOP: #0b5f98 1px solid; MARGIN: 0px auto; BORDER-LEFT: #0b5f98 1px solid; WIDTH: 700px; BORDER-BOTTOM: #0b5f98 1px solid">
<DIV 
style="PADDING-RIGHT: 1px; PADDING-LEFT: 1px; FLOAT: left; PADDING-BOTTOM: 1px; WIDTH: 16px; COLOR: white; PADDING-TOP: 1px; BACKGROUND-COLOR: #0b5f98">图书导读 
</DIV>
<DIV 
style="PADDING-LEFT: 2px; FLOAT: right; WIDTH: 670px; LINE-HEIGHT: 16pt; TEXT-ALIGN: left"><!--导读-->
<H1 id=divCurrentNode 
style="PADDING-LEFT: 2px; FONT-SIZE: 12px; WIDTH: 100%; COLOR: #b83507; TEXT-ALIGN: left">当前章节:<A 
href="http://book.csdn.net/bookfiles/65/100651880.shtml"><FONT color=red>2.4 
实例:HOOK管理功能的实现 </FONT></A></H1>
<DIV id=divRelateNode style="PADDING-LEFT: 2px">
<DIV style="FLOAT: left; WIDTH: 49%">·<A 
href="http://book.csdn.net/bookfiles/65/100651877.shtml">2.1 栈 </A></DIV>
<DIV style="FLOAT: right; WIDTH: 49%">·<A 
href="http://book.csdn.net/bookfiles/65/100651878.shtml">2.2 队列 </A></DIV>
<DIV style="FLOAT: left; WIDTH: 49%">·<A 
href="http://book.csdn.net/bookfiles/65/100651879.shtml">2.3 排序表 </A></DIV>
<DIV style="FLOAT: right; WIDTH: 49%">·<A 
href="http://book.csdn.net/bookfiles/65/100652553.shtml">5.1.1 
普通树的描述方法</A></DIV>
<DIV style="FLOAT: left; WIDTH: 49%">·<A 
href="http://book.csdn.net/bookfiles/65/100652554.shtml">5.1.2 
树的操作接口设计</A></DIV>
<DIV style="FLOAT: right; WIDTH: 49%">·<A 
href="http://book.csdn.net/bookfiles/65/100652555.shtml">5.1.3 
树的遍历算法</A></DIV></DIV></DIV></DIV>
<DIV class=clear></DIV></DIV><!-- main -->
<DIV id=main>
<DIV id=text>
<DIV id=csdn_zhaig_ad_yahoo_2></DIV>
<H2 style="LINE-HEIGHT: 16.3pt"><A name=_Toc122884728><FONT size=5>2.4 
</FONT></A>实例:HOOK管理功能的实现</H2>
<H3 style="LINE-HEIGHT: 16.3pt"><A name=_Toc122884729></A>2.4.1 单个函数的HOOK实现</H3>
<P 
style="LINE-HEIGHT: 16.3pt">很多读者可能用过金山词霸之类的软件,鼠标只要往单词上一指,就可以弹出对应单词的解释,这种屏幕取词便是使用了HOOK功能拦截Windows 
API的调用来实现的。本节要用数组来实现对函数HOOK的管理功能,首先讨论如何实现对单个函数的HOOK功能。</P>
<P>对某个函数的HOOK就是通过某种方法使得调用这个函数时调用到指定的钩子函数。实现HOOK的方法很多,最简单的一种方法便是将调用函数的开头位置的代码改成一条跳转到钩子函数的指令即可。</P>
<P>譬如我们自己写了一个MyMalloc()函数,以实现所有对malloc()函数的调用都调用MyMalloc()函数,假设malloc函数的起始地址是0x00421540,那么只要将0x00421540开始的几个字节改成jmp 
DWORD PTR MyMalloc指令即可, 假设MyMalloc()函数执行代码的起始地址为00401830,在INTEL32位芯片系列的机器中,jmp 
DWORD PTR 
MyMalloc这条指令的机器码为0xff2500401830,共6个字节,只要将这6个字节写入malloc()函数的开头6个字节中,即可实现调用malloc()函数时跳转到MyMalloc()函数。</P>
<P>以下代码便能实现将跳转到MyMalloc()函数的指令写入malloc函数起始位置。</P>
<P style="LINE-HEIGHT: 14pt">DWORD lpSrcFunc = (DWORD)malloc;</P>
<P style="LINE-HEIGHT: 14pt">DWORD dwNewFunc = (DWROD)MyMalloc;</P>
<P style="LINE-HEIGHT: 14pt">DWORD lppNewFunc = &amp;dwNewFunc;</P>
<P style="LINE-HEIGHT: 14pt">*(unsigned char *)lpSrcFunc = (unsigned 
char)0xff;</P>
<P style="LINE-HEIGHT: 14pt">*(((unsigned char *)lpSrcFunc)+1) = (unsigned 
char)0x25;</P>
<P style="LINE-HEIGHT: 14pt">memcpy( (void *)(lpSrcFunc+2),(const void 
*)&amp;lppNewFunc,sizeof(DWORD) );</P>
<P style="LINE-HEIGHT: 15.8pt">如果是像Windows 
NT系列的操作系统,对执行代码的内存做了保护,是不能直接调用以上代码的,还需要使用VirtualProtect()函数将lpSrcFunc指向的地址处的内存属性改成可以写的,才可以调用以上代码。</P>
<P 
style="LINE-HEIGHT: 15.8pt">还要考虑将malloc()的调用改掉后再如何恢复的问题,否则程序运行很容易出现问题。恢复的做法便是将malloc()起始处的6个字节先保存起来,当要恢复时,将保存的6个字节写回原来位置即可。</P>
<P 
style="LINE-HEIGHT: 15.8pt">还需说明的是,以上介绍的是同一进程内的HOOK实现方法,如果要HOOK其他进程中的函数调用,还需要将上述代码注入到目标进程中去执行才可以实现HOOK功能,将代码注入到其他进程中的方法有很多种,Windows系统下常用的方法有以下几种。</P>
<P style="LINE-HEIGHT: 15.8pt">① 使用Windows API函数 
SetWindowsHookEx()将程序注入到其他进程中执行;</P>
<P style="LINE-HEIGHT: 15.8pt">② 使用修改DLL IMPORT表的方法来实现对DLL中函数的HOOK;</P>
<P style="LINE-HEIGHT: 15.8pt">③ 使用CreateRemoteThread()函数将代码注入到其他进程中执行;</P>
<P style="LINE-HEIGHT: 15.8pt">④ 对于Windows 
NT系列操作系统,还可以使用注册表设置来实现将代码注入到其他进程中执行。</P>
<P style="LINE-HEIGHT: 15.8pt">以上几种方法在很多书籍中都有详细介绍,这里就不作进一步介绍。</P>
<H3 style="LINE-HEIGHT: 15.8pt"><A name=_Toc122884730></A>2.4.2 多个函数的HOOK实现</H3>
<P 
style="LINE-HEIGHT: 15.8pt">采用前面的方法对多个函数实现HOOK,当设置HOOK时,如何保存那些函数的起始6个字节?当取消HOOK时,如何从保存的数据中找到某个函数的起始6个字节?解决这个问题,可以用一个结构体数组来实现,结构体中包含源函数地址、源函数起始位置的6个字节数据等内容。HOOK管理结构体设计如下。</P>
<P style="LINE-HEIGHT: 14pt">typedef struct APIHOOKDATA_st {</P>
<P style="LINE-HEIGHT: 14pt">DWORD dwSrcFuncAddr; /* 源函数的地址 */</P>
<P style="LINE-HEIGHT: 14pt">DWORD dwNewFuncAddr; /* 钩子函数的地址 */</P>
<P style="LINE-HEIGHT: 14pt">BYTE byHeaderCode[6]; /* 源函数起始6字节 */</P>
<P style="LINE-HEIGHT: 14pt">WORD wFlag; /* 用来表示是否设置了HOOK的标志 */</P>
<P style="LINE-HEIGHT: 14pt">} APIHOOKDATA;</P>
<P style="LINE-HEIGHT: 14pt">typedef struct APIHOOK_st {</P>
<P style="LINE-HEIGHT: 14pt">APIHOOKDATA *pHookData;</P>
<P style="LINE-HEIGHT: 14pt">UINT uMaxFunctions;</P>
<P style="LINE-HEIGHT: 14pt">} APIHOOK;</P>
<P>APIHOOKDATA结构体用来记录单个函数的HOOK数据,APIHOOK结构体用来管理多个函数的HOOK,里面包含一个APIHOOKDATA结构体数组,uMaxFunctions是数组的长度,表示最多可以HOOK的函数个数。</P>
<H4>1. 多个函数的HOOK管理</H4>
<P>对多个函数的HOOK管理可以分为以下四个操作步骤。</P>
<P>① 初始化;</P>
<P>② 设置某个函数的HOOK;</P>
<P>③ 取消某个函数的HOOK;</P>
<P>④ 关闭。</P>
<P>下面以Windows NT系列操作系统为例来实现以上四个操作的代码。初始化操作主要是为结构体分配内存,将整个数组清零。编码如下。</P>
<P style="LINE-HEIGHT: 14pt">/** ApiHook 模块初始化函数</P>
<P style="LINE-HEIGHT: 14pt">@param INT nMaxHookFuncCounts——最大可设置的钩子数量 </P>
<P style="LINE-HEIGHT: 14pt">@return INT (by default)<SUB> </SUB>——返回NULL 
表示失败</P>
<P style="LINE-HEIGHT: 14pt">*/</P>
<P style="LINE-HEIGHT: 14pt"><B>HANDLE ApiHook_Init(UINT uMaxFunctions)</B></P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">APIHOOK * pApiHook = (APIHOOK 
*)malloc(sizeof(APIHOOK));</P>
<P style="LINE-HEIGHT: 14pt">if ( pApiHook )</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">pApiHook-&gt;uMaxFunctions = uMaxFunctions;</P>
<P style="LINE-HEIGHT: 14pt">pApiHook-&gt;pHookData =</P>
<P style="LINE-HEIGHT: 14pt">(APIHOOKDATA *)malloc(sizeof(APIHOOKDATA) 
*uMaxFunctions);</P>
<P style="LINE-HEIGHT: 14pt">if ( NULL != pApiHook-&gt;pHookData)</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">memset(pApiHook-&gt;pHookData,0,sizeof(APIHOOKDATA) 
*uMaxFunctions );</P>
<P style="LINE-HEIGHT: 14pt">return (HANDLE)pApiHook;</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">free(pApiHook);</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">return NULL;</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<H4>2. 设置HOOK操作</H4>
<P>设置某个函数的HOOK操作主要是在数组中查找未使用的节点,将源函数相关信息保存到节点中,修改源函数起始位置的几个字节为一条跳转到钩子函数的指令。</P>
<P style="LINE-HEIGHT: 14pt">/** 通过地址来设置某个函数的钩子函数</P>
<P style="LINE-HEIGHT: 14pt">@param HANDLE hApiHook——由ApiHook_Init()函数生成的句柄 </P>
<P style="LINE-HEIGHT: 14pt">@param DWORD dwSrcFuncAddr——源函数地址 </P>
<P style="LINE-HEIGHT: 14pt">@param DWORD dwNewFuncAddr——钩子函数地址 </P>
<P style="LINE-HEIGHT: 14pt">@return INT (by default)<SUB> 
</SUB>——返回-1表示失败;返回0表示在HOOK数组中的序号</P>
<P style="LINE-HEIGHT: 14pt">*/</P>
<P style="LINE-HEIGHT: 14pt"><B>INT ApiHook_SetByAddr(HANDLE 
hApiHook</B><B>,</B><B>DWORD dwSrcFuncAddr</B><B>,</B><B></B></P>
<P style="LINE-HEIGHT: 14pt"><B></B><B></B><B>DWORD dwNewFuncAddr)</B></P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">DWORD dwOldProtect;</P>
<P style="LINE-HEIGHT: 14pt">DWORD dwNewProtect;</P>
<P style="LINE-HEIGHT: 14pt">DWORD lpSrcFunc;</P>
<P style="LINE-HEIGHT: 14pt">DWORD lppNewFunc;</P>
<P style="LINE-HEIGHT: 14pt">UINT i;</P>
<P style="LINE-HEIGHT: 14pt">INT nAlreadyFlag = 0;</P>
<P style="LINE-HEIGHT: 14pt">if ( NULL == hApiHook )</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">return-1;</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">APIHOOK *pApiHook = (APIHOOK *)hApiHook;</P>
<P style="LINE-HEIGHT: 14pt">lpSrcFunc = dwSrcFuncAddr;</P>
<P style="LINE-HEIGHT: 14pt">/* 查找是否已设置了钩子 */</P>
<P style="LINE-HEIGHT: 14pt">for ( i = 0; i &lt; pApiHook-&gt;uMaxFunctions; i++ 
)</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">if ( pApiHook-&gt;pHookData[i].dwSrcFuncAddr == 
lpSrcFunc )</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">/* 如果已经设置了钩子,仅仅改变 */</P>
<P style="LINE-HEIGHT: 14pt">nAlreadyFlag = 1;</P>
<P style="LINE-HEIGHT: 14pt">break;</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">/* 如果没有设置源函数的钩子函数,在表中找出一个可供记录的位置 */</P>
<P style="LINE-HEIGHT: 14pt">if ( i == pApiHook-&gt;uMaxFunctions )</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">for ( i = 0; i &lt; pApiHook-&gt;uMaxFunctions; i++ 
)</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">if (pApiHook-&gt;pHookData[i].wFlag == 0 )</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">break;</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">} </P>
<P style="LINE-HEIGHT: 14pt">if ( i == pApiHook-&gt;uMaxFunctions )</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">return-1;</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">/* 将新的钩子函数地址记录到表中 */</P>
<P style="LINE-HEIGHT: 14pt">pApiHook-&gt;pHookData[i].dwNewFuncAddr = 
dwNewFuncAddr;</P>
<P style="LINE-HEIGHT: 14pt">/* 以下这段代码将源函数头部6个字节保存到表中 */</P>
<P style="LINE-HEIGHT: 14pt">lppNewFunc = 
(DWORD)(&amp;(pApiHook-&gt;pHookData[i].dwNewFuncAddr) );</P>
<P style="LINE-HEIGHT: 14pt">if ( !nAlreadyFlag )</P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">/* 将源函数起始处6个字节保存到 byHeaderCode.中 */</P>
<P style="LINE-HEIGHT: 14pt">memcpy( 
pApiHook-&gt;pHookData[i].byHeaderCode,(const void *)lpSrcFunc,6);</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">/* 以下这段代码将源函数首部6个字节改成为一条跳转到新函数地址的指令 */</P>
<P style="LINE-HEIGHT: 14pt">if ( VirtualProtect( (LPVOID)lpSrcFunc,6, 
PAGE_EXECUTE_READWRITE,</P>
<P style="LINE-HEIGHT: 14pt">&amp;dwOldProtect ) == 0 ) </P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">return-1;</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<P style="LINE-HEIGHT: 14pt">*(unsigned char *)lpSrcFunc = (unsigned 
char)0xff;</P>
<P style="LINE-HEIGHT: 14pt">*(((unsigned char *)lpSrcFunc)+1) = (unsigned 
char)0x25;</P>
<P style="LINE-HEIGHT: 14pt">memcpy( (void *)(lpSrcFunc+2),(const void 
*)&amp;lppNewFunc,4 ); </P>
<P style="LINE-HEIGHT: 14pt">if ( VirtualProtect( 
(LPVOID)lpSrcFunc,6,dwOldProtect, &amp;dwNewProtect) == 0 ) </P>
<P style="LINE-HEIGHT: 14pt">{</P>
<P style="LINE-HEIGHT: 14pt">return-1;</P>
<P style="LINE-HEIGHT: 14pt">};</P>
<P style="LINE-HEIGHT: 14pt">pApiHook-&gt;pHookData[i].wFlag = 1;</P>
<P style="LINE-HEIGHT: 14pt">pApiHook-&gt;pHookData[i].dwSrcFuncAddr = 
lpSrcFunc; </P>
<P style="LINE-HEIGHT: 14pt">return (INT)i;</P>
<P style="LINE-HEIGHT: 14pt">}</P>
<H4>3. 取消HOOK操作</H4>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -