/* * How to dereference a null pointer and get away with it. * * G. Back, CS 3214 */ #include #include #include #include #define __USE_GNU 1 #include 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_EIP]); /* The assembly code for main (below) is: 8048507: b8 00 00 00 00 mov $0x0,%eax ----> This is where it faults, eip has value 804850c on fault 804850c: 8b 00 mov (%eax),%eax ----> If it hadn't faulted, result would be in %eax 804850e: 89 44 24 04 mov %eax,0x4(%esp) */ ctxt->uc_mcontext.gregs[REG_EAX] = 42; // put '42' in eax ctxt->uc_mcontext.gregs[REG_EIP] += 2; // skip '8b 00' above // upon return, OS will read *ctxt and restore CPU's registers } int main() { int status; struct sigaction act; act.sa_sigaction = catch_segfault; act.sa_flags = SA_SIGINFO; sigemptyset (&act.sa_mask); status = sigaction (SIGSEGV, &act, NULL); if (status) { perror ("sigaction"); exit (1); } printf("Dereferencing NULL -> %d ...\n", *(int *)NULL); return 0; }