엄범

Loadable Kernel Module


Note ) root가 아니면 `` insmod``를 사용할 수 없기 때문에, LKM을 등록할 수 없다.

LKM을 이용하면 커널을 recompile/reboot하지 않아도 커널에 기능을 추가/확장할 수 있다.
따라서 syscall을 추가하고, hooking하는 것도 가능하다.
드라이버가 대체로 LKM으로 구현되어 있다.
확장자는 `` *.ko`` 다.
```bash
lsmod      // list
insmod     // insert

rmmod      // remove

modinfo    // info

modprobe   // insmod와 달리 의존 관계에 있는 모듈까지 insert해준다.

```


LKM 추가하기

```bash
apt-get install build-essential linux-headers-$(uname -r)
```
컴파일에 필요한 헤더 다운. ``bash /usr/src/linux-headers-$(uname -r)`` 경로에 다운로드 되며 나중에 Makefile에서 이 곳을 참조하도록 설정하게 된다.
안나오는 경우 `` apt-cache search``해보면 조회는 되는데 kernel 버전이 다를 것이다.
이런 경우 다른 버전으로 `` make``까지는 가능한데, `` insmod``에서 잘못된 module이라고 뜨며 로드가 안된다.

1. sym_print.c 작성

LKM 내부에서도 ``c strcmp()`` 등을 사용할 수 있다.
```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
 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("umbum");
MODULE_DESCRIPTION("sys_call_table hooking test");
 
static int __init sym_print_init(void)
{
    unsigned long *k = 0xc2072f60;
    unsigned long *s = 0xc1072f60;
    unsigned long **sct = 0xc25d3160;
    printk(KERN_INFO "sym_print LKM!\n");
    printk("kallsyms sys_getpid   %p : %p\n", k, *k);
    printk("System.map sys_getpid %p : %p\n", s, *s);
    printk("sct[20(__NR_getpid)]  %p : %p : %p\n", &sct[20], sct[20], *sct[20]); 
    return 0;    // Non-zero return means that the module couldn't be loaded.
}
 
static void __exit sym_print_exit(void)
{
    printk(KERN_INFO "sym_print LKM removed.\n");
}
 
module_init(sym_print_init);
module_exit(sym_print_exit);
```

2. Makefile 작성

  • .o라고 적혀있다고 컴파일할 필요 없음.
  • 어디서 make하든 경로는 상관 없다.
  • -C 옵션으로 적은 경로가 include path다.
  • 앞에 한 칸의 tab이 들어가야 한다.
```bash
obj-m += sym_print.o
 
all:
[\t]make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
 
clean:
[\t]make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
```


3. make

```bash
root@kali32:~/add_syscall# make
make -C /lib/modules/4.13.0-kali1-686-pae/build M=/root/add_syscall modules
make[1]: Entering directory '/usr/src/linux-headers-4.13.0-kali1-686-pae'
  CC [M]  /root/add_syscall/sym_print.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /root/add_syscall/sym_print.mod.o
  LD [M]  /root/add_syscall/sym_print.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.13.0-kali1-686-pae'
root@kali32:~/add_syscall# ls
Makefile        sym_print.c   sym_print.mod.c  sym_print.o
Module.symvers  sym_print.ko  sym_print.mod.o  modules.order
```

4. 

```bash
root@kali32:~/add_syscall# insmod sym_print.ko
root@kali32:~/add_syscall# dmesg | tail -4
[11061.736957] sym_print LKM!
[11061.736962] kallsyms sys_getpid   c2072f60 : 26748d3e
[11061.736964] System.map sys_getpid c1072f60 : 9a67ff72
[11061.736965] sct[20(__NR_getpid)]  c25d31b0 : c2072f60 : 26748d3e
root@kali32:~/add_syscall# dmesg | tail -1
[11076.582411] sym_print LKM removed.
```

Kernel Compile

recompile이라고 나와있지만, compile도 동일한 프로세스로 진행된다.
kali compile이지만 보편적인 compile process를 따른다.

참고하면 좋다.