/* * How to dereference a null pointer and get away with it. * * G. Back, CS 3214, updated Fall 2014 * * Must compile with -O2 */ /* required so that REG_RIP etc. are defined the first time sys/ucontext.h is included */ #define _GNU_SOURCE 1 #include #include #include #include static void install_signal_handler(int signal, void (*handler)(int, siginfo_t *, void *)) { struct sigaction act; act.sa_sigaction = handler; act.sa_flags = SA_SIGINFO; sigemptyset (&act.sa_mask); int status = sigaction (signal, &act, NULL); if (status) { perror ("sigaction"); exit (1); } } /* * 400668: 8b 34 25 00 00 00 00 mov 0x0,%esi * 40066f: bf e2 07 40 00 mov $0x4007e2,%edi * 400674: 31 c0 xor %eax,%eax * 400676: e8 2d fe ff ff callq 4004a8 */ static void catch_segfault(int signo, siginfo_t *info, void * _ctxt) { ucontext_t * ctxt = _ctxt; printf("Catching Segfault at sig=%d fault addr is %p eip was at %x\n", signo, info->si_addr, ctxt->uc_mcontext.gregs[REG_RIP]); // skip offending instruction ctxt->uc_mcontext.gregs[REG_RIP] += 7; // put 42 into %rsi ctxt->uc_mcontext.gregs[REG_RSI] = 42; // upon return, OS will apply any changes to ctxt // to process's saved state, the restore the state // execution will continue at 400668 + 7 = 40066f } int main() { install_signal_handler(SIGSEGV, catch_segfault); printf("Dereferencing NULL -> %d ...\n", *(int *)NULL); return 0; }