返回
顶部

(所有压缩包的密码均为1)

references:

环境搭建

漏洞成因

由于驱动程序未检查由用户模式传过来的地址是否位于用户模式中,可能会导致任意内核地址的任意写(Write-What-Where

#ifdef SECURE
        ProbeForRead((PVOID)Where, sizeof(PULONG_PTR), (ULONG)__alignof(PULONG_PTR));
        ProbeForRead((PVOID)What, sizeof(PULONG_PTR), (ULONG)__alignof(PULONG_PTR));

        *(Where) = *(What);
#else
        DbgPrint("[+] Triggering Arbitrary Overwrite\n");
        *(Where) = *(What);
#endif

可以看到,安全代码使用了函数ProbeForRead对用户传过来的地址进行了检查,而漏洞代码未进行任何检查,直接写入用户指定的内存地址

在IDA中可以看到触发漏洞函数的IO control code是0x22200B

image-20240125142016291

查看漏洞代码:

int __stdcall TriggerArbitraryOverwrite(_WRITE_WHAT_WHERE *UserWriteWhatWhere)
{
  unsigned int *What; // edi
  unsigned int *Where; // ebx

  ProbeForRead(UserWriteWhatWhere, 8u, 4u);
  What = UserWriteWhatWhere->What;
  Where = UserWriteWhatWhere->Where;
  DbgPrint("[+] UserWriteWhatWhere: 0x%p\n", UserWriteWhatWhere);
  DbgPrint("[+] WRITE_WHAT_WHERE Size: 0x%X\n", 8);
  DbgPrint("[+] UserWriteWhatWhere->What: 0x%p\n", What);
  DbgPrint("[+] UserWriteWhatWhere->Where: 0x%p\n", Where);
  DbgPrint("[+] Triggering Arbitrary Overwrite\n");
  *Where = *What;
  return 0;
}

很明显,传入的是一个结构体,两个字段,一个What,一个Where

typedef struct _UserWriteWhatWhere {
    DWORD What;
    DWORD Where;
} _WRITE_WHAT_WHERE

触发漏洞

#include <stdio.h>
#include <malloc.h>
#include <Windows.h>
#pragma pack(1)
typedef struct _UserWriteWhatWhere {
    DWORD What;
    DWORD Where;
} _WRITE_WHAT_WHERE;

int main() {
    HANDLE driver_handle = CreateFileW(L"\\\\.\\HackSysExtremeVulnerableDriver", 0xC0000000, 3, 0, 3, 0x80, 0);
    if(INVALID_HANDLE_VALUE==driver_handle) {
        printf("can not open device, %x\n",GetLastError());
        exit(-1);
    }

    // io control 
        _WRITE_WHAT_WHERE* www = (_WRITE_WHAT_WHERE*)malloc(sizeof(_WRITE_WHAT_WHERE));
    if (0 == www) {
        printf("I've never seen malloc falied\n"); exit(-1);
    }
    // 这两个地址该怎么写我还真不知道  不过可以先随便写两个地址  看看iocode好不好使
    int what = 0;
    int where = 1;
    DWORD whataddresss = reinterpret_cast<DWORD>(&what);
    DWORD whereaddresss = reinterpret_cast<DWORD>(&where);
    www->What = whataddresss;
    www->Where = whereaddresss;
    DWORD   BytesReturned = 0;
    // 触发漏洞    iocontrol调用之后  where的值由1变成了0  说明调用正确
    if (DeviceIoControl(driver_handle, 0x22200B, www, sizeof(www), 0, 0, &BytesReturned, 0))
        return 1;

    return 0;
}

现在我们已经知道怎么抵达漏洞代码了,但是并不清楚如何进行利用

要想正确的利用该漏洞还不引起BSOD,需要用到Windows的一个未公开的函数ZWQueryIntervalProfile,该函数会调用系统调用nt!NtQueryIntervalProfile,内核函数存在于ntoskrnl.exe中,我们需要把这个文件搞到ida里看一看