[kernel] LKM, Loadable Kernel Module / Kernel Compile
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를 따른다.
참고하면 좋다.
'OS > Kernel' 카테고리의 다른 글
[kernel] Page Protection (0) | 2017.10.16 |
---|---|
[kernel] addr_limit : kernel space arg (0) | 2017.10.15 |
[kernel] virt_to_phys (0) | 2017.10.13 |
[kernel] exploit (0) | 2017.10.06 |
Interrupt (0) | 2016.10.07 |