Вопрос детский, но ответа так и не нашел =( Итак, анализирую SDT, иду по списку ServiceTable SST, получаю адреса всех функций ядра. Как узнать, какие из них перехвачены? Очевидно, нужно сравнить с эталоном. Но вот где взять оригинальные адреса (те, которые были в ServiceTable до перехвата)? Буду оч признателен за кусок кода.
Ок, спасиба. Такой вопрос: реальные адреса NativeAPI искать в файле ядра на диске или в загруженном модуле?
найти в экспорте ядра на диске точку входа, сложить с базой реального ядра в памяти и радоваться жизни
можно использовать давно опробованный способ - взять адрес любой функции ядра и листать страницами вниз до MZ-PE заголовка. хотя это както не красиво... с другой стороны, вполне возможно, что база ядра при каждой загрузке одинаковая.
ИМХО - криво. А если функция перехвачена? Долго листать буду... =) А базу ядра, при большом желании, получаем из списка модулей. Это при условии, что ядро всегда первым следует...
>> Это при условии, что ядро всегда первым следует... всегда, можешь не парится) >> с другой стороны, вполне возможно, что база ядра при каждой загрузке одинаковая. не вполне возможно, а так и есть... правда, может отличаться от версии к версии
Код (Text): BOOL GetOriginalSDTs() { HMODULE hKernel; DWORD dwKSDT; DWORD dwKiServiceTable; PMODULES pModules=(PMODULES)&pModules; DWORD dwNeededSize,rc; DWORD dwKernelBase; PCHAR pKernelName; PDWORD pService; PIMAGE_FILE_HEADER pfh; PIMAGE_OPTIONAL_HEADER poh; PIMAGE_SECTION_HEADER psh; HMODULE hntdll = GetModuleHandle("ntdll.dll"); *(FARPROC *)&_NtQuerySystemInformation = GetProcAddress(hntdll, "ZwQuerySystemInformation"); rc=_NtQuerySystemInformation(SystemModuleInformation,pModules,4,&dwNeededSize); if (rc==STATUS_INFO_LENGTH_MISMATCH) { pModules=(PMODULES)GlobalAlloc(GPTR,dwNeededSize); rc=_NtQuerySystemInformation(SystemModuleInformation,pModules,dwNeededSize,NULL); } else return FALSE; if (!NT_SUCCESS(rc)) return FALSE; dwKernelBase = (DWORD)pModules->smi.Base; pKernelName = pModules->smi.ModuleNameOffset+pModules->smi.ImageName; hKernel = LoadLibraryEx(pKernelName,0,DONT_RESOLVE_DLL_REFERENCES); if (!hKernel) return FALSE; GlobalFree(pModules); if (!(dwKSDT = (DWORD)GetProcAddress(hKernel,"KeServiceDescriptorTable"))) return FALSE; dwKSDT -= (DWORD)hKernel; if (!(dwKiServiceTable = FindKiServiceTable(hKernel,dwKSDT))) return FALSE; GetHeaders((PCHAR)hKernel,&pfh,&poh,&psh); pService = (PDWORD)((DWORD)hKernel + dwKiServiceTable); for (pService=(PDWORD)((DWORD)hKernel+dwKiServiceTable); *pService-poh->ImageBase<poh->SizeOfImage; pService++,dwServices++) TABLE[dwServices] = *pService - poh->ImageBase+dwKernelBase; NEWTABLE = (DWORD)(dwKernelBase + dwKSDT); FreeLibrary(hKernel); return TRUE; } примерно так. далее пускашь цикл по восстановлению SDT.
Угу, r3 и восстановление SDT :\ SDTRestore AFAIK юзал PhysicalMemory, однако сейчас его проблематично использовать.
<В догонку: а ядро всегда идет первым в списке модулей, получаемых ZqQuerySystemInformation? > нет. Элементарный пример. Простейший. Я могу перехватить данную функцию или список list_entry в ядре и отредактировать. Но видел системы, где модуль ядра на чистой системе не был первым в списке. Учти это.
что-то я не понимаю.. KeServiceDescriptorTable в образе - пустой массивчик, он заполняется динамически, а KiServiceTable не экспортируется.. остается толко привязываться к инструкциям, которые заполняют таблицу? k3internal а где это такое было, не помнишь? ps логично, если ядро идет первым, но логично, если идет и последним. вообще привязываться к его порядку в списке правда не стоит, имхо