Доброго времени суток! Прошу помочь начинающему с вот такой задачкой: Необходимо восстановить оригинальный адрес функции ZwWriteVirtualMemory в SST! Как это делается с точки зрения теории вроде нашел : «Для восстановления SST можно использовать ее копию, хранящуюся внутри NTOSKRNL.EXE. Находим все перекрестные ссылки к KeServiceDescriptorTable (т.е. просто ищем ее адрес, записанный с учетом обратного порядка байт на x86, задом наоборот). Одна из них ведет к инструкции типа "mov [mem], imm32" и представляет собой смещение оригинальной SST (imm32), записываемой в KeServiceDescriptorTable[0].» Проблема 1: Как будет выглядеть инструкция «mov [mem], imm32» в HEX или bin виде? Проблема 2: Даже если я и узнаю как будет выглядеть данная инструкция, в правильности своих дальнейших действий нет ни какой уверенности. Для начала я бы взял и перевернул последовательность байт отображающую данную инструкцию (дабы получить код, записанный с учетом обратного порядка байт на x86), затем используя функции ZwCreateFile / ZwReadFile загрузил бы файл NTOSKRNL.EXE в память, после чего нашел бы в нем полученную последовательность байт, которая бы и являлась начальным адресом SST в данном файле, затем со смещением в 4 байта от полученного адреса я смог бы найли адреса оригинальных функций SST, нашел бы среди них ту которая мне нужна, взял бы ее адрес и записал в ту же позицию в SST в памяти. Плиз развейте или подтвердите кто-нибуть мой миф ))) и помогите пожалуйста с получением кода инструкции «mov [mem], imm32» если она мне чем-то действительно поможет. Заранее большое спосибо!
Проблема 1: Как будет выглядеть инструкция «mov [mem], imm32» в HEX или bin виде? Береш отладчик вбиваеш инструкциюи смотриш кода C705 mem_dword imm32_dword Посмотри какиенить сырсы сигнатурных поисков, а как выгледят команды в хексе смотри просто в Olly DBG
Спасибо за ответ! "Береш отладчик вбиваеш инструкциюи смотриш кода" - это в том смысле, что мне нужно создать левый .exe в котором бы просто были эти инструкции, затем загрузить в Olly DBG и узнать их код? Но я ведь не могу это(mov [mem], imm32) скомпилить. Одним из операндов вроде бы должен быть регистр? Или я очень сильно туплю? Пробовал так же запустить в Olly DBG какой-нибудь .exe и вбить вместо какой-нибудь строки данную инструкцию, тоже не вышло. А что значит C705 - не это ли именно то, что мне нужно? Пробовал искать данную последовательность только наоборот(0x05 0xC7) в NTOSKRNL.EXE нашел ее аж 12 раз DWORD dw; HANDLE hh = CreateFile("C:/WINDOWS/system32/NTOSKRNL.EXE", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); int i = GetFileSize(hh, &dw); UCHAR* buf = new UCHAR; ReadFile(hh, buf, i, &dw, NULL); int k = 1; for(int n = 0; n < i; n ++) { if(buf[n] == 0x05) { if(buf[n+1] == 0xC7) { printf("found - %d\n", k++); } } } delete [] buf; Я вообще хоть на правильном пути к решению своей задачи или глупости делаю?
загружаешь совершенно левый бинарник, хоть блокнот, хоть калькулятор. выбираешь любую инструкцию и жмешь пробел (Assembly). Вводишь команду mov [12345678], abcdef12 - пример команды типа mov [mem],imm32, и жмешь ентер. "и о чудо, никаких пятен!" олли отассемблировал команду и показал слева ее машинный код.
asd Спасибо по поводу запроса поиска! Я икал SST или SSDT, а там в темах упоминается SDT! Потому не находил! Большое спасибо сейчас буду изучать! Дело принципа, просто заинтересовало! Все делаю именно так, но к несчастью пятна есть (( Загрузил bin NOTEPAD сделал все вроде так, как нужно, но увы: ниже окошка ввода команд появляется красненькая надпись "Unknown identifier" и ничего не происходит ((((
Asd, на одной из найденных тем я встретил фразу пробовал поиском таких статей не нашел, можно попросить ссылочку? Очень хочется посмотреть теоретическое описание! ))
Искал инфу по форму, нашел следуюший код: Код (Text): #include <ntddk.h> #define DEBUG #ifdef DEBUG #define DBGPRINT DbgPrint #else #define DBGPRINT #endif typedef BOOLEAN BOOL; typedef ULONG DWORD; typedef USHORT WORD; typedef UCHAR BYTE; 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 0xAD void DriverUnload(PDRIVER_OBJECT DriverObject){ } NTSTATUS DrvUnhookQST(ULONG dwSysCall, ULONG dwOriginal){ ULONG CR0Reg; DBGPRINT("fun addr - %x", dwOriginal); _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); DBGPRINT("%d", dwNameCount); for(i = 0; i < dwNameCount; i++){ pszExportName = (char *)(AddressOfNames[i] + hModule); DBGPRINT("%s", pszExportName); 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){ DBGPRINT("Loading driver"); DriverObject->DriverUnload = DriverUnload; RestoreSDT(); return STATUS_SUCCESS; } Но с его применением возникла небольшая проблемка: В ф-ии "xGetProcAddress" в стороке dwNameCount = *(ULONG *)(ptr + 24); получаю ноль (dwNameCount = 0) Узнать по этому поводу смог то, что образ файла загружается загрузчиком ОС как бы по по одному, а зачитывается ф-ей xGetProcAddress по другому, и что необходима несколько иная реализация данной ф-ии! Кто что может подсказать по этому поводу? P.S. система "WinXP sp2"
Адрес оригинальной SST в ntoskrnl является одним из параметров функции KeAddSystemServiceTable, вызываемой для добавления SST в том же модуле(в win32k также). Но поиск ссылки на эту функцию будет довольно сложен.