Как востановить KeServiceDescriptorTableShadow

Тема в разделе "WASM.WIN32", создана пользователем sasha_s, 21 дек 2005.

  1. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    Ну эта та которая лежит в win32k.sys. Так вот как востановить KeServiceDescriptorTable описано тут: http://www.security.org.sg/code/sdtrestore.html

    А как востановить KeServiceDescriptorTableShadow что-то я не нашел еще. Подскажите плиз...
     
  2. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    Ну дык а что мешает загрузить win32k.sys с диска и найти Shadow SDT там?
     
  3. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus




    а нетути там что-то такой вещи как "KeServiceDescriptorTableShadow"! В выше указанном примере поиск "KeServiceDescriptorTable" осуществляется так:
    Код (Text):
    1. DWORD procAPIExportAddr(DWORD hModule, char *apiName)
    2. {  
    3.     if(!hModule || !apiName)
    4.         return 0;
    5.  
    6.     char *ptr = (char *)hModule;
    7.     ptr += 0x3c;        // offset 0x3c contains offset to PE header
    8.    
    9.     // offset 78h into PE header contains addr of export table
    10.     ptr = (char *)(*(DWORD *)ptr) + hModule + 0x78;
    11.  
    12.     // ptr now points to export directory table
    13.     ptr = (char *)(*(DWORD *)ptr) + hModule;
    14.  
    15.     // offset 24 into the export directory table == number of entries
    16.     // in the Export Name Pointer Table
    17.     // table
    18.     DWORD numEntries = *(DWORD *)(ptr + 24);
    19.     //printf("NumEntries = %d\n", numEntries);
    20.  
    21.     // offset 32 into export directory contains offset to Export Name Pointer Table
    22.     DWORD *ExportNamePointerTable = (DWORD *)(*(DWORD *)(ptr + 32) + hModule);  
    23.    
    24.     DWORD ordinalBase = *((DWORD *)(ptr + 16));
    25.     //printf("OrdinalBase is %d\n", ordinalBase);
    26.  
    27.     // offset 36 into export directory contains offset to Ordinal Table
    28.     WORD *ExportOrdinalTable = (WORD *)((*(DWORD *)(ptr + 36)) + hModule);
    29.    
    30.     // offset 28 into export directory contains offset to Export Addr Table
    31.     DWORD *ExportAddrTable = (DWORD *)((*(DWORD *)(ptr + 28)) + hModule);
    32.  
    33.     FILE    *f = fopen("_ntoskrnl_exe.txt", "w+b");
    34.     for(DWORD i = 0; i < numEntries; i++)
    35.     {      
    36.         char *exportName = (char *)(ExportNamePointerTable[i] + hModule);
    37.  
    38.         if (f)
    39.             fprintf(f, "%s\r\n", exportName);
    40.  
    41.         if(myStrcmpA(exportName, apiName) == TRUE)
    42.         {
    43.             WORD ordinal = ExportOrdinalTable[i];
    44.             //printf("%s (i = %d) Ordinal = %d at %X\n", exportName,
    45.                                         i, ordinal, ExportAddrTable[ordinal]);
    46.  
    47.             return (DWORD)(ExportAddrTable[ordinal]);
    48.         }      
    49.     }
    50.     if (f)
    51.         fclose(f);
    52.  
    53.     return 0;
    54. }
    где apiName == "KeServiceDescriptorTable"!

    А в win32k.sys нет "KeServiceDescriptorTableShadow" в таблице экспорта.



    Так как и где ее искать?
     
  4. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"


    SdtRVA = &KeServiceDescriptorTable->win32k.ServiceTable - GetModuleHandle("win32k.sys");

    pTrueSdt = LoadPeFile("win32k.sys") + SdtRVA;



    GetModuleHandle и LoadPeFile в ядре естественно нет, но я думаю у каждого есть свои их реализации.

    Суть такова: находим Shadow SDT в памяти, вычисляем разницу с базой загрйзки win32k, грузим свою копию win32k, прибавляем смещение и получаем чистую Shadow SDT.

    Единственно надо учесть, что перед восстановлением оригинальной SDT надо обработать релоки в win32k согласно базе загрузки основной копии win32k.sys.

    Все это может выглядеть примерно так:



    pWin32k = GetModuleHandle("win32k.sys");

    SdtRVA = &KeServiceDescriptorTable->win32k.ServiceTable - pWin32k ;

    w32kCopy = LoadPeFile("win32k.sys");

    ProcessRelocs(w32kCopy, pWin32k);

    memcpy(&KeServiceDescriptorTable->win32k.ServiceTable, w32kCopy + SdtRVA, SdtSize);



    Сорцы кусков моего пелоадера (там LoadPeFile, GetModuleHandle, ProcessRelocs и прочая фигня) както проскакивали на форуме, так что поищи как следует.
     
  5. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    СУПЕР! Ответ по существу и все понятно, но вот я не нашел в форуме сорцы GetModuleHandle и ProcessRelocs (LoadPeFile у меня есть свой)... Может искал плохо, но всеже если тебе не трудно то выложи их тут, или кинь мне на мыло: str1@tut.by
     
  6. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    В принципе без GetModuleHandle можно обойтись перебрав все загруженные модули (NtQueryInformation или что-то в этом духе) и получить ImageBase win32k.sys
     
  7. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    GetModuleHandle у меня собственно и перебирает модули через ZwQuerySystemInformation (только идет дополнительная обработка для ntoskrnl и hal, так как они называться могут по другому).

    А код ProcessRelocs приведу тут:
    Код (Text):
    1. void ProcessRelocs(
    2.             IN PVOID Image,
    3.             IN PVOID NewImageBase
    4.             )
    5. {
    6.     PIMAGE_DOS_HEADER       dHeader = Image;
    7.     PIMAGE_NT_HEADERS       ntHeaders = RVATOVA(Image, dHeader->e_lfanew);
    8.     ULONG RelRVA   = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELO C].VirtualAddress;
    9.     ULONG RelSize  = ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELO C].Size;
    10.     ULONG Delta    = (ULONG)NewImageBase - ntHeaders->OptionalHeader.ImageBase;
    11.  
    12.     if (RelRVA && RelSize && !(ntHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) &&
    13.         RelRVA + RelSize <= ntHeaders->OptionalHeader.SizeOfImage)
    14.     {
    15.         PIMAGE_BASE_RELOCATION Reloc = RVATOVA(Image, RelRVA);
    16.         BOOLEAN bFirstChunk = TRUE;
    17.  
    18.         while (bFirstChunk || Reloc->VirtualAddress)
    19.         {
    20.             PIMAGE_FIXUP_ENTRY Fixup = (PVOID)((ULONG)Reloc + sizeof(IMAGE_BASE_RELOCATION));
    21.             ULONG r, dwPointerRva;
    22.  
    23.             bFirstChunk = FALSE;
    24.  
    25.             for (r = 0; r < (Reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) >> 1; r++)
    26.             {
    27.                 if (Fixup->Type == IMAGE_REL_BASED_HIGHLOW)
    28.                 {
    29.                     dwPointerRva = Reloc->VirtualAddress + Fixup->Offset;
    30.  
    31.                     if (dwPointerRva > ntHeaders->OptionalHeader.SizeOfImage) return;
    32.  
    33.                     *(PULONG)((ULONG)dHeader + dwPointerRva) += Delta;
    34.                 }
    35.  
    36.                 Fixup++;
    37.             }
    38.  
    39.             Reloc = (PVOID)((ULONG)Reloc + Reloc->SizeOfBlock);
    40.         }
    41.     }
    42. }
     
  8. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    Спасибо! Буду пробывать.
     
  9. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    вот только RVATOVA и PIMAGE_FIXUP_ENTRY у меня не определены... Подскажи где брал, или мот это чисто твои фичи -- тогда выложи.
     
  10. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    RVATOVA и PIMAGE_FIXUP_ENTRY я уже в инете нашел:
    Код (Text):
    1. #define RVATOVA(base,offset) ((PVOID)((DWORD)(base)+(DWORD)(offset)))
    2. typedef struct _IMAGE_FIXUP_ENTRY {
    3.     WORD    Offset:12;
    4.     WORD    Type:4;
    5. } IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY;




    Вопросс у меня делетантский: А зачем надо делать ProcessRelocs? Почему нельзя просто скопировать эту таблицу?
     
  11. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"




    Нет почему-же, скопировать можно, да только кроме бсода не удасться ничего получить :)

    В таблице находятся адреса функций в win32k, и эти адреса там идут относительно ее ImageBase. Так как драйвера грузятся всегда не по ImageBase, то адреса в загруженом win32k естественно будут отличаться от адресов в файле на величину разницы базы загрузки с ImageBase.

    В принципе, вместо обработки релоков можно просто прибавлять эту разницу.