Перехваты импорта через ядро

Тема в разделе "WASM.NT.KERNEL", создана пользователем ntcdm, 13 сен 2010.

  1. ntcdm

    ntcdm New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2007
    Сообщения:
    247
    Есть некий процесс A.EXE, который импортирует и использует функцию msvcrt!memset - Мне нужно перехватить вызов этой функции и специальным образом заполнять буффер.

    Решил воспользоватся методом перехвата IAT, описанным в книжке "Rootkits:subverting the Windows Kernel" - смешанный подход к захвату:
    Код (Text):
    1. NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,
    2.                      IN PUNICODE_STRING theRegistryPath)
    3. {
    4.     NTSTATUS ntStatus;
    5.     gb_Hooked = FALSE; // We have not hooked yet
    6.  
    7.     ntStatus = PsSetLoadImageNotifyRoutine(MyImageLoadNotify);
    8.  
    9.     return ntStatus;
    10. }
    11.  
    12. /////////////////////////////////////////////////////////
    13. // MyImageLoadNotify gets called when an image is loaded
    14. // into kernel or user space. At this point, you could
    15. // filter your hook based on ProcessId or on the name of
    16. // of the image.
    17. VOID MyImageLoadNotify(IN PUNICODE_STRING  FullImageName,
    18.                        IN HANDLE  ProcessId, // Process where image is mapped
    19.                        IN PIMAGE_INFO  ImageInfo)
    20. {
    21. //  UNICODE_STRING u_targetDLL;
    22.  
    23.     DbgPrint("Image name: %ws\n", FullImageName->Buffer);
    24.     // Setup the name of the DLL to target
    25. //  RtlInitUnicodeString(&u_targetDLL, L"\\WINDOWS\\system32\\kernel32.dll");
    26.  
    27. //  if (RtlCompareUnicodeString(FullImageName, &u_targetDLL, TRUE) == 0)
    28. //  {
    29.         HookImportsOfImage(ImageInfo->ImageBase, ProcessId);
    30. //  }
    31.  
    32. }
    33.  
    34.  
    35. NTSTATUS HookImportsOfImage(PIMAGE_DOS_HEADER image_addr, HANDLE h_proc)
    36. {
    37.     PIMAGE_DOS_HEADER dosHeader;
    38.     PIMAGE_NT_HEADERS pNTHeader;
    39.     PIMAGE_IMPORT_DESCRIPTOR importDesc;
    40.     PIMAGE_IMPORT_BY_NAME p_ibn;
    41.     DWORD importsStartRVA;
    42.     PDWORD pd_IAT, pd_INTO;
    43.     int count, index;
    44.     char *dll_name = NULL;
    45.     char *pc_dlltar = "kernel32.dll";
    46.     char *pc_fnctar = "GetProcAddress";
    47.     PMDL  p_mdl;
    48.     PDWORD MappedImTable;
    49.     DWORD d_sharedM = 0x7ffe0800;
    50.     DWORD d_sharedK = 0xffdf0800;
    51.  
    52.     // Little detour
    53.     unsigned char new_code[] = {
    54.         0x90,                          // NOP make INT 3 to see
    55.         0xb8, 0xff, 0xff, 0xff, 0xff,  // mov eax, 0xffffffff
    56.         0xff, 0xe0                     // jmp eax
    57.     };
    58.    
    59.     dosHeader = (PIMAGE_DOS_HEADER) image_addr;
    60.  
    61.     pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader,
    62.                                 dosHeader->e_lfanew );
    63.    
    64.     // First, verify that the e_lfanew field gave us a reasonable
    65.     // pointer, then verify the PE signature.
    66.     if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE )
    67.         return STATUS_INVALID_IMAGE_FORMAT;
    68.  
    69.     importsStartRVA = pNTHeader->OptionalHeader.DataDirectory
    70.                             [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    71.  
    72.     if (!importsStartRVA)
    73.         return STATUS_INVALID_IMAGE_FORMAT;
    74.  
    75.     importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (importsStartRVA + (DWORD) dosHeader);
    76.  
    77.     for (count = 0; importDesc[count].Characteristics != 0; count++)
    78.     {
    79.         dll_name = (char*) (importDesc[count].Name + (DWORD) dosHeader);
    80.                
    81.         pd_IAT = (PDWORD)(((DWORD) dosHeader) + (DWORD)importDesc[count].FirstThunk);
    82.         pd_INTO = (PDWORD)(((DWORD) dosHeader) + (DWORD)importDesc[count].OriginalFirstThunk);
    83.  
    84.         for (index = 0; pd_IAT[index] != 0; index++)
    85.         {
    86.             // If this is an import by ordinal the high
    87.             // bit is set
    88.             if ((pd_INTO[index] & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
    89.             {
    90.                 p_ibn = (PIMAGE_IMPORT_BY_NAME)(pd_INTO[index]+((DWORD) dosHeader));
    91.                 if ((_stricmp(dll_name, pc_dlltar) == 0) && \
    92.                     (strcmp(p_ibn->Name, pc_fnctar) == 0))
    93.                 {
    94.                     //DbgPrint("Imports from DLL: %s", dll_name);
    95.                     //DbgPrint(" Name: %s Address: %x\n", p_ibn->Name, pd_IAT[index]);     
    96.  
    97.                     // Use the trick you already learned to map a different
    98.                     // virtual address to the same physical page so no
    99.                     // permission problems.
    100.                     //
    101.                     // Map the memory into our domain so we can change the permissions on the MDL
    102.                     p_mdl = MmCreateMdl(NULL, &pd_IAT[index], 4);
    103.                     if(!p_mdl)
    104.                         return STATUS_UNSUCCESSFUL;
    105.  
    106.                     MmBuildMdlForNonPagedPool(p_mdl);
    107.  
    108.                     // Change the flags of the MDL
    109.                     p_mdl->MdlFlags = p_mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
    110.  
    111.                     MappedImTable = MmMapLockedPages(p_mdl, KernelMode);
    112.                    
    113.                     if (!gb_Hooked)
    114.                     {
    115.                         // Writing the raw opcodes to memory
    116.                         // used a kernel address that gets mapped
    117.                         // into the address space of all processes
    118.                         // thanks to Barnaby Jack
    119.                         RtlCopyMemory((PVOID)d_sharedK, new_code, 8);
    120.                         RtlCopyMemory((PVOID)(d_sharedK+2),(PVOID)&pd_IAT[index], 4);
    121.                         gb_Hooked = TRUE;
    122.                     }
    123.  
    124.                     // Offset to the "new function"
    125.                     *MappedImTable = d_sharedM;
    126.  
    127.                     // Free MDL
    128.                     MmUnmapLockedPages(MappedImTable, p_mdl);
    129.                     IoFreeMdl(p_mdl);
    130.  
    131.                 }
    132.             }
    133.         }
    134.     }
    135.     return STATUS_SUCCESS;
    136. }
    Проблема в том, что система настраивает импорты уже ПОСЛЕ того как моя функция отработала - соответсвтенно я ставлю хуки, а система потом их затирает. Кто нибудь сталкивался с подобной задачей, если да, то как решили ее?
     
  2. slesh

    slesh New Member

    Публикаций:
    0
    Регистрация:
    6 фев 2009
    Сообщения:
    214
    как вариант подготовить все вещи(в плане права доступа к памяти), затем перебить в PE заголовке EntryPoint для DLL. И как тока система всё загрузит и передаст управление на точку входа в DLL то ты поставишь нужные хуки куда надо, ну и потом передашь управление на оригинальную точку входа
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    ntcdm
    Импорт пользовательских модулей настраивается юзермодным лодером. При нотификации вы имеете только проекцию модуля. Все остальные действия с этой проекцией выполнит поток вернувшись в U-mode. Это очень плохой способ. Темболее патч. Решением может стать настройка импорта вручную(правка проекции эквивалентна изменению файла), таким образом, дабы после отработки загрузчика в импорте были адреса ваших хэндлеров.
     
  4. ntcdm

    ntcdm New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2007
    Сообщения:
    247
    Спасибо за подсказки. Я кстати тем временем пробовал похукать функцию memset через сплайс, так модуль msvcrt.dll во всех процессах поменялся (не на диске), естественно меня это не устраивает

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

    Clerk
    Скажи, а как можно настроить импорт вручную при загрузке чтобы там оказались адреса моих обработчиков? разве до этого я не делал то же самое?
    И что значит правка проекции эквивалентна изменению файла? что, файл на диске будет меняться если я в проекцию пишу? Может быть более подробно просветишь меня.
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    ntcdm
    Нужно делать это также как с файлом. Есть ли возможность изменить модуль на диске таким образом, дабы после загрузки его в IAT оказался ваш адрес ?
    Если биндинг то да, в остальных типах импорта это весьма проблемно.
     
  6. ntcdm

    ntcdm New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2007
    Сообщения:
    247
    самое простое что приходит в голову - изготовить мою Дллку в которой сделать функции-переходники кроме одной нужной мне, которую выполнить как фильтр. Затем при загрузке файла менять имя Длл-ки на мое. Но может быть есть какой-то простой способ, например чтобы лоадер не затирал импорт адресом импортирвемой функции при загрузке?
     
  7. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    ntcdm
    Есть эффективные способы связанные с исключениями. Но их не хотят юзать, так как для получения некоторых переменных необходимо выполнить парсинг ядра, который якобы считается не стабильным, вдобавок написать трап-процессинг для многих не представляется возможным, хотя там ничего сложного нет. Если разбить модуль(сделать инвалидными какието ссылки в нём), то при использовании их будут возникать исключения которые нужно откатать. При этом будут доступен целевой системный рантайм. Тоесть останов в теле лодера. Этого можно достичь также различными манипуляциями с загрузчиком(например фильтрация отладочного вывода http://www.wasm.ru/forum/viewtopic.php?id=38310, при этом отладочный стаб получает инфы более чем достаточно.

    Либо это перехват любой точки близко расположенной к коду настраивающему импорт(LdrpWalkImportDescriptor).

    upd.: Посмотрел. Происходит следующее:
    Код (Text):
    1. typedef struct _IMAGE_IMPORT_BY_NAME {
    2.     WORD    Hint;
    3.     BYTE    Name[1];
    4. } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
    5.  
    6. typedef struct _IMAGE_THUNK_DATA {
    7.     union {
    8.         PBYTE  ForwarderString;
    9.         PDWORD Function;
    10.         DWORD Ordinal;
    11.         PIMAGE_IMPORT_BY_NAME AddressOfData;
    12.     } u1;
    13. } IMAGE_THUNK_DATA;
    14. typedef IMAGE_THUNK_DATA * PIMAGE_THUNK_DATA;
    Код (Text):
    1. NTSTATUS
    2. LdrpSnapThunk (
    3.     IN PVOID DllBase,
    4.     IN PVOID ImageBase,
    5.     IN PIMAGE_THUNK_DATA OriginalThunk,
    6.     IN OUT PIMAGE_THUNK_DATA Thunk,
    7.     IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
    8.     IN ULONG ExportSize,
    9.     IN BOOLEAN StaticSnap,
    10.     IN PSZ DllName
    11.     )
    12.  
    13. /*++
    14.  
    15. Routine Description:
    16.  
    17.     This function snaps a thunk using the specified Export Section data.
    18.     If the section data does not support the thunk, then the thunk is
    19.     partially snapped (Dll field is still non-null, but snap address is
    20.     set).
    21.  
    22. Arguments:
    23.  
    24.     DllBase - Base of Dll.
    25.  
    26.     ImageBase - Base of image that contains the thunks to snap.
    27.  
    28.     Thunk - On input, supplies the thunk to snap.  When successfully
    29.         snapped, the function field is set to point to the address in
    30.         the DLL, and the DLL field is set to NULL.
    31.  
    32.     ExportDirectory - Supplies the Export Section data from a DLL.
    33.  
    34.     StaticSnap - If TRUE, then loader is attempting a static snap,
    35.                  and any ordinal/name lookup failure will be reported.
    36.  
    37. Return Value:
    38.  
    39.     STATUS_SUCCESS or STATUS_PROCEDURE_NOT_FOUND
    40.  
    41. --*/
    42.  
    43. {
    44.     BOOLEAN Ordinal;
    45.     USHORT OrdinalNumber;
    46.     ULONG OriginalOrdinalNumber;
    47.     PIMAGE_IMPORT_BY_NAME AddressOfData;
    48.     PULONG NameTableBase;
    49.     PUSHORT NameOrdinalTableBase;
    50.     PULONG Addr;
    51.     USHORT HintIndex;
    52.     NTSTATUS st;
    53.     PSZ ImportString;
    54.  
    55.     //
    56.     // Determine if snap is by name, or by ordinal
    57.     //
    58.  
    59.     Ordinal = (BOOLEAN)IMAGE_SNAP_BY_ORDINAL(OriginalThunk->u1.Ordinal);
    60.  
    61.     if (Ordinal) {
    62.         OriginalOrdinalNumber = (ULONG)IMAGE_ORDINAL(OriginalThunk->u1.Ordinal);
    63.         OrdinalNumber = (USHORT)(OriginalOrdinalNumber - ExportDirectory->Base);
    64.     } else {
    65.              //
    66.              // Change AddressOfData from an RVA to a VA.
    67.              //
    68.  
    69.              AddressOfData = (PIMAGE_IMPORT_BY_NAME)((ULONG_PTR)ImageBase + ((ULONG_PTR)OriginalThunk->u1.AddressOfData & 0xffffffff));
    70.              ImportString = (PSZ)AddressOfData->Name;
    71.  
    72.              //
    73.              // Lookup Name in NameTable
    74.              //
    75.  
    76.              NameTableBase = (PULONG)((ULONG_PTR)DllBase + (ULONG)ExportDirectory->AddressOfNames);
    77.              NameOrdinalTableBase = (PUSHORT)((ULONG_PTR)DllBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
    78.  
    79.              //
    80.              // Before dropping into binary search, see if
    81.              // the hint index results in a successful
    82.              // match. If the hint index is zero, then
    83.              // drop into binary search.
    84.              //
    85.  
    86.              HintIndex = AddressOfData->Hint;
    Делаем инвалидным RVA описателя импортируемой функции в IMAGE_THUNK_DATA. Тогда при обращении к описателю IMAGE_IMPORT_BY_NAME будет возникать #AV:
    Код (Text):
    1. HintIndex = AddressOfData->Hint
    ну или в коде:
    Код (Text):
    1. $ ==>    7C917BD1 _LdrpSnapThunk@32        mov edi,edi
    2. $+2      7C917BD3                          push ebp
    3. $+3      7C917BD4                          mov ebp,esp
    4. $+5      7C917BD6                          sub esp,28
    5. $+8      7C917BD9                          mov eax,dword ptr ss:[ebp+10]
    6. $+B      7C917BDC                          mov eax,dword ptr ds:[eax]
    7. $+D      7C917BDE                          mov edx,eax
    8. $+F      7C917BE0                          push ebx
    9. $+10     7C917BE1                          shr edx,1F
    10. $+13     7C917BE4                          push esi
    11. $+14     7C917BE5                          and dl,1
    12. $+17     7C917BE8                          push edi
    13. $+18     7C917BE9                          mov byte ptr ss:[ebp+13],dl
    14. $+1B     7C917BEC                          jnz ntdll.7C917EA4
    15. $+21     7C917BF2                          mov ecx,dword ptr ss:[ebp+C]
    16. $+24     7C917BF5                          test ecx,ecx
    17. $+26     7C917BF7                          je ntdll.7C93FEFC
    18. $+2C     7C917BFD                          mov esi,dword ptr ss:[ebp+18]
    19. $+2F     7C917C00                          mov edi,dword ptr ds:[esi+24]
    20. $+32     7C917C03                          add edi,dword ptr ss:[ebp+8]
    21. $+35     7C917C06                          add ecx,eax
    22. $+37     7C917C08                          mov eax,dword ptr ds:[esi+20]
    23. $+3A     7C917C0B                          add eax,dword ptr ss:[ebp+8]
    24. $+3D     7C917C0E                          lea ebx,dword ptr ds:[ecx+2]
    25. $+40     7C917C11                          movzx ecx,word ptr ds:[ecx] ; * #AV
    (Ecx:PIMAGE_IMPORT_BY_NAME, AddressOfData).
    Тогда можно указать свою ссылку, либо перехватить адрес возврата из функции и изменить IAT.
     
  8. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Както так(диспетчер исключений имеет контекст и выполняет примерно такой код, до этого хэндлер NtMapViewOfSection проецирует секцию и разбивает OriginalThunk, загружая туда инвалидное значение THUNK_SIGNATURE):
    Код (Text):
    1. ; typedef struct _IMAGE_IMPORT_BY_NAME {
    2. ;     WORD    Hint;
    3. ;     BYTE    Name[1];
    4. ; } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
    5.  
    6. ; typedef struct _IMAGE_THUNK_DATA {
    7. ;     union {
    8. ;         PBYTE  ForwarderString;
    9. ;         PDWORD Function;
    10. ;         DWORD Ordinal;
    11. ;         PIMAGE_IMPORT_BY_NAME AddressOfData;
    12. ;     } u1;
    13. ; } IMAGE_THUNK_DATA;
    14. ; typedef IMAGE_THUNK_DATA * PIMAGE_THUNK_DATA;
    15.  
    16. ; def. ldrsnap.c/ldrp.h
    17. ;
    18. ; NTSTATUS
    19. ; LdrpSnapThunk (
    20. ;    IN PVOID DllBase,
    21. ;    IN PVOID ImageBase,
    22. ;    IN PIMAGE_THUNK_DATA OriginalThunk,
    23. ;    IN OUT PIMAGE_THUNK_DATA Thunk,
    24. ;    IN PIMAGE_EXPORT_DIRECTORY ExportDirectory,
    25. ;    IN ULONG ExportSize,
    26. ;    IN BOOLEAN StaticSnap,
    27. ;    IN PSZ DllName
    28. ;    );
    29.  
    30. ; SFC
    31. ;
    32. STACK_FRAME struct
    33. Next        PVOID ? ; PSTACK_FRAME
    34. Ip      PVOID ?
    35. STACK_FRAME ends
    36. PSTACK_FRAME typedef ptr STACK_FRAME
    37.  
    38. ; ~ LdrpSnapThunk()
    39. ;
    40. LDRP_SNAP_THUNK_FRAME struct
    41. Sfc             STACK_FRAME <>  ; ~ LdrpSnapIAT()
    42. DllBase         PVOID ?
    43. ImageBase           PVOID ?
    44. OriginalThunk       PIMAGE_THUNK_DATA ?
    45. Thunk           PIMAGE_THUNK_DATA ?
    46. ExportDirectory PIMAGE_EXPORT_DIRECTORY ?
    47. ExportSize      ULONG ?
    48. StaticSnap      BOOLEAN ?
    49. DllName         PSTR ?
    50. LDRP_SNAP_THUNK_FRAME ends
    51. PLDRP_SNAP_THUNK_FRAME typedef ptr LDRP_SNAP_THUNK_FRAME
    52.  
    53. ; PCR
    54. PCR equ fs:
    55. PcPrcbData equ 00120H
    56.  
    57. ; PRCB
    58. PbCurrentThread equ 00004H
    59.  
    60. ; TEB
    61. TeStackBase equ 00004H
    62. TeStackLimit equ 00008H
    63.  
    64. ; CONTEXT
    65. CsEbp equ 000B4H
    66. CsEsp equ 000C4H
    67. CsEip equ 000B8H
    68. CsEax equ 000B0H
    69.  
    70. ; o IF, PASSIVE_LEVEL
    71. ;
    72. XcptDispatch proc uses ebx esi edi Context:PCONTEXT, DllBase:PVOID
    73.     %SEH_Prolog
    74.     mov ebx,Context
    75.     assume ebx:PCONTEXT
    76.    
    77.     invoke PsGetCurrentThread   ; PETHREAD
    78. ;   mov eax,PCR[PcPrcbData + PbCurrentThread]
    79.  
    80.     invoke PsGetThreadTeb, Eax  ; PTEB
    81.  
    82.     mov ecx,dword ptr [ebx + CsEsp] ; Esp
    83.     mov esi,dword ptr [ebx + CsEbp] ; Ebp
    84.     cmp ecx,dword ptr [eax + TeStackLimit]  ; Esp >= StackLimit
    85.     mov edx,esi
    86.     jb Error
    87.     sub edx,ecx ; Var's: (Ebp - Esp)
    88.     jna Error       ; Ebp > Esp
    89. ; Def. 0x28
    90.     cmp edx,10H ; Min Var's: Ebp >= Esp + 10H
    91.     jb Error
    92.     lea ecx,[esi + sizeof(LDRP_SNAP_THUNK_FRAME)]
    93.     cmp edx,40H ; Max Var's: Ebp <= Esp + 40H
    94.     ja Error
    95.     cmp ecx,dword ptr [eax + TeStackBase]   ; Ebp + sizeof(Arg's) < StackBase
    96.     jnb Error
    97.  
    98.     assume esi:PLDRP_SNAP_THUNK_FRAME
    99.    
    100.     mov eax,DllBase ; msvcrt.dll
    101.     cmp [esi].DllBase,eax
    102.     jne Error
    103.  
    104.     cmp [esi].OriginalThunk,THUNK_SIGNATURE ; Magic
    105.     jne Error
    106.    
    107.     invoke RtlImageNtHeader, [esi].ImageBase
    108.     test eax,eax    ; PIMAGE_NT_HEADERS
    109.     jz Error
    110.    
    111.     mov eax,[esi].ImageBase
    112.     add eax,[esi].Thunk     ; PIMAGE_IMPORT_BY_NAME
    113.     add eax,2   ; IMAGE_IMPORT_BY_NAME.Name
    114.     invoke ValidateImportByName, Eax
    115.     test eax,eax    ; PNEW_ENTRY(Handler)
    116.     mov ecx,[esi].Thunk
    117.     jz Error
    118.     mov dword ptr [ecx],eax
    119.    
    120.     mov edx,[esi].Sfc.Ip    ; Eip
    121.     mov ecx,[esi].Sfc.Next  ; Ebp
    122.     add esi,sizeof(LDRP_SNAP_THUNK_FRAME)   ; Esp
    123.     mov dword ptr [ebx + CsEax],STATUS_SUCCESS
    124.     mov dword ptr [ebx + CsEip],edx
    125.     mov dword ptr [ebx + CsEbp],ecx
    126.     mov dword ptr [ebx + CsEsp],esi
    127.     ; Нужно восстановить регистры Ebx, Esi и Edi, тут упрощённо.
    128.     xor eax,eax
    129. Exit:
    130.     %SEH_Epilog
    131.     ret
    132. Error:
    133.     mov eax,STATUS_UNSUCCESSFUL
    134.     jmp Exit
    135. XcptDispatch endp
    В теории должно работать.
     
  9. dfrsa

    dfrsa New Member

    Публикаций:
    0
    Регистрация:
    5 янв 2010
    Сообщения:
    88
    используйте APC без форсированной доставки
     
  10. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    dfrsa
    APC механизм асинхронный. Тоесть она будет доставлена при возврате из сервиса(NtMapViewOfSection), либо после того как загрузчик отработает http://www.wasm.ru/forum/viewtopic.php?id=38310. Если при возврате из сервиса, то это ничего не даёт. А если при возврате из загрузчика, то тут и APC не нужна - всеголишь изменить ссылку на стартап код в контексте текущего потока(Eip/Eax). APC использовать в данном случае не приемлимо. Вобще наверно можно использовать решение "в лоб" - создать свой дескриптор(IMAGE_IMPORT_DESCRIPTOR) и инициализировать TimeDateStamp, дабы адрес не менялся.
     
  11. ntcdm

    ntcdm New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2007
    Сообщения:
    247
    Я просто ищу наиболее простой способ, так чтобы он в будущем был переносим и на платформу x64.

    Пока что мне нравится идея с Bound Import, но как же мне похукать функцию через него - пока не сообразил.
     
  12. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Перенастроить импорт. Тоесть например может не хватать места для нового дескриптора. Он будет описывать один вход в IAT. Проверки принадлежности ссылок модулю сведены к минимому, адрес таблицы импорта вроде не проверяется, тогда её можно переместить за пределы модуля, например в приватную память. Попробую в юзермоде сделать.
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Может лучше изменить адрес функции в таблице экспорта ?
    Тогда при импорте будет загружаться ссылка на хэндлер. При динамическом импорте также.
     
  14. ntcdm

    ntcdm New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2007
    Сообщения:
    247
    Я до этого хукал сплайсом код функции самой ДЛЛки - так он менялся во всех процессах.

    А как же мне изменить экспорт для этой ДЛЛки только в данном процессе?
     
  15. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Файловые проекции не разделяемы. Находите таблицу экспорта, в ней адрес своей функции и изменяете его.
     
  16. ntcdm

    ntcdm New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2007
    Сообщения:
    247
    На данный момент экспериментирую со способом изменения экспорта функции в ДЛЛ-ке. Почему-то при попытке вызова моего кода выпадает эксепшен.

    т.е. в дебагере я вижу что управление передается на мой код -
    001b:00030004 8bec mov ebp,esp

    но при нажатии F11 (шаг) выпадает в ntdll!KiUserExceptionDispatcher

    С чем это может быть связано? Может быть с тем что страница памяти не помечена как выполянемая?

    Память в процессе выделяю след. образом:
    Код (Text):
    1.             PMDL pMdl = NULL;
    2.             BYTE *pVirtualMemory = NULL;
    3.             PHYSICAL_ADDRESS phBegin,phEnd,phSkip;
    4.             phBegin.QuadPart = 0;
    5.             phEnd.QuadPart = (LONGLONG)-1;
    6.             phSkip.QuadPart = 0;
    7.             DWORD dwAllocationSize;
    8.             __try
    9.             {
    10.  
    11.                 pMdl = MmAllocatePagesForMdl(phBegin, phEnd, phSkip, 0x1000);
    12.                 DBGPRINT(("ImageLoadNotifyRoutine MmAllocatePagesForMdl %X\r\n", pMdl));
    13.                 if (pMdl)
    14.                 {
    15.                     dwAllocationSize = MmGetMdlByteCount(pMdl);
    16.                     if (dwAllocationSize >= 0x60)
    17.                     {
    18.                         pVirtualMemory = (BYTE *)MmMapLockedPagesSpecifyCache(pMdl, UserMode, MmCached, 0, FALSE, NormalPagePriority);
    19.                         DBGPRINT(("ImageLoadNotifyRoutine MmMapLockedPagesSpecifyCache %X\r\n", pVirtualMemory));
    20.                         if (pVirtualMemory)
    21.                         {
    И у меня память стабильно выделяется по виртуальному адресу 0x30000

    Может быть еще что то надо?
     
  17. ziral2088

    ziral2088 New Member

    Публикаций:
    0
    Регистрация:
    16 авг 2009
    Сообщения:
    283
    какой доступ у памяти? Атрибут на исполнение стоит?
     
  18. ntcdm

    ntcdm New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2007
    Сообщения:
    247
    В том то и дело что я не знаю... А как это узнать из WinDbg? Пробовал через "!address" но это расширение под Win7 не работает.

    Как можно узнать стоит атрибут на исполнение или нет?
     
  19. EFiR

    EFiR New Member

    Публикаций:
    0
    Регистрация:
    1 фев 2010
    Сообщения:
    28
    !pte va показывает атрибуты, где va - виртуал адрес страницы
     
  20. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    ziral2088
    Не вводите людей в заблуждение. Доступ на исполнение задаётся в дескрипторе сегмента, а не PTE/PDE. В дефолтных кодовых сегментах разрешено исполнение, в сегментах данных запрещено. Поэтому и не работает в NT атрибут PAGE_EXECUTE.

    ntcdm
    Контекст покажите.