使用弯路钩住记事本中的文字
Posted
技术标签:
【中文标题】使用弯路钩住记事本中的文字【英文标题】:Using detours for hooking writing text in notepad 【发布时间】:2010-07-16 09:56:12 【问题描述】:我正在尝试使用 detours 来挂钩文本输出,例如在记事本中。
我写了以下代码。我不会在这里放所有代码,而是最重要的部分。
DLL 部分:
DLLEXPORT LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
if (nCode < 0)
return CallNextHookEx(0, nCode, wParam, lParam);
if (nCode == HCBT_ACTIVATE)
HWND hWnd = (HWND)wParam;
TCHAR szTemp[255];
GetWindowText(hWnd, szTemp, 255);
DetourTransactionBegin();
DetourUpdateThread(hWnd);
DetourAttach(&(PVOID&)Real_DrawText, Mine_DrawText);
DetourTransactionCommit();
DetourTransactionBegin();
DetourUpdateThread(hWnd);
DetourAttach(&(PVOID&)Real_DrawTextEx, Mine_DrawTextEx);
DetourTransactionCommit();
DetourTransactionBegin();
DetourUpdateThread(hWnd);
DetourAttach(&(PVOID&)Real_TextOut, Mine_TextOut);
DetourTransactionCommit();
DetourTransactionBegin();
DetourUpdateThread(hWnd);
DetourAttach(&(PVOID&)Real_ExtTextOut, Mine_ExtTextOut);
DetourTransactionCommit();
return 0;
客户端部分:
int main(int argc, char* argv[])
HOOKPROC hkprcSysMsg;
static HINSTANCE hinstDLL;
static HHOOK hhookSysMsg;
hinstDLL = LoadLibrary(TEXT("dllsample.dll"));
//cout << (hinstDLL == NULL);
hkprcSysMsg = (HOOKPROC)GetProcAddress(hinstDLL, "_CBTProc@12");
DWORD dw = GetLastError();
//cout << (hkprcSysMsg == NULL);
//cout << dw;
hhookSysMsg = SetWindowsHookEx(
WH_CBT,
hkprcSysMsg,
hinstDLL,
0);
//std::cout << (hhookSysMsg == NULL);
int i;
std::cin >> i;
问题是所有 4 个绘制文本的函数都没有被钩住。我做错了什么。我已经开始研究弯路,但在文档中没有找到我的问题的答案。
如果需要其他部分代码,我稍后会放在这里。
【问题讨论】:
【参考方案1】:DrawText 是一个宏,可以根据 UNICODE 预处理器设置转到 DrawTextW 或 DrawTextA。那么也许记事本正在调用一个,而您正在连接另一个?
我认为 DrawTextA 转发到 DrawTextW,所以尝试直接挂钩。
编辑,下面的示例代码,在顶部使用命令编译。运行 main.exe。运行 sysinternals 调试视图以查看输出。
代码编译成一个名为 t4.dll 的 dll 和一个名为 main.exe 的可执行文件,当您运行 main.exe 时,该 dll 通过 SetWindowHookEx 调用加载到每个正在运行的进程中,然后在每个进程上调用 CBTProc 函数在适当的时候线程。
/* t4.cpp
cl.exe /Zi /EHa /c /DUNICODE /D_UNICODE /I "c:/program files/Microsoft Research/Detours Express 2.1/include/" t4.cpp
link /DLL /DEBUG /LIBPATH:"c:/Program Files/Microsoft Visual Studio 10.0/VC/lib" /LIBPATH:"C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib" /LIBPATH:"c:/program files/Microsoft Research/Detours Express 2.1/lib" t4.obj user32.lib gdi32.lib
link /OUT:main.exe /DEBUG /LIBPATH:"c:/Program Files/Microsoft Visual Studio 10.0/VC/lib" /LIBPATH:"C:\Program Files\Microsoft SDKs\Windows\v7.0A\Lib" /LIBPATH:"c:/program files/Microsoft Research/Detours Express 2.1/lib" t4.obj user32.lib gdi32.lib
*/
#include <iostream>
#define NOMINMAX
#include <string.h>
#include <tchar.h>
#include <windows.h>
#include "detours.h"
#pragma comment(lib, "detours")
#pragma comment(lib, "detoured")
int (WINAPI *Real_DrawText)(HDC hDC, LPCTSTR lpchText, int, LPRECT, UINT) = DrawText;
BOOL (WINAPI *Real_TextOut)(
__in HDC hdc,
__in int nXStart,
__in int nYStart,
__in LPCTSTR lpString,
__in int cbString
) = TextOut;
int (WINAPI *Real_DrawTextEx)(
__in HDC hdc,
__inout LPTSTR lpchText,
__in int cchText,
__inout LPRECT lprc,
__in UINT dwDTFormat,
__in LPDRAWTEXTPARAMS lpDTParams
) = DrawTextEx;
BOOL (WINAPI *Real_ExtTextOut)(
__in HDC hdc,
__in int X,
__in int Y,
__in UINT fuOptions,
__in const RECT *lprc,
__in LPCTSTR lpString,
__in UINT cbCount,
__in const INT *lpDx
) = ExtTextOut;
int WINAPI Mine_DrawText(
__in HDC hDC,
__inout LPCTSTR lpchText,
__in int nCount,
__inout LPRECT lpRect,
__in UINT uFormat
)
OutputDebugString(TEXT("DrawText"));
OutputDebugString(lpchText);
return Real_DrawText(hDC, lpchText, nCount, lpRect, uFormat);
BOOL WINAPI Mine_TextOut(
__in HDC hdc,
__in int nXStart,
__in int nYStart,
__in LPCTSTR lpString,
__in int cbString
)
OutputDebugString(TEXT("TextOut"));
OutputDebugString(lpString);
return Real_TextOut(hdc, nXStart, nYStart, lpString, cbString);
int WINAPI Mine_DrawTextEx(
__in HDC hdc,
__inout LPTSTR lpchText,
__in int cchText,
__inout LPRECT lprc,
__in UINT dwDTFormat,
__in LPDRAWTEXTPARAMS lpDTParams
)
OutputDebugString(TEXT("DrawTextEx"));
OutputDebugString(lpchText);
return Real_DrawTextEx(hdc, lpchText, cchText, lprc, dwDTFormat, lpDTParams);
BOOL WINAPI Mine_ExtTextOut(
__in HDC hdc,
__in int X,
__in int Y,
__in UINT fuOptions,
__in const RECT *lprc,
__in LPCTSTR lpString,
__in UINT cbCount,
__in const INT *lpDx
)
OutputDebugString(TEXT("ExtTextOut"));
OutputDebugString(lpString);
return Real_ExtTextOut( hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx );
#define DLLEXPORT extern "C" __declspec(dllexport)
static DWORD dwTlsIndex; // address of shared memory
// Stores a DWORD in thread local storage
BOOL WINAPI StoreData(DWORD dw)
LPVOID lpvData;
DWORD * pData; // The stored memory pointer
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData == NULL)
lpvData = (LPVOID) LocalAlloc(LPTR, 256);
if (lpvData == NULL)
return FALSE;
if (!TlsSetValue(dwTlsIndex, lpvData))
return FALSE;
pData = (DWORD *) lpvData; // Cast to my data type.
// In this example, it is only a pointer to a DWORD
// but it can be a structure pointer to contain more complicated data.
(*pData) = dw;
return TRUE;
// Retrieve a DWORD from thread local storage
BOOL WINAPI GetData(DWORD *pdw)
LPVOID lpvData;
DWORD * pData; // The stored memory pointer
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData == NULL)
return FALSE;
pData = (DWORD *) lpvData;
(*pdw) = (*pData);
return TRUE;
DLLEXPORT LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
if (nCode < 0)
return CallNextHookEx(0, nCode, wParam, lParam);
// Get a flag indicating if we're already detoured.
DWORD detoured=false;
GetData(&detoured);
// If the window is activating and we're not detoured...
if (nCode == HCBT_ACTIVATE && !detoured)
OutputDebugString(TEXT("CBTProc"));
HWND hWnd = (HWND)wParam;
// get window title
TCHAR szTemp[256];
int rc = GetWindowText(hWnd, szTemp, 255);
if (rc != 0)
OutputDebugString(szTemp);
// hook notepad functions.
if (_tcsstr(szTemp, TEXT("Notepad"))!=0)
OutputDebugString(TEXT("Detouring"));
HANDLE hThread = GetCurrentThread();
DetourTransactionBegin();
DetourUpdateThread(hThread);
DetourAttach(&(PVOID&)Real_DrawText, Mine_DrawText);
DetourAttach(&(PVOID&)Real_TextOut, Mine_TextOut);
DetourAttach(&(PVOID&)Real_DrawTextEx, Mine_DrawTextEx);
DetourAttach(&(PVOID&)Real_ExtTextOut, Mine_ExtTextOut);
DetourTransactionCommit();
StoreData(true);
return 0;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle
DWORD fdwReason, // reason called
LPVOID lpvReserved) // reserved
LPVOID lpvData;
BOOL fIgnore;
switch (fdwReason)
// The DLL is loading due to process
// initialization or a call to LoadLibrary.
case DLL_PROCESS_ATTACH:
OutputDebugString(TEXT("DLL_PROCESS_ATTACH"));
// Allocate a TLS index.
if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
return FALSE;
// No break: Initialize the index for first thread.
// The attached process creates a new thread.
case DLL_THREAD_ATTACH:
OutputDebugString(TEXT("DLL_THREAD_ATTACH"));
// Initialize the TLS index for this thread.
lpvData = (LPVOID) LocalAlloc(LPTR, 256);
if (lpvData != NULL)
fIgnore = TlsSetValue(dwTlsIndex, lpvData);
break;
// The thread of the attached process terminates.
case DLL_THREAD_DETACH:
OutputDebugString(TEXT("DLL_THREAD_DETACH"));
DWORD detoured=false;
GetData(&detoured);
if(detoured)
OutputDebugString(TEXT("Un-Detouring"));
HANDLE hThread = GetCurrentThread();
DetourTransactionBegin();
DetourUpdateThread(hThread);
DetourDetach(&(PVOID&)Real_DrawText, Mine_DrawText);
DetourDetach(&(PVOID&)Real_TextOut, Mine_TextOut);
DetourDetach(&(PVOID&)Real_DrawTextEx, Mine_DrawTextEx);
DetourDetach(&(PVOID&)Real_ExtTextOut, Mine_ExtTextOut);
DetourTransactionCommit();
// Release the allocated memory for this thread.
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
LocalFree((HLOCAL) lpvData);
break;
// DLL unload due to process termination or FreeLibrary.
case DLL_PROCESS_DETACH:
OutputDebugString(TEXT("DLL_PROCESS_DETACH"));
// Release the allocated memory for this thread.
lpvData = TlsGetValue(dwTlsIndex);
if (lpvData != NULL)
LocalFree((HLOCAL) lpvData);
// Release the TLS index.
TlsFree(dwTlsIndex);
break;
default:
break;
return TRUE;
int main(int argc, char* argv[])
HOOKPROC hkprcSysMsg;
HHOOK hhookSysMsg;
HINSTANCE dll = LoadLibrary(TEXT("t4.dll"));
hkprcSysMsg = (HOOKPROC)GetProcAddress(dll, "_CBTProc@12");
DWORD dw = GetLastError();
hhookSysMsg = SetWindowsHookEx(
WH_CBT,
hkprcSysMsg,
dll,
0);
int i;
std::cin >> i;
UnhookWindowsHookEx(hhookSysMsg);
【讨论】:
@timlendus:DetourUpdateThread 行看起来有点滑稽。通常它们会像 DetourUpdateThread(::GetCurrentThread());以上是关于使用弯路钩住记事本中的文字的主要内容,如果未能解决你的问题,请参考以下文章