void symbol_restore(struct kernsym *sym) { bool pte_ro; if (sym->hijacked) { set_addr_rw((unsigned long) sym->addr, &pte_ro); memcpy(sym->addr, &sym->orig_start_bytes[0], OP_JMP_SIZE); set_addr_ro((unsigned long) sym->addr, pte_ro); sym->hijacked = false; malloc_free(sym->new_addr); } if (sym->name_alloc) { malloc_free(sym->name); sym->name_alloc = false; } return; }
int __init init_hooking(void) { sys_call_table = (void*)0xffffffff81600300; original_call = (uint64_t(*)(void))(sys_call_table[__NR_regdev]); set_addr_rw((unsigned long)sys_call_table); sys_call_table[__NR_regdev] = our_sys_open; return 0; }
static void proc_init(void) { uptime_proc_file = create_proc_entry(MODULE_NAME, 0, NULL); if (uptime_proc_file == NULL) { #ifdef DEBUG printk(KERN_ALERT "%s error: could not create temporary /proc entry\n", MODULE_NAME); #endif proc_failed = 1; return; } proc_root = uptime_proc_file->parent; if (proc_root == NULL || strcmp(proc_root->name, "/proc") != 0) { #ifdef DEBUG printk(KERN_ALERT "%s error: could not identify /proc root entry\n", MODULE_NAME); #endif proc_failed = 1; return; } proc_root_fops = (struct file_operations *)proc_root->proc_fops; remove_proc_entry("temp_hack", NULL); uptime_proc_file = proc_root->subdir; while (uptime_proc_file) { if (strcmp(uptime_proc_file->name, PROCFS_NAME) == 0) goto found; uptime_proc_file = uptime_proc_file->next; } proc_failed = 1; #ifdef DEBUG printk(KERN_ALERT "%s did not found /proc/%s file", MODULE_NAME, PROCFS_NAME); #endif return; found: uptime_proc_fops = (struct file_operations *)uptime_proc_file->proc_fops; old_uptime_proc_open = uptime_proc_fops->open; if (uptime_proc_fops != NULL) { set_addr_rw(uptime_proc_fops); uptime_proc_fops->open = uptime_proc_open; set_addr_ro(uptime_proc_fops); #ifdef DEBUG printk(KERN_INFO "%s: successfully wrapped /proc/%s\n", MODULE_NAME, PROCFS_NAME); #endif } }
static void proc_cleanup(void) { if (!proc_failed && (uptime_proc_fops != NULL)) { set_addr_rw(uptime_proc_fops); uptime_proc_fops->open = old_uptime_proc_open; set_addr_ro(uptime_proc_fops); #ifdef DEBUG printk(KERN_INFO "%s: successfully unwrapped /proc/%s\n", MODULE_NAME, PROCFS_NAME); #endif } #ifdef DEBUG else printk(KERN_INFO "%s: nothing to unwrap, exiting\n", MODULE_NAME); #endif }
int symbol_hijack(struct kernsym *sym, const char *symbol_name, unsigned long *code) { int ret; unsigned long orig_addr; unsigned long dest_addr; unsigned long end_addr; u32 *poffset; struct insn insn; bool pte_ro; ret = find_symbol_address(sym, symbol_name); if (IN_ERR(ret)) return ret; if (*(u8 *)sym->addr == OP_JMP_REL32) { printk(PKPRE "error: %s already appears to be hijacked\n", symbol_name); return -EFAULT; } sym->new_addr = malloc(sym->size); if (sym->new_addr == NULL) { printk(PKPRE "Failed to allocate buffer of size %lu for %s\n", sym->size, sym->name); return -ENOMEM; } memset(sym->new_addr, 0, (size_t)sym->size); if (sym->size < OP_JMP_SIZE) { ret = -EFAULT; goto out_error; } orig_addr = (unsigned long)sym->addr; dest_addr = (unsigned long)sym->new_addr; end_addr = orig_addr + sym->size; while (end_addr > orig_addr && *(u8 *)(end_addr - 1) == '\0') --end_addr; if (orig_addr == end_addr) { printk(PKPRE "A spurious symbol \"%s\" (address: %p) seems to contain only zeros\n", sym->name, sym->addr); ret = -EILSEQ; goto out_error; } while (orig_addr < end_addr) { tpe_insn_init(&insn, (void *)orig_addr); tpe_insn_get_length(&insn); if (insn.length == 0) { printk(PKPRE "Failed to decode instruction at %p (%s+0x%lx)\n", (const void *)orig_addr, sym->name, orig_addr - (unsigned long)sym->addr); ret = -EILSEQ; goto out_error; } copy_and_fixup_insn(&insn, (void *)dest_addr, sym); orig_addr += insn.length; dest_addr += insn.length; } sym->new_size = dest_addr - (unsigned long)sym->new_addr; sym->run = sym->new_addr; set_addr_rw((unsigned long) sym->addr, &pte_ro); memcpy(&sym->orig_start_bytes[0], sym->addr, OP_JMP_SIZE); *(u8 *)sym->addr = OP_JMP_REL32; poffset = (u32 *)((unsigned long)sym->addr + 1); *poffset = CODE_OFFSET_FROM_ADDR((unsigned long)sym->addr, OP_JMP_SIZE, (unsigned long)code); set_addr_ro((unsigned long) sym->addr, pte_ro); sym->hijacked = true; return 0; out_error: malloc_free(sym->new_addr); return ret; }