Установка хука с использованием трамплина
От: forston  
Дата: 05.06.09 05:38
Оценка:
Приветствую, возникла проблемка, не могу разобраться.
DLL инжектится в уже запущенный процесс — приложение пустышка вызывающее несколько раз MessageBoxW, с инжектом моей dll у функци трамплина затирается код на джамп назад в оригинальную функцию, у оригинальной функции затираются первые пять байт джампом на подставную. А вот с подставной проблема, не знаю почему но тело функции при дизасме заставлено int 3

сама dll`ka

#include <windows.h>
#include "detours.h"
#pragma comment(lib, "detours.lib")

extern "C" __declspec(dllexport) LRESULT CALLBACK dllfnc(int nCode, WPARAM wParam, LPARAM lParam);

BOOL _stdcall InterceptAPI(HMODULE hLocalModule, LPCWSTR c_szDllName, const char* c_szApiName, DWORD dwReplaced, DWORD dwTrampoline, int offset);
BOOL WINAPI _stdcall TrampolineMessageBoxW(HWND hWnd,LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
BOOL _stdcall TrampolineFunc(HWND hWnd,LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);

BOOL _stdcall TrampolineFunc(HWND hWnd,LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) {
    __asm{
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
    }
    return TRUE;
}

BOOL WINAPI _stdcall TrampolineMessageBoxW(HWND hWnd,LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) {
    TCHAR * str = L"WAS HOOKED";
    return TrampolineFunc(hWnd, str, str, uType);
}

BOOL _stdcall InterceptAPI(HMODULE hLocalModule, LPCWSTR c_szDllName, const char* c_szApiName, DWORD dwReplaced, DWORD dwTrampoline, int offset) {
    int i;
    DWORD dwOldProtect;
    DWORD dwAddressToIntercept = (DWORD)GetProcAddress(GetModuleHandle(c_szDllName), (char*)c_szApiName);

    BYTE *pbTargetCode = (BYTE *) dwAddressToIntercept;
    BYTE *pbReplaced = (BYTE *) dwReplaced;
    BYTE *pbTrampoline = (BYTE *) dwTrampoline;

    // Change the protection of the trampoline region
    // so that we can overwrite the first 5 + offset bytes.
    VirtualProtect((void *) dwTrampoline, 5+offset, PAGE_WRITECOPY, &dwOldProtect);

    for (i=0;i<offset;i++) {
        *pbTrampoline++ = *pbTargetCode++;
    }

    pbTargetCode = (BYTE *) dwAddressToIntercept;
    
    // Insert unconditional jump in the trampoline.
    *pbTrampoline++ = 0xE9;        // jump rel32
    *((signed int *)(pbTrampoline)) = (pbTargetCode+offset) - (pbTrampoline + 4);
    VirtualProtect((void *) dwTrampoline, 5+offset, PAGE_EXECUTE, &dwOldProtect);

    
    // Overwrite the first 5 bytes of the target function
    VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_WRITECOPY, &dwOldProtect);
    *pbTargetCode++ = 0xE9;        // jump rel32
    *((signed int *)(pbTargetCode)) = pbReplaced - (pbTargetCode +4);
    VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_EXECUTE, &dwOldProtect);

    FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
    return TRUE;
}


BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID reserved) {
    if(reason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls( hInst );
        InterceptAPI(hInst, L"user32.dll", "MessageBoxW", (DWORD)TrampolineMessageBoxW, (DWORD)TrampolineFunc, 0);
    }
    return TRUE;
}


05.06.09 11:28: Перенесено модератором из 'C/C++' — Хитрик Денис
winapi cplusplus
Re: Установка хука с использованием трамплина
От: DTB Россия  
Дата: 05.06.09 11:00
Оценка:
Здравствуйте, forston, Вы писали:

F>Приветствую, возникла проблемка, не могу разобраться.

F>DLL инжектится в уже запущенный процесс — приложение пустышка вызывающее несколько раз MessageBoxW, с инжектом моей dll у функци трамплина затирается код на джамп назад в оригинальную функцию, у оригинальной функции затираются первые пять байт джампом на подставную. А вот с подставной проблема, не знаю почему но тело функции при дизасме заставлено int 3

вот что у меня получилось

// Tramp.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "Tramp.h"


#include <windows.h>
//#include "detours.h"
//#pragma comment(lib, "detours.lib")

extern "C" __declspec(dllexport) LRESULT CALLBACK dllfnc(int nCode, WPARAM wParam, LPARAM lParam);

BOOL _stdcall InterceptAPI(HMODULE hLocalModule, LPCWSTR c_szDllName, const char* c_szApiName, DWORD dwReplaced, DWORD dwTrampoline, int offset);
BOOL WINAPI _stdcall TrampolineMessageBoxW(HWND hWnd,LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
//BOOL _stdcall TrampolineFunc(HWND hWnd,LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);

BOOL __declspec(naked) TrampolineFunc(HWND hWnd,LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) 
{
    __asm{
        nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
    }
    //return TRUE;
}

BOOL WINAPI _stdcall TrampolineMessageBoxW(HWND hWnd,LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) {
    TCHAR * str = L"WAS HOOKED";
    return TrampolineFunc(hWnd, str, str, uType);
}

BOOL _stdcall InterceptAPI(HMODULE hLocalModule, LPCWSTR c_szDllName, const char* c_szApiName, DWORD dwReplaced, DWORD dwTrampoline, int offset) {
    int i;
    DWORD dwOldProtect;
    HMODULE hm = GetModuleHandleW(c_szDllName);
    DWORD dwAddressToIntercept = (DWORD)GetProcAddress(hm, (char*)c_szApiName);

    BYTE *pbTargetCode = (BYTE *) dwAddressToIntercept;
    BYTE *pbReplaced = (BYTE *) dwReplaced;
    BYTE *pbTrampoline = (BYTE *) dwTrampoline;

    // Change the protection of the trampoline region
    // so that we can overwrite the first 5 + offset bytes.
    VirtualProtect((void *) dwTrampoline, 5+offset, PAGE_EXECUTE_READWRITE, &dwOldProtect);

    for (i=0;i<offset;i++) {
        *pbTrampoline++ = *pbTargetCode++;
    }

    pbTargetCode = (BYTE *) dwAddressToIntercept;

    // Insert unconditional jump in the trampoline.
    *pbTrampoline++ = 0xE9;        // jump rel32
    *((signed int *)(pbTrampoline)) = (pbTargetCode+offset) - (pbTrampoline + 4);
    VirtualProtect((void *) dwTrampoline, 5+offset, PAGE_EXECUTE_READWRITE, &dwOldProtect);


    // Overwrite the first 5 bytes of the target function
    VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);
    *pbTargetCode++ = 0xE9;        // jump rel32
    *((signed int *)(pbTargetCode)) = pbReplaced - (pbTargetCode +4);
    VirtualProtect((void *) dwAddressToIntercept, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);

    FlushInstructionCache(GetCurrentProcess(), NULL, NULL);
    return TRUE;
}


int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    InterceptAPI(hInstance, L"user32.dll", "MessageBoxW", (DWORD)TrampolineMessageBoxW, (DWORD)TrampolineFunc, 0);

    MessageBoxW(NULL, NULL, NULL, 0); // to load user32.dll into exe
    return 0;
}


и дальше проблема stack overflow, из за бесконечной рекурсии (прыгает не в оригинал, а сам в себя)
вообще еще будет много проблем не проще для обычных функций использовать перехват через таблицу экспорт/импорта? (по рихтеру, статья есть даже где-то тут на сайте)
Have fun...
Re[2]: Установка хука с использованием трамплина
От: forston  
Дата: 05.06.09 18:02
Оценка:
Здравствуйте, DTB, Вы писали:

DTB>и дальше проблема stack overflow, из за бесконечной рекурсии (прыгает не в оригинал, а сам в себя)

DTB>вообще еще будет много проблем:) не проще для обычных функций использовать перехват через таблицу экспорт/импорта? (по рихтеру, статья есть даже где-то тут на сайте)

Хм... Сейчас пройдусь в олле. через IAT не легче — во первых орет проактивка, что мешает работать, во вторых не все программы используют IAT, если к примеру мы вызываем функцию по GetProcAddress. Рихтера пролистал, устаревший код, который даже не работает. (поддержка win9x\me не нужна в моей либе)

Этот пример брался с INTEL`овского сайта, http://software.intel.com/en-us/articles/intercepting-system-api-calls/

Ед. проблема, вроде, которая может возникнуть — это если другой тред процесса вызовет функцию раньше чем мы ее заменим — но этого можно избежать стопнув все треды, до выполнения слайса с трамплином.

PS: извиняюсь за инклуды детурса ) забыл удалить, он естесвенно не нужен. Пробовал и его, но размер в 100+кб раздражает. То же самое что стрелять из пушки по комарам.
Re[3]: Установка хука с использованием трамплина
От: DTB Россия  
Дата: 05.06.09 18:45
Оценка:
Здравствуйте, forston, Вы писали:

F>Хм... Сейчас пройдусь в олле. через IAT не легче — во первых орет проактивка, что мешает работать, во вторых не все программы используют IAT, если к примеру мы вызываем функцию по GetProcAddress. Рихтера пролистал, устаревший код, который даже не работает. (поддержка win9x\me не нужна в моей либе)

зависит от сферы применения, в одном из моих проектов код рихтера вполне себе жизнеспособен (перехват пары стандартных функций), плюс его еще в том, что можно перехватывать одну и ту же функцию несколько раз, с трамплинами могут быть грабли. насчет проактивки, вроде никто из клиентов не жаловался

F>Этот пример брался с INTEL`овского сайта, http://software.intel.com/en-us/articles/intercepting-system-api-calls/

кривой код, ни проверок, и метод дубовый. могут быть проблемы с инструкциями в начале кода оригинальной функции, они не учитываются (для каждой функции длину трамплина нужно вычислять отдельно), т.е. код не универсальный

F>Ед. проблема, вроде, которая может возникнуть — это если другой тред процесса вызовет функцию раньше чем мы ее заменим — но этого можно избежать стопнув все треды, до выполнения слайса с трамплином.

да, в этом случае лучше стопать

F>PS: извиняюсь за инклуды детурса ) забыл удалить, он естесвенно не нужен. Пробовал и его, но размер в 100+кб раздражает. То же самое что стрелять из пушки по комарам.

+ нужна лицензия для коммерческого использования (точно не помню, для lite версии может и не надо), сама библиотечка неплохая
Have fun...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.