hook sys_call_table

```c

#include <linux/module.h>    // included for all kernel modules

#include <linux/kernel.h>    // included for KERN_INFO

#include <linux/init.h>      // included for __init and __exit macros

#include <linux/cred.h>

 

MODULE_LICENSE("GPL");

MODULE_AUTHOR("umbum");

MODULE_DESCRIPTION("sys_call_table hooking test");


#define page_offset 0xc0000000

#define phys_offset 0x1a000000


// #define __NR_write 4

#define __NR_target 4


typedef asmlinkage long (*sys_write_t)(unsigned int fd, const char __user *buf, size_t count);


sys_write_t orig_sys_write;

unsigned long **sct;


asmlinkage long hook_sys_write(unsigned int fd, char __user *buf, size_t count){

    if (!strcmp(buf, "bum")){

        buf[0] = 'B';  // not string, but char

        buf[1] = 'U';  // so, these are not affected by addr_limit

        buf[2] = 'M';

    }


    return orig_sys_write(fd, buf, count);

}


static unsigned long **get_sys_call_table(void){

    return page_offset + phys_offset + 0x005d3160; // sct_offset

}



static void set_page_rw(unsigned long addr, int bit){

    unsigned int level;

    pte_t *pte;


    pte = lookup_address(addr, &level);

    if (bit == 1) {

        pte->pte |= _PAGE_RW;

    }

    else {

            pte->pte &= ~_PAGE_RW;

    }

}



static int __init b_hook_init(void)

{

    sct = get_sys_call_table();


    printk(KERN_INFO "b_hook LKM is loaded\n");

    printk("origin   sct[__NR_target]  %p : %p : %p\n", &sct[__NR_target], sct[__NR_target], *sct[__NR_target]); 


    orig_sys_write = (sys_write_t)sct[__NR_target];

    set_page_rw((unsigned long)sct, 1);

    sct[4] = (unsigned long *)hook_sys_write; 


    printk("hooked   sct[__NR_target]  %p : %p : %p\n", &sct[__NR_target], sct[__NR_target], *sct[__NR_target]); 


    return 0;    // Non-zero return means that the module couldn't be loaded.

}

 

static void __exit b_hook_exit(void)

{

    sct[__NR_target] = (unsigned long *)orig_sys_write;

    set_page_rw((unsigned long)sct, 0);

    printk("restored sct[__NR_target]  %p : %p : %p\n", &sct[__NR_target], sct[__NR_target], *sct[__NR_target]); 

    printk(KERN_INFO "b_hook LKM is removed.\n");

}

 

module_init(b_hook_init);

module_exit(b_hook_exit);

```
  • LKM make 시 타입을 꽤 엄격하게 따지기 때문에, type casting 잘 해주어야 한다.
  • `` buf``의 내용을 수정하기 위해 ``c hook_sys_write()`` 의 인자에 ``c const``를 제거했는데, 잘 동작한다.
    이런 식으로 실제로는 상수가 아니지만, 함수 내부에서 변경하지 못하도록 설정하고 싶은 경우 ``c const``를 활용할 수 있을 것 같다.
  • ``c hook_sys_write()`` 내부에 있는 ``c printk()``가 제대로 로그를 찍어주지 않는다. 단순히 `` dmesg``로 확인이 안될 뿐 버퍼에 쌓이는 건가 싶었는데 `` rmmod``하고 난 이후에도 로그가 찍히지 않는걸로 보아 그냥 유실되는 것 같다.


``c asmlinkage``를 지정하면 어셈블리 코드에서 해당 함수를 직접 호출할 수 있다.

컴파일 시 함수의 인자 전달 방식이 레지스터를 사용하는 방식으로 지정될 경우,

assembly code에서 이 함수를 호출할 때 레지스터를 사용해 인자를 전달하도록 코딩하지 않는다면 함수에서 인자를 제대로 받을 수 없다.

따라서 모든 인자를 스택으로 받도록 지정하는 것이 ``c asmlinkage``다.