[转载]FYI, How I solved Windows re-entrancy hooking problem

本文通过一个实例探讨了在Windows API中使用钩子时遇到的重入问题。具体问题出现在使用CreateFileExW()钩子调用GetSecurityInfo()时,后者间接再次调用了CreateFileExW(),导致内存被意外覆盖,最终解释了为何某些钩子行为异常。

This past week, I debugged an interesting hook problem, caused by my hook calling Windows API's that caused a re-entrancy problem. This is exactly what happened. Maybe it will explain why certain hooks work strangely like when the Next hook function is not called right away. 

1. Hooked program calls fopen("myfilename", "r") to open "myfilename" for reading. fopen() is part of the C runtime library. 
2. My API hook of CreateFileExW() is called. It is called HookCreateFileExW(). The first parameter is passed "myfilename". It calls Windows API GetSecurityInfo(). 

Code:

// Pseudocode 
HookCreateFileExW (LPWSTR pFileName, ...) 

   if ( lstrcmpiW(pFileName, L"myfilename") == 0 ) 
   { 
      // pFileName is "myfilename"; get it's security info 
      GetSecurityInfo(); 
      ... 

         // now pFilename is "netapi.dll" 
   } 




3. GetSecurityInfo() either directly or indirectly calls CreateFileExW(). This causes HookCreateFileExW() to be called again. This time, it passes the filename "netapi.dll" as the first parameter. BUT: the first parameter is a pointer to the same memory location as before; "netapi.dll" has overwritten "myfilename". So when the call to GetSecurityInfo() returns, pFileName is not "myfilename" but "netapi.dll". 

4. My hook is screwed up because the parameter has changed after the call to GetSecurityInfo. 


MORAL: Some Windows API's are NOT reentrant. Your hook can't safely call certain API's while it has been called by those same API's. Otherwise the API's might do things they weren't designed for, like reusing memory buffers before they are done, as GetSecurityInfo() used the same buffer that was used in the initial call to CreateFileExW. 

WORKAROUND: Once I found GetSecurityInfo() causes the filename to be overwritten, I preserve it myself: 

Code:

// Pseudocode 
HookCreateFileExW (LPWSTR pFileName, ...) 

   if ( lstrcmpiW(pFileName, L"myfilename") == 0 ) 
   { 
      // pFileName is "myfilename"; get it's security info 

      // preserve filename which is destroyed in call to GetSecurityInfo() 
      WCHAR szBuf[MAX_PATH]; 
      lstrcpyW (szBuf, pFileName); 
      GetSecurityInfo(); 
      ... 

         // now pFilename is "netapi.dll" 

         // restore filename 
         lstrcpyW (pFileName, szBuf); 


   } 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值