Я экспериментирую на Detours.Захват DrawString в dll не работает
Прежде всего, у меня есть ForHook.cpp, который использует gdiplus DrawString для печати «Hello».
VOID OnPaint(HDC hdc)
{
Graphics graphics(hdc);
FontFamily fontFamily(L"Times New Roman");
Font font(&fontFamily, 24, FontStyleRegular, UnitPixel);
PointF pointF(30.0f, 10.0f);
SolidBrush solidBrush(Color(255, 0, 0, 255));
graphics.DrawString(L"Hello", -1, &font, pointF, &solidBrush);
}
Я написал объезд код ForHook.cpp, это команда перехватывать DrawString, пишут «Ха-ха» в окне вместо «Привет». И это работает. Код, используемый для замены gdiplus DrawString:
class CDetour {
public:
static Gdiplus::Status(CDetour::*pDrawString)(const WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b);
Gdiplus::Status MyDrawString(WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b);
};
Gdiplus::Status CDetour::MyDrawString(WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b)
{
WCHAR* a = L"Haha!";
return (this->*pDrawString)(a, len, f, org, b);
}
Gdiplus::Status(CDetour::* CDetour::pDrawString)(const WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b) = (Gdiplus::Status(CDetour::*)(const WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b))&Graphics::DrawString;
объезд код:
Gdiplus::Status(CDetour::* pMyDrawString)(WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b) = &CDetour::MyDrawString;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)(CDetour::pDrawString), *(PBYTE*)&pMyDrawString);
DetourTransactionCommit();
Затем я перейду их библиотеки DLL и DLL нагрузки в ForHook.cpp. В, где я имел обыкновение объезд код:
LoadLibrary(TEXT("Mydll.dll"));
объезд код ставится под DllMain:
case DLL_PROCESS_ATTACH:
//detours
MessageBox(0, L"Process Attach", L"Info", MB_OK);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)(CDetour::pDrawString), *(PBYTE*)&pMyDrawString);
if (DetourTransactionCommit() == NO_ERROR)
{
//WCHAR buffer[15];
//_ultow_s(GetCurrentThreadId(), buffer, 15, 10);
MessageBox(0, L"Dll successfully injected.", L"Info", MB_OK);
//MessageBox(0, buffer, L"Info", MB_OK);
}
break;
И я использую detourdetach когда длл отдельностоящий:
case DLL_PROCESS_DETACH:
MessageBox(0, L"Process Detach", L"Info", MB_OK);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)(CDetour::pDrawString), *(PBYTE*)&pMyDrawString);
DetourTransactionCommit();
break;
Как Detours API будет не вызывается в ForHook.cpp, я также удалил #include <detours.h>
и #pragma comment(lib, "detours.lib)
.
Сложность в том, что dll прилагается, я проверил его с помощью Listdlls.exe. Dll находится под идентификатором процесса ForHook.exe. Но программа по-прежнему печатает «Привет» вместо «Ха-ха».
Почему это не работает? И как я могу это изменить?
dllmain.cpp:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <detours.h>
#include <gdiplus.h>
#include <windows.h>
#include <objidl.h>
using namespace Gdiplus;
#pragma comment (lib,"Gdiplus.lib")
#pragma comment(lib,"detours.lib")
//class __declspec(dllexport) CDetour
class CDetour
{
public:
static Gdiplus::Status(CDetour::*pDrawString)(const WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b);
Gdiplus::Status MyDrawString(WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b);
};
Gdiplus::Status CDetour::MyDrawString(WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b)
{
WCHAR* a = L"Haha!";
return (this->*pDrawString)(a, len, f, org, b);
}
DWORD GetMainThreadId(DWORD dwPid)
{
LPVOID lpTid;
_asm
{
mov eax, fs:[18h]
add eax, 36
mov[lpTid], eax
}
HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, dwPid);
if (hProcess == NULL)
return NULL;
DWORD dwTid;
if (ReadProcessMemory(hProcess, lpTid, &dwTid, sizeof(dwTid), NULL) == FALSE)
{
CloseHandle(hProcess);
return NULL;
}
CloseHandle(hProcess);
return dwTid;
}
Gdiplus::Status(CDetour::* CDetour::pDrawString)(const WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b) = (Gdiplus::Status(CDetour::*)(const WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b))&Graphics::DrawString;
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
//MessageBox(0, TEXT("Why?"), TEXT("Info"), MB_OK);
Gdiplus::Status(CDetour:: *pMyDrawString)(WCHAR* s, INT len, const Gdiplus::Font *f, const Gdiplus::PointF& org, const Gdiplus::Brush* b) = &CDetour::MyDrawString;
//WCHAR buf[15];
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
//MessageBox(0, L"Process Attach", L"Info", MB_OK);
//_ultow_s(GetMainThreadId(GetCurrentProcessId()), buf, 15, 10);
//MessageBox(0, buf, L"Info", MB_OK);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)(CDetour::pDrawString), *(PBYTE*)&pMyDrawString);
if (DetourTransactionCommit() == NO_ERROR)
{
WCHAR buffer[15];
_ultow_s(GetCurrentThreadId(), buffer, 15, 10);
//MessageBox(0, L"Dll successfully injected.", L"Info", MB_OK);
MessageBox(0, buffer, L"Info", MB_OK);
}
break;
case DLL_THREAD_ATTACH:
//detours
//MessageBox(0, L"Thread Attach", L"Info", MB_OK);
//_ultow_s(GetMainThreadId(GetCurrentProcessId()), buf, 15, 10);
//MessageBox(0, buf, L"Info", MB_OK);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)(CDetour::pDrawString), *(PBYTE*)&pMyDrawString);
if (DetourTransactionCommit() == NO_ERROR)
{
WCHAR buffer[15];
_ultow_s(GetCurrentThreadId(), buffer, 15, 10);
//MessageBox(0, L"Dll successfully injected.", L"Info", MB_OK);
MessageBox(0, buffer, L"Info", MB_OK);
}
break;
case DLL_THREAD_DETACH:
//MessageBox(0, L"Thread Detach", L"Info", MB_OK);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)(CDetour::pDrawString), *(PBYTE*)&pMyDrawString);
DetourTransactionCommit();
break;
case DLL_PROCESS_DETACH:
//MessageBox(0, L"Proccess Detach", L"Info", MB_OK);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)(CDetour::pDrawString), *(PBYTE*)&pMyDrawString);
DetourTransactionCommit();
break;
}
return TRUE;
}
Спасибо за быстрый ответ. –
Я думал, что это может быть не одна и та же. Таким образом, вы могли видеть, что в моем DLL_PROCESS_ATTACH я попытался вывести текущий идентификатор потока. И я также выпустил тот же код сразу после загрузки dll в ForHook.cpp. Идентификаторы потоков одинаковы. –
Я принял ваш совет, переместил код в DLL_THREAD_ATTACH, это не сработало. –