Files
SKELETONKEY/modules/copy_fail_family/src/exploit_su.h
T
leviathan 52e8c99022 Phase 1: module interface + registry + top-level dispatcher
- core/module.h: struct iamroot_module + iamroot_result_t
- core/registry.{h,c}: flat-array module registry with find-by-name
- modules/copy_fail_family/iamroot_modules.{h,c}: bridge layer
  exposing 5 modules (copy_fail, copy_fail_gcm, dirty_frag_esp,
  dirty_frag_esp6, dirty_frag_rxrpc) wired to the absorbed DIRTYFAIL
  detect/exploit functions; df_result_t/iamroot_result_t share numeric
  values intentionally for zero-cost translation
- iamroot.c: top-level CLI dispatcher with --scan / --list / --exploit /
  --mitigate / --cleanup, JSON output, --i-know gate
- Restored modules/copy_fail_family/src/ structure (DIRTYFAIL Makefile
  expects it; the initial flat copy broke that contract)
- Top-level Makefile builds one binary; filters out DIRTYFAIL's
  original dirtyfail.c main so it doesn't conflict with iamroot.c

Verified end-to-end on kctf-mgr (Linux): clean compile, 5 modules
register, --scan --json output ingest-ready, exit codes propagate.
2026-05-16 19:32:11 -04:00

57 lines
2.4 KiB
C

/*
* DIRTYFAIL — exploit_su.h
*
* V4bel-style page-cache shellcode injection against /usr/bin/su.
*
* Different chain than the /etc/passwd UID-flip exploits:
* - Targets /usr/bin/su's ELF entry point in the page cache
* - Plants ~48 bytes of x86_64 shellcode (setuid(0); setgid(0);
* execve("/bin/sh")) via 12 chained 4-byte writes
* - When /usr/bin/su is exec'd, kernel sets euid=0 (setuid bit on
* disk, unaffected by page-cache mods), dynamic linker resolves,
* control transfers to entry point → our shellcode → /bin/sh
*
* Mitigation profile vs. /etc/passwd flip:
* + Bypasses `pam_unix nullok` removal — no PAM dependency at all
* + Works even if password rotation policy enforces complex passwords
* - Crashes /usr/bin/su system-wide if shellcode is wrong (until
* drop_caches or reboot)
* - Stash-and-revert is the safety net: cleanup-su restores the
* original 48 bytes from /var/tmp/.dirtyfail-su.state.
*
* Architecture: x86_64 only for now. The shellcode is hardcoded for
* the SYSV amd64 syscall ABI. arm64/aarch64 would need a different
* shellcode blob and possibly a different entry-point fixup.
*
* Reference: V4bel/dirtyfrag's xfrm-ESP variant uses the same target
* file pattern with a different (4-byte) primitive. Theori's Xint
* disclosure uses /usr/bin/su as the canonical target.
*/
#ifndef DIRTYFAIL_EXPLOIT_SU_H
#define DIRTYFAIL_EXPLOIT_SU_H
#include "common.h"
/* End-to-end PoC: locate /usr/bin/su (or DIRTYFAIL_SU_PATH override),
* stash original entry-point bytes, plant shellcode, verify, and
* (if do_shell) invoke `su -` so the kernel exec's our hijacked
* /usr/bin/su as setuid root → shellcode runs → /bin/sh.
*
* `do_shell=false` runs the plant + verify + revert sequence — useful
* for testing the primitive without leaving the system in a broken
* state (su would otherwise be unusable until drop_caches). */
df_result_t exploit_su_shellcode(bool do_shell);
/* Restore /usr/bin/su's original entry-point bytes from
* /var/tmp/.dirtyfail-su.state and drop_caches to evict the modified
* page. Returns DF_OK on success, DF_TEST_ERROR if state file is
* missing or the on-disk file no longer matches. */
df_result_t cleanup_su_shellcode(void);
/* Used by --list-state. Returns true if /var/tmp/.dirtyfail-su.state
* is present (and prints a summary), false if absent. Side-effect free. */
bool exploit_su_list_state(void);
#endif