Зравствуйте, собственно интересует как востановить SDT. Но только не в user mode, а на уровне ядра. Все что я нашел по данной тематике работает на уровне пользователя. Единственное упомянание про это на форуме здесь: http://www.wasm.ru/forum/viewtopic.php?pid=108168#p108168. Но застопорился на реализации LoadPeFile для ядра. Может у кого есть уже готовые решения?
Вот мой сорц. Почти всё выдрано из статьи 90210 Код (Text): #include <ntddk.h> typedef NTSTATUS (NTAPI *NTPROC)(); typedef NTPROC *PNTPROC; typedef struct _SYSTEM_SERVICE_TABLE{ PNTPROC ServiceTable; PULONG CounterTable; ULONG ServiceLimit; PUCHAR ArgumentTable; } SYSTEM_SERVICE_TABLE, *PSYSTEM_SERVICE_TABLE; typedef struct _SERVICE_DESCRIPTOR_TABLE{ SYSTEM_SERVICE_TABLE NtoskrnlTable; SYSTEM_SERVICE_TABLE Table2; SYSTEM_SERVICE_TABLE Table3; SYSTEM_SERVICE_TABLE Table4; } SERVICE_DESCRIPTOR_TABLE, *PSERVICE_DESCRIPTOR_TABLE; typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation, SystemProcessorInformation, SystemPerformanceInformation, SystemTimeOfDayInformation, SystemNotImplemented1, SystemProcessesAndThreadsInformation, SystemCallCounts, SystemConfigurationInformation, SystemProcessorTimes, SystemGlobalFlag, SystemNotImplemented2, SystemModuleInformation, SystemLockInformation, SystemNotImplemented3, SystemNotImplemented4, SystemNotImplemented5, SystemHandleInformation, SystemObjectInformation, SystemPagefileInformation, SystemInstructionEmulationCounts, SystemInvalidInfoClass1, SystemCacheInformation, SystemPoolTagInformation, SystemProcessorStatistics, SystemDpcInformation, SystemNotImplemented6, SystemLoadImage, SystemUnloadImage, SystemTimeAdjustment, SystemNotImplemented7, SystemNotImplemented8, SystemNotImplemented9, SystemCrashDumpInformation, SystemExceptionInformation, SystemCrashDumpStateInformation, SystemKernelDebuggerInformation, SystemContextSwitchInformation, SystemRegistryQuotaInformation, SystemLoadAndCallImage, SystemPrioritySeparation, SystemNotImplemented10, SystemNotImplemented11, SystemInvalidInfoClass2, SystemInvalidInfoClass3, SystemTimeZoneInformation, SystemLookasideInformation, SystemSetTimeSlipEvent, SystemCreateSession, SystemDeleteSession, SystemInvalidInfoClass4, SystemRangeStartInformation, SystemVerifierInformation, SystemAddVerifier, SystemSessionProcessesInformation } SYSTEM_INFORMATION_CLASS; typedef struct _SYSTEM_MODULE{ ULONG Reserved[2]; PVOID Base; ULONG Size; ULONG Flags; USHORT Index; USHORT Unknown; USHORT LoadCount; USHORT ModuleNameOffset; CHAR ImageName[256]; } SYSTEM_MODULE, *PSYSTEM_MODULE; typedef struct _SYSTEM_MODULE_INFORMATION { ULONG dwCount; SYSTEM_MODULE Modules[1]; } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; #ifdef __cplusplus extern "C" { #endif extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable; extern NTSYSAPI NTSTATUS NTAPI ZwCreateSection( OUT PHANDLE SectionHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN PLARGE_INTEGER SectionSize OPTIONAL, IN ULONG Protect, IN ULONG Attributes, IN HANDLE FileHandle ); extern NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation ( IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG Length, OUT PULONG ReturnLength ); #ifdef __cplusplus } #endif #define RESTORE_SYSCALL 0x35 void DriverUnload(PDRIVER_OBJECT DriverObject){ } NTSTATUS DrvUnhookQST(ULONG dwSysCall, ULONG dwOriginal){ ULONG CR0Reg; _asm mov eax,CR0 _asm mov CR0Reg,eax _asm and eax,0xFFFEFFFF _asm mov cr0, eax KeServiceDescriptorTable->NtoskrnlTable.ServiceTable[dwSysCall] = (NTPROC)dwOriginal; _asm mov eax,CR0Reg _asm mov cr0,eax } HANDLE hKernelFile = 0, hKernelSection = 0; PVOID pKernel = NULL; void UnMapKernel(){ if (pKernel) ZwUnmapViewOfSection(pKernel, NtCurrentProcess()); if (hKernelSection) ZwClose(hKernelSection); if (hKernelFile) ZwClose(hKernelFile); } NTSTATUS MapKernel(){ UNICODE_STRING usKernelFile; OBJECT_ATTRIBUTES oaKernelFile; NTSTATUS ns = STATUS_SUCCESS; IO_STATUS_BLOCK iosb; ULONG dwViewSize = 0; RtlInitUnicodeString(&usKernelFile, L"\\SystemRoot\\System32\\ntoskrnl.exe"); InitializeObjectAttributes(&oaKernelFile, &usKernelFile, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); ns = ZwOpenFile(&hKernelFile, FILE_READ_DATA | SYNCHRONIZE, &oaKernelFile, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_NONALERT); if (ns != STATUS_SUCCESS) return ns; ns = ZwCreateSection(&hKernelSection, SECTION_MAP_READ, NULL, NULL, PAGE_READONLY, 0x8000000, hKernelFile); if (ns != STATUS_SUCCESS){ UnMapKernel(); return ns; } ns = ZwMapViewOfSection(hKernelSection, NtCurrentProcess(), &pKernel, 0, 0, NULL, &dwViewSize, ViewShare, 0, PAGE_READONLY); if (ns != STATUS_SUCCESS) UnMapKernel(); return ns; } ULONG mystrcmp(char *str1, char *str2){ while(*str1 && *str2) if(*str1 == *str2){ str1++; str2++; }else return 0; if(*str1 && !*str2) return 0; else if (*str2 && !*str1) return 0; return 1; } ULONG xGetProcAddress(ULONG hModule, char *pszName){ ULONG dwNameCount, *AddressOfNames, *AddressOfFunctions; USHORT *AddressOfOrdinals; ULONG i; char *pszExportName; char *ptr = (char *)hModule; ptr += 0x3c; ptr = (char *)(*(ULONG *)ptr) + hModule + 0x78; ptr = (char *)(*(ULONG *)ptr) + hModule; dwNameCount = *(ULONG *)(ptr + 24); AddressOfNames = (ULONG *)(*(ULONG *)(ptr + 32) + hModule); AddressOfOrdinals = (USHORT *)((*(ULONG *)(ptr + 36)) + hModule); AddressOfFunctions = (ULONG *)((*(ULONG *)(ptr + 28)) + hModule); for(i = 0; i < dwNameCount; i++){ pszExportName = (char *)(AddressOfNames[i] + hModule); if(mystrcmp(pszExportName, pszName) == 1) return (ULONG)(AddressOfFunctions[AddressOfOrdinals[i]]); } return 0; } typedef struct _IMAGE_BASE_RELOCATION{ ULONG VirtualAddress; ULONG SizeOfBlock; } IMAGE_BASE_RELOCATION, *PIMAGE_BASE_RELOCATION; typedef struct { USHORT offset: 12; USHORT type: 4; } IMAGE_FIXUP_ENTRY, *PIMAGE_FIXUP_ENTRY; ULONG GetKiServiceTable(ULONG SDT, ULONG hModule){ char *ptr; PIMAGE_BASE_RELOCATION pbr; PIMAGE_FIXUP_ENTRY pfe; ULONG bFirst = 1, dwPointerRVA, i; ptr = (char *)hModule; ptr += 0x3c; ptr = (char *)(*(ULONG *)ptr) + hModule + 0xA0; pbr = (PIMAGE_BASE_RELOCATION)((char *)(*(ULONG *)ptr) + hModule); while ((bFirst) || (pbr->VirtualAddress)){ bFirst = 0; pfe = (PIMAGE_FIXUP_ENTRY)((ULONG)pbr + 8); for (i = 0; i < (pbr->SizeOfBlock - 8) >> 1; i++, pfe++) if (pfe->type == 3){ dwPointerRVA = pbr->VirtualAddress + pfe->offset; if (*(PULONG)(hModule + dwPointerRVA) - 0x400000 == SDT) if (*(PUSHORT)(hModule + dwPointerRVA - 2) == 0x05c7) return (*(PULONG)(hModule + dwPointerRVA + 4) - 0x400000 + hModule); } *(PULONG)&pbr += pbr->SizeOfBlock; } return 0; } ULONG GetKernelBase(){ ULONG cb = 0, i; PSYSTEM_MODULE_INFORMATION p = NULL; NTSTATUS ns; ZwQuerySystemInformation(SystemModuleInformation, &p, 0, &cb); if (!cb) return 0; p = ExAllocatePool(PagedPool, cb); if (!p) return 0; ns = ZwQuerySystemInformation(SystemModuleInformation, p, cb, &cb); if (ns != STATUS_SUCCESS) goto exit; for (i = 0; i < p->dwCount; i++) if (mystrcmp("ntoskrnl.exe", &(p->Modules[i].ImageName[p->Modules[i].ModuleNameOffset])) == 1) return (ULONG)p->Modules[i].Base; exit: ExFreePool(p); return 0; } NTSTATUS RestoreSDT(){ ULONG SDT, KernelBase; PNTPROC KiServiceTable; if (MapKernel() != STATUS_SUCCESS) return STATUS_SUCCESS; SDT = xGetProcAddress((ULONG)pKernel, "KeServiceDescriptorTable"); if (!SDT) goto exit; KiServiceTable = (PNTPROC)GetKiServiceTable(SDT, (ULONG)pKernel); if (!KiServiceTable) goto exit; KernelBase = GetKernelBase(); if (!KernelBase) goto exit; DrvUnhookQST(RESTORE_SYSCALL, (ULONG)(KiServiceTable[RESTORE_SYSCALL]) - 0x400000 + GetKernelBase()); exit: UnMapKernel(); return STATUS_SUCCESS; } NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath){ DriverObject->DriverUnload = DriverUnload; RestoreSDT(); return STATUS_SUCCESS; }
n0name, спасибо. Вроде то что надо. Но при беглом просмотре возник один вопрос: зачем в GetKernelBase делаешь это: Код (Text): for (i = 0; i < p->dwCount; i++) if (mystrcmp("ntoskrnl.exe", &(p->Modules[i].ImageName[p->Modules[i].ModuleNameOffset])) == 1) return (ULONG)p->Modules[i].Base; во-первых, ядро вроде все время первым в списке долдно идти, а во-вторых, оно не всегда будет называться ntoskrnl.exe. Например на многопроцессорной машине ядро называется ntkrnlpa.exe
должно, не должно, это вопрос спорный, хочешь сделаю скрин где ntoskrnl.exe последний? Ну да, но для многопроцессорной машины и код должен быть более строгим.
Даже на однопроцессорной тачке ядро может называться по любому. boot.ini: /KERNEL=lol.xxx Хм, не видел, чтобы ядро было в списке не первым.