Перехват функции в vtable

Тема в разделе "WASM.BEGINNERS", создана пользователем InTRUEdeR, 7 июл 2008.

  1. InTRUEdeR

    InTRUEdeR New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2007
    Сообщения:
    13
    вот вся длл моя.

    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3.  
    4. const int NumberOfOpcodes=8;
    5.  
    6. BOOL Detour(void);
    7. BOOL Retour(void);
    8. void MyFunction(void);
    9. void *DetourClassFunc(BYTE *src, const BYTE *dst, const int len);
    10. void RetourClassFunc(BYTE *src, BYTE *restore, const int len);
    11. void *VTableFunction(void **VTabEntry, DWORD index);
    12.  
    13. void *OldFunctionAddress;
    14.  
    15. void **VTable;
    16. void *bytes;
    17.  
    18. INT WINAPI DllMain
    19. (
    20.     HANDLE hinstDLL,
    21.     ULONG fdwReason,
    22.     LPVOID lpvReserved
    23. )
    24. {
    25.     switch (fdwReason)
    26.     {
    27.         case DLL_PROCESS_ATTACH:
    28.             if (!Detour())
    29.             {
    30.                 return FALSE;
    31.             }
    32.             break;
    33.  
    34.         case DLL_PROCESS_DETACH:
    35.             if(!Retour())
    36.                 return FALSE;
    37.             break;
    38.     }
    39.     return TRUE;
    40. }
    41.  
    42. BOOL Detour(void)
    43. {
    44.     HMODULE hModule;
    45.     hModule = GetModuleHandle("Library.dll");
    46.     VTable = (VOID **)((DWORD)hModule + 0xACA08);
    47.     OldFunctionAddress = VTableFunction(VTable,2);
    48.     bytes = DetourClassFunc((BYTE *)OldFunctionAddress, (BYTE *)MyFunction, NumberOfOpcodes);
    49.     return TRUE;
    50. }
    51.  
    52. BOOL Retour(void)
    53. {
    54.     RetourClassFunc((BYTE *)OldFunctionAddress, (BYTE *)bytes, NumberOfOpcodes);
    55.     return TRUE;
    56. }
    57.  
    58. VOID MyFunction()
    59. {
    60.     MessageBox(NULL,"Hello from MyFunction!","OK!",MB_OK);
    61. }
    62.  
    63. void *DetourClassFunc(BYTE *src, const BYTE *dst, const int len)
    64. {
    65.     int i;
    66.     BYTE *jmp = (BYTE*)malloc(len+8);
    67.    
    68.     DWORD dwBack;
    69.    
    70.     VirtualProtect(src, len, PAGE_READWRITE, &dwBack);
    71.     memcpy(jmp+3, src, len);
    72.    
    73.     // calculate callback function call
    74.     jmp[0] = 0x58;                          // pop eax
    75.     jmp[1] = 0x59;                          // pop ecx
    76.     jmp[2] = 0x50;                          // push eax
    77.     jmp[len+3] = 0xE9;                      // jmp
    78.     *(DWORD*)(jmp+len+4) = (DWORD)((src+len) - (jmp+len+3)) - 5;
    79.    
    80.     // detour source function call
    81.     src[0] = 0x58;                          // pop eax;
    82.     src[1] = 0x51;                          // push ecx
    83.     src[2] = 0x50;                          // push eax
    84.     src[3] = 0xE9;                          // jmp
    85.     *(DWORD*)(src+4) = (DWORD)(dst - (src+3)) - 5;
    86.    
    87.     for( i=8; i < len; i++ )
    88.         src[i] = 0x90;
    89.    
    90.     VirtualProtect(src, len, dwBack, &dwBack);
    91.    
    92.     return jmp;
    93. }
    94.  
    95. void RetourClassFunc(BYTE *src, BYTE *restore, const int len)
    96. {
    97.     DWORD dwBack;
    98.     VirtualProtect(src, len, PAGE_READWRITE, &dwBack);
    99.     memcpy(src, restore+3, len);
    100.    
    101.     restore[3] = 0xE9;
    102.     *(DWORD*)(restore+4) = (DWORD)(src - (restore+3)) - 5;
    103.    
    104.     VirtualProtect(src, len, dwBack, &dwBack);
    105. }
    106.  
    107. void *VTableFunction(void **VTabEntry, DWORD index)
    108. {
    109.     return *(void **)((DWORD)VTabEntry + index*4);
    110. }
     
  2. mikityak

    mikityak Забанен

    Публикаций:
    0
    Регистрация:
    5 авг 2007
    Сообщения:
    160
    Ну а почену не хочиш.. скинуть все и ту Длл которую хукаеш.. мне интересно посмотреть
    на такой вариант хука.. чем тебе тот не подхидит.. проверен получилса.. стати подсоединять тя может сама винда.. (я несказал што програмлю сильно, но делать неф..
    вот бы посмотрел.. [​IMG]) ну как хочиш.. сам пока писал хук 4 раза все сначала нада было переделывать..

    http://www.ring3circus.com/source/direct3d_9_hook.cpp чем плох вариант ?
     
  3. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Интересно, раз идет такая жесткая привязка к адресу, почему бы просто не взять конкретный адрес интересующей ф-ии в vftable и не подменить его на свой? Т.е. просто скопировать значение по адресу 100ACA10 и записать адрес своей ф-ии в этот же адрес.
     
  4. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    _mikityak_
    Первый раз тут смайлики вижу..
     
  5. InTRUEdeR

    InTRUEdeR New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2007
    Сообщения:
    13
    Mika0x65
    я ж говорю, было принципиально использование DetourClassFunc...
    поменял адреса, не работает... точнее результата не вижу. наверное программа при загрузке сразу адреса функций получает, а потом использует. И инжектиться и изменять что-либо уже бестолку :dntknw:
     
  6. mikityak

    mikityak Забанен

    Публикаций:
    0
    Регистрация:
    5 авг 2007
    Сообщения:
    160
    InTRUEdeR
    Не влез так и всуть всего.. но может вылетаеш ты братела со своим перехватом.. [​IMG]ты хоть видиш што происходит у тебя в нутри, незнаю
    я к примеру Олькой смог посмотреть когда гнал с етими Инжектор...
    ладно надоело [​IMG].. больше не буду срать своим кревым русским.. [​IMG]
     
  7. InTRUEdeR

    InTRUEdeR New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2007
    Сообщения:
    13
    _mikityak_, вижу что внутри получаются нужные мне адреса и их замены. сейчас просто не хочет срабатывать моя функция. варианта два: или перехватываемая функция никогда не вызывается или вызывается по ранее вычисленному адресу, не обращая внимания на то, что я заменил адрес...
     
  8. mikityak

    mikityak Забанен

    Публикаций:
    0
    Регистрация:
    5 авг 2007
    Сообщения:
    160
    [​IMG] позно ловиш.. яш сказал тутше пущай винда ставит хук..
    [​IMG] просто не хочет срабатывать [​IMG] извени в лом разбиратса когданибуть, посмотрим твой вариант хука..

    мой ставим

    Код (Text):
    1. void __stdcall wglSwapBuffers_My(HDC hDC)
    2. {
    3. ...
    4.         WriteHook(address_wglSwapBuffers, backup_wglSwapBuffers);
    5.         (reinterpret_cast<type_wglSwapBuffers> (address_wglSwapBuffers))(hDC);
    6.         WriteHook(address_wglSwapBuffers, patch_wglSwapBuffers);
    7. ...
    8. только што возвратил.. назад работу хукнотой функцыи..
    9. }
    последний раз ломал голову тем што эта гадость которую хачу хукнуть.. выгружаетса и снова загружаетса прогой которая ее использует.. при старте [​IMG]
     
  9. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    InTRUEdeR
    У тебя же начало vtable по смещению 0xACA04:
    Код (Text):
    1. 0000:100ACA04                          ; Exported entry 672. ??_7CButton@@6B@
    2. 0000:100ACA04                                          public ??_7CButton@@6B@
    3. 0000:100ACA04                          ; const CButton::`vftable'
    А ты используешь 0xACA08:
    Код (Text):
    1.     VTable = (VOID **)((DWORD)hModule + 0xACA08);
    2.     OldFunctionAddress = VTableFunction(VTable,2);
    Т.е. получаешь адрес четвёртой функции из vtable (адрес CControlBase::Create(long)). Неужели так и задумано?


    Вообще странно. Не должно быть таких адресов. Там по идее должно быть число (Базовый_Адрес_Dll + 0x28360).


    Конечно, ничего не мешает ей это делать, но один оценил бы это либо как бессмысленные расходы ресурсов, либо как какой-то хак. Так что маловероятно.



    Mika0x65
    Как самый первый же!
     
  10. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Sol_Ksacap
    Если не ошибаюсь, то в общем случае указатель на vtable идет после последнего члена класса, в котором объявлен первый виртуальный метод. Самым первым он будет в том случае, когда класс является наследником некого базового класса с виртуальными методами, но без полей (членов), как например TObject в VCL. Объявляемые в потомках дополнительные члены идут после указателя на vtable, поэтому в итоге он оказывается либо в самом начале (если наследование идет от виртуального "пустого" класса) или в общем случае где-то в середине структуры класса
     
  11. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    А-ха. Похоже, это Борланд такое генерирует, да? Просто компилятор от MS всегда стремится сделать указатель на vtable первым членом класса.
    Интересно, запихнёт ли VS2k8 указатель на vtable в середину объекта в следующем случае:
    Код (Text):
    1. class A
    2. {
    3. public:
    4.     int a1, a2;
    5.     A(): a1(0xAAAAaaa1) { a2 = 0xAAAAaaa2; };
    6. };
    7.  
    8. class B: public A
    9. {
    10. public:
    11.     int b1, b2;
    12.     B(): b1(0xBBBBbbb1) { b2 = 0xBBBBbbb2; };
    13.     virtual int __cdecl dummy1()     { return 1; };
    14.     virtual int __cdecl dummy2(int) { return 2; };
    15. };
    16.  
    17.  
    18. int main(int, int, int, int)
    19. {
    20.     B b;
    21. }
    ...Нет, не запихнул. Вместо этого компилятор создал родительский объект внутри дочернего %)
    [​IMG]
     
  12. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ну понятно, что если классы объявлены в одном модуле (h-файле), то компилятор может "запихнуть" vtable в начало. А если в разных модулях, которые могут использоваться в разных прогах или dll ? Тут уж логично или всегда резервировать место под vtable независимо от наличия виртуальных методов в классе или уж вставлять его "как придется" при первом объявлении вирт.метода.
     
  13. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    Ммм... Ведь чтобы произошло наследование, компилятор должен видеть объявление родительского класса.
    Т.е. пусть класс 'A' реализован в dll, а класс 'B', наследующий класс 'A' - в exe-файле. При создании exe-файла компилятор видит, как объявлен класс 'A'; а мы видим, что единственная деталь, которая изменяется при кодогенерации - конструктор 'A', вызывающийся из dll.

    Понимаем хотя, что всё это ничего не значит - ибо это лишь детали реализации наследования одним конкретным компилятором...


    InTRUEdeR
    Ну как? Можешь попробовать под отладчиком вписать по адресу (Адрес_Загрузки_Dll + 0xACA10) заведомо левое значение - например, 0x0000FFFF. И если прога упадёт при вызове Create, то ты будешь знать, что перехват таким способом возможен ;)