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

被折叠的 条评论
为什么被折叠?



