🏷️Getting the address of sys_call_table within an LKM (kernel version > 5.14.0)
📌Check the static sys_call_table address
- System.map에서 static address를 확인할 수 있다.
vi System.map-5.14.0
ffffffff82001680 D sys_call_table
📌Check the dynamic sys_call_table address
- 하지만, running kernel의 sys_call_table의 address를 가져오려면 다른 방법을 사용해야 한다.
- symbols of running kernel을 확인하려면 kallsyms에서 읽어야 한다.
cat /proc/kallsyms | grep sys_call_table
- 커널 버전에 따라 커널 모듈에서 sys_call_table 주소를 읽는 방법이 다르다.
- 🖇️cf. KASLR가 켜져있는 커널이라면, 부팅할 때마다 주소가 다르다. (일반적으로 켜져있다.)
📌Get the dynamic sys_call_table address within an LKM
- kprobe를 통해
kallsyms_lookup_name
함수의 주소를 가져온다.
- 🖇️cf. kprobe
- 커널에서 제공하는 도구로, 개발자가 커널의 실행 중인 특정 코드 위치에 동적으로 breakpoint를 설정할 수 있게 해준다.
- 커널 함수의 실행을 가로채거나 특정 지점에서 추가적인 코드를 실행시킬 수 있다.
- kprobe는 디버깅, 성능 분석, 시스템 모니터링 등 다양한 목적으로 사용될 수 있다.
- 아래 코드는 5.14.0 kernel에서 동작된다.
static unsigned long int **acquire_sys_call_table(void)
{
unsigned long int (*kallsyms_lookup_name)(const char *name);
struct kprobe kp = {
.symbol_name = "kallsyms_lookup_name",
};
if (register_kprobe(&kp) < 0){
return NULL;
}
kallsyms_lookup_name = (unsigned long (*)(const char *name))kp.addr;
unregister_kprobe(&kp);
return (unsigned long int **)kallsyms_lookup_name("sys_call_table");
}