2014-11-06 2 views
0

Я экспериментирую на 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; 
} 

ответ

0

прежде всего, вы хотите, чтобы попытаться избежать делать НИЧЕГО в DllMain(). Во-вторых, вы устанавливаете это в PROCESS attach, когда вы, вероятно, действительно хотите вызвать его в DLL_THREAD_ATTACH. Если вы поместите какие-то визуальные маркеры в свой код, вы обнаружите, что при загрузке DLL Windows делает некоторые вещи WHACKY. Вы увидите ProcessAttach (Ok, Sure ...), Затем вы увидите ThreadAttach() ... OK ... Но тогда вы увидите как ThreadDetatch(), и когда ваше приложение ЗАКРЫТЬ, вы будете получать PROCESS_DETATCH, но не THREAD_DETATCH ...

Весьма вероятно, что информация Thread вы настраиваете в PROCESS_ATTACH является НЕ нить, что на самом деле делает работу ... Переместить свой код THREAD_ATTACH, и это, вероятно, сработает. Код, скорее всего, использует TLS, еще одну страшную технологию, поскольку DLL идет ...

+0

Спасибо за быстрый ответ. –

+0

Я думал, что это может быть не одна и та же. Таким образом, вы могли видеть, что в моем DLL_PROCESS_ATTACH я попытался вывести текущий идентификатор потока. И я также выпустил тот же код сразу после загрузки dll в ForHook.cpp. Идентификаторы потоков одинаковы. –

+0

Я принял ваш совет, переместил код в DLL_THREAD_ATTACH, это не сработало. –

Смежные вопросы