Last active
August 5, 2022 04:23
-
-
Save 3intermute/11ba22dba63362431a8cec84aedaffae to your computer and use it in GitHub Desktop.
arm64 syscall hooking
This file contains hidden or 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 <linux/init.h> | |
#include <linux/module.h> | |
#include <linux/kernel.h> | |
#include <asm-generic/unistd.h> | |
#include "resolve_kallsyms.h" | |
#include "set_page_flags.h" | |
#include "direct_syscall_hook.h" | |
MODULE_LICENSE("GPL"); | |
MODULE_AUTHOR("0xwillow"); | |
MODULE_DESCRIPTION("syscall table hook on arm64, no ftrace"); | |
MODULE_VERSION("1.0"); | |
static asmlinkage int (*orig_mkdirat) (const struct pt_regs *); | |
asmlinkage int new_mkdirat(const struct pt_regs *regs) { | |
char __user *pathname_usr_ptr = (char *) regs->regs[1]; | |
char pathname[NAME_MAX] = {0}; | |
strncpy_from_user(pathname, pathname_usr_ptr, NAME_MAX); // 256 bits | |
pr_info("debug: mkdirat called :D, path (%s), fd (%i), mode (%lli)\n", pathname, (int) regs->regs[0], regs->regs[2]); | |
if ((int) regs->regs[0] == -1) { | |
return 0xdeadbeef; | |
} | |
return orig_mkdirat(regs); | |
} | |
struct direct_syscall_hook hook = {__NR_mkdirat, new_mkdirat, &orig_mkdirat}; | |
static int __init hook_test_mod_init(void) { | |
pr_info("debug: module loaded\n"); | |
hook_syscall(&hook); | |
return 0; | |
} | |
static void __exit hook_test_mod_exit(void) { | |
pr_info("debug: module unloaded\n"); | |
} | |
module_init(hook_test_mod_init); | |
module_exit(hook_test_mod_exit); |
This file contains hidden or 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
#ifndef _RESOLV_DIRECT_HOOK_H_ | |
#define _RESOLV_DIRECT_HOOK_H_ | |
#include <asm/unistd.h> | |
#include "resolve_kallsyms.h" | |
#include "set_page_flags.h" | |
struct direct_syscall_hook { | |
int number; | |
void *new; | |
void *orig; | |
}; | |
void **sys_call_table_addr = NULL; | |
static int resolve_syscall_table(void) { | |
sys_call_table_addr = kallsyms_lookup_name_("sys_call_table"); | |
return 0; | |
} | |
void hook_syscall(struct direct_syscall_hook *hook) { | |
if (!sys_call_table_addr) { | |
resolve_syscall_table(); | |
} | |
*((uintptr_t *) hook->orig) = sys_call_table_addr[hook->number]; | |
pte_t *ptep = page_from_virt(&sys_call_table_addr[hook->number]); | |
pr_info("debug: ptep @ %pK, pte_write flag (%i)\n", &sys_call_table_addr[hook->number], pte_write(*ptep)); | |
pr_info("debug: flipping write protect flag...\n"); | |
pte_flip_write_protect(page_from_virt(&sys_call_table_addr[hook->number])); | |
ptep = page_from_virt(&sys_call_table_addr[hook->number]); | |
pr_info("debug: ptep @ %pK, pte_write flag (%i)\n", &sys_call_table_addr[hook->number], pte_write(*ptep)); | |
sys_call_table_addr[hook->number] = hook->new; | |
pr_info("debug: hook_syscall of #%i, orig @ %pK, new @%pK, success\n", hook->number, hook->orig, hook->new); | |
} | |
void unhook_syscall(struct direct_syscall_hook *hook) { | |
if (!sys_call_table_addr) { | |
resolve_syscall_table(); | |
} | |
sys_call_table_addr[hook->number] = hook->orig; | |
pr_info("debug: unhook_syscall of #%i, orig restored @ %pK, new @%pK, success\n", hook->number, hook->orig, hook->new); | |
} | |
#endif |
This file contains hidden or 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
#ifndef _RESOLV_KALLSYMS_H_ | |
#define _RESOLV_KALLSYMS_H_ | |
#include <linux/kprobes.h> | |
#include <linux/ftrace.h> | |
#include <asm/unistd.h> | |
typedef uintptr_t (*kallsyms_lookup_name_t)(const char *symbol_name); | |
static kallsyms_lookup_name_t kallsyms_lookup_name__ = NULL; | |
uintptr_t kprobe_get_func_addr(const char *func_name) { | |
static struct kprobe kp; | |
kp.symbol_name = func_name; | |
if (register_kprobe(&kp) < 0) { | |
pr_info("debug: kprobe_get_func_addr of %s failed\n", func_name); | |
return -ENOENT; | |
} | |
uintptr_t tmp = kp.addr; | |
unregister_kprobe(&kp); | |
pr_info("debug: kprobe_get_func_addr %s @ %pK\n", func_name, tmp); | |
return tmp; | |
} | |
uintptr_t kallsyms_lookup_name_(const char *symbol_name) { | |
if (!kallsyms_lookup_name__) { | |
kallsyms_lookup_name__ = kprobe_get_func_addr("kallsyms_lookup_name"); | |
} | |
uintptr_t tmp = kallsyms_lookup_name__(symbol_name); | |
pr_info("debug: kallsyms_lookup_name_ %s @ %pK\n", symbol_name, tmp); | |
return tmp; | |
} | |
#endif |
This file contains hidden or 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
#ifndef _SET_PAGE_FLAGS_H_ | |
#define _SET_PAGE_FLAGS_H_ | |
#include <asm/pgtable.h> | |
#include "resolve_kallsyms.h" | |
pte_t *page_from_virt(uintptr_t addr) { | |
pgd_t *pgd; | |
pud_t *pud; | |
pmd_t *pmd; | |
pte_t *ptep; | |
struct mm_struct *init_mm_ptr = kallsyms_lookup_name_("init_mm"); | |
pgd = pgd_offset(init_mm_ptr, addr); | |
if (pgd_none(*pgd) || pgd_bad(*pgd)) { | |
return NULL; | |
} | |
pud = pud_offset(pgd, addr); | |
if (pud_none(*pud) || pud_bad(*pud)) { | |
return NULL; | |
} | |
pmd = pmd_offset(pud, addr); | |
if (pmd_none(*pmd) || pmd_bad(*pmd)) { | |
return NULL; | |
} | |
ptep = pte_offset_map(pmd, addr); | |
if (!ptep) { | |
return NULL; | |
} | |
return ptep; | |
} | |
void pte_flip_write_protect(pte_t *ptep) { | |
if (!pte_write(*ptep)) { | |
*ptep = pte_mkwrite(pte_mkdirty(*ptep)); | |
*ptep = clear_pte_bit(*ptep, __pgprot((_AT(pteval_t, 1) << 7))); | |
return; | |
} | |
pte_wrprotect(*ptep); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment