#include<linux/init.h>
#include<linux/module.h>
#include<linux/moduleparam.h>
#include<linux/unistd.h>
#include<linux/sched.h>
#include<linux/syscalls.h>
#include<linux/string.h>
#include<linux/fs.h>
#include<linux/fdtable.h>
#include<linux/uaccess.h>
#include <linux/kallsyms.h>
#include<linux/rtc.h>
#include<linux/vmalloc.h>
#include <linux/slab.h>
//module macros
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("hook sys_mkdir");
unsigned long _sys_call_table = 0;
static void*
get_lstar_dosys_addr(void){
unsigned long lstar;
// temp variables for scan
unsigned int i;
unsigned char *off;
rdmsrl(MSR_LSTAR, lstar);
// print out int 0x80 handler
printk("[+] entry_SYSCALL_64 is at 0x%lx\n", lstar);
// scan for known pattern(0xff14c5xx)
// pattern is just before sys_call_table address
for(i = 0; i <= PAGE_SIZE; i++) {
off = (char*)lstar + i;
if(*(off) == 0x48 && *(off+1) == 0x89 && *(off+2) == 0xe6) {
return (off + 3); //call do_syscall_64
}
}
return NULL;
}
static void*
get_lstar_dosys(void)
{
unsigned long* lstar_dosys_addr = get_lstar_dosys_addr();
if(lstar_dosys_addr != NULL) {
printk("[+] call_do_syscall_64 at: 0x%lx\n", lstar_dosys_addr);
unsigned int offset = *(unsigned int*)((char*)lstar_dosys_addr + 1);
printk("[+] offset is: 0x%08x\n", offset);
unsigned long base = 0xffffffff00000000;
return (void*)(base | ((unsigned long)lstar_dosys_addr + 5 + offset));
}
return NULL;
}
static void*
get_sys_sct_addr(unsigned long* do_syscall_64_addr)
{
unsigned char* off;
int i;
for(i = 0; i <= PAGE_SIZE; i++) {
off = (char*)do_syscall_64_addr + i;
if(*(off) == 0x48 && *(off+1) == 0x8b && *(off+2) == 0x04 && *(off+3) == 0xfd) {
return (off+4);
}
}
return NULL;
}
static void*
get_sys_sct(unsigned long* do_syscall_64_addr)
{
unsigned long* sct_addr = get_sys_sct_addr(do_syscall_64_addr);
if(!sct_addr){
return NULL;
}
unsigned int offset = *(unsigned int*)(sct_addr);
unsigned long base = 0xffffffff00000000;
return (void*)(base | offset);
}
//hooked execve
static int hook_execve_init(void){
printk("[+] Finding sys_call_table\n");
unsigned long* do_syscall_64_addr = 0;
do_syscall_64_addr = get_lstar_dosys();
if(!do_syscall_64_addr){
printk("[x] Failed to find do_syscall_64_addr\n");
return 0;
}
printk("[+] Found do_syscall_64_addr at: 0x%lx\n", do_syscall_64_addr);
_sys_call_table = get_sys_sct(do_syscall_64_addr);
if(!_sys_call_table) {
printk("[x] Failed to find sys_call_table\n");
return 0;
}
printk("[+] Found sys_call_table at: 0x%lx\n", _sys_call_table);
return 0;
}
// initialize the module
static int hooked_init(void) {
get_lstar_dosys_addr();
return 0;
}
static void hooked_exit(void) {
}
/*entry/exit macros*/
module_init(hooked_init);
module_exit(hooked_exit);