[kernel] hook sys_call_table
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``다.
'OS > Kernel' 카테고리의 다른 글
CVE-2017-1000112 : Exploitable memory corruption due to UFO to non-UFO path switch (0) | 2017.11.08 |
---|---|
[kernel] current 구조체 / cred 수정 (0) | 2017.10.22 |
[kernel] get sys_call_table (0) | 2017.10.16 |
[kernel] Page Protection (0) | 2017.10.16 |
[kernel] addr_limit : kernel space arg (0) | 2017.10.15 |