+#define _GNU_SOURCE foo
+
#include <limits.h>
+#include <signal.h>
#include <sys/mman.h>
#include <sys/types.h>
+#include <sys/ucontext.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_BITS (sizeof(size_t) * CHAR_BIT - 1)
+int dummy = 13;
+int *pi;
+
+static void catch_sigsegv(int signal, siginfo_t *info, void *p) {
+ (void)(signal);
+
+ ucontext_t *uctx = (ucontext_t*)p;
+ greg_t rip = uctx->uc_mcontext.gregs[REG_RIP];
+
+ fprintf(stderr, "Caught a segfault at %p\n", info->si_addr);
+ fflush(stderr);
+
+ // Point it at a variable we can always load
+ pi = &dummy;
+ // Roll back %rip so we can reload *pi before dereferencing
+ rip -= 7; // length of mov 0x2006b4(%rip),%rax # 0x6012b0 <pi>
+ uctx->uc_mcontext.gregs[REG_RIP] = rip;
+}
+
int main() {
pid_t pid = getpid();
printf("My pid is: %d\n", pid);
}
}
+ sigset_t empty;
+ sigemptyset(&empty);
+ struct sigaction sigsegv_action = {
+ .sa_sigaction = catch_sigsegv,
+ .sa_mask = empty,
+ .sa_flags = SA_SIGINFO
+ };
+ sigaction(SIGSEGV, &sigsegv_action, NULL);
+
srand48(time(NULL));
int data;
do {
- int *pi;
uint32_t lower = lrand48();
uint32_t upper = lrand48();
printf("*%p = ", (void*)pi);
fflush(stdout);
data = *pi;
- printf("%x\n", data);
+ if (pi != &dummy) {
+ printf("%04x\n", data);
+ } else {
+ printf("dummy\n");
+ }
if (munmap((void*)(pvalue & ~0xFFFL), 4096)) {
perror("munmap");
}
- } while (data == 0);
+ } while (data == 0 || pi == &dummy);
}