Linux系统调用函数替换
===================
#### 获取系统调用数组首地址
首先寻找一个系统调用函数,我们选择sys_close函数。根据这个地址进行偏移,当某个偏移地址+__NR_close的值等于sys_close相等时,则认为此偏移后的地址为系统调用首地址。
点击(此处)折叠或打开
- unsigned long **find_sys_call_table(void) {
- unsigned long ptr;
- unsigned long *p;
- pr_err("Start found sys_call_table.\n");
- for (ptr = (unsigned long)sys_close;
- ptr < (unsigned long)&loops_per_jiffy;
- ptr += sizeof(void *)) {
- p = (unsigned long *)ptr;
- if (p[__NR_close] == (unsigned long)sys_close) {
- pr_err("Found the sys_call_table!!! __NR_close[%d] sys_close[%lx]\n"
- " __NR_execve[%d] sct[__NR_execve][0x%lx]\n",
- __NR_close,
- (unsigned long)sys_close,
- __NR_execve,
- p[__NR_execve]);
- return (unsigned long **)p;
- }
- }
- return NULL;
- }
#### 修改指定的系统调用
因为系统调用的数组是只读类型的,所以其值是不可以修改的,因此我们需要将只读保护位去掉。
cr0中有一个WP位,wp位0禁止写保护实模式。wp为1开启写保护 保护模式。
wp对应的位为:0x00010000
点击(此处)折叠或打开
- unsigned long original_cr0;
- original_cr0 = read_cr0(); #获取rc0寄存器数据
- write_cr0(original_cr0 & ~0x00010000); #将常量保护标记位去掉
- ##此处修改系统调用表等操作
- write_cr0(original_cr0); #将寄存器值恢复,常量保护恢复
代码如下:
内核模块init时:
点击(此处)折叠或打开
- void *orig_sys_call_table [NR_syscalls];
- original_cr0 = read_cr0();
- write_cr0(original_cr0 & ~0x00010000);
- pr_err("Loading module change_write, sys_call_table at %p\n", sys_call_table_ptr);
- for(i = 0; i < NR_syscalls - 1; i ++) {
- orig_sys_call_table[i] = sys_call_table_ptr[i];
- }
- orig_write = (void *)(sys_call_table_ptr[__NR_write]);
- sys_call_table_ptr[__NR_write]= (void *)my_write;
- write_cr0(original_cr0);
内核模块exit时,恢复正常write函数:
点击(此处)折叠或打开
- write_cr0(original_cr0 & ~0x00010000);
- sys_call_table_ptr[__NR_write] = (void *)orig_write;
- write_cr0(original_cr0);
#### 修改sys_execve系统调用
修改sys_execve函数不像普通系统调用一样,在此系统调用执行之前先进拦截或者记录相关信息的操作,就需要进行平衡栈。
在替换系统调用时需要调用此汇编函数,将my_stub_execve_hook替换原有的系统调用,当进入此函数时,先将寄存器入栈,再执行自定义函数(比如行为记录,行为拦截等功能),自定义函数执行完成后,将之前入栈的寄存器恢复出来,然后再执行原生的execve函数:
sys_call_table_ptr[__NR_execve]= (void*)my_stub_execve_hook;
execve必须执行栈平衡,这是和其他系统调用区别的地方。
点击(此处)折叠或打开
- .text
- .global my_stub_execve_hook
- my_stub_execve_hook:
- pushq %rbx
- pushq %rdi
- pushq %rsi
- pushq %rdx
- pushq %rcx
- pushq %rax
- pushq %r8
- pushq %r9
- pushq %r10
- pushq %r11
- call my_execve_hook
- pop %r11
- pop %r10
- pop %r9
- pop %r8
- pop %rax
- pop %rcx
- pop %rdx
- pop %rsi
- pop %rdi
- pop %rbx
- jmp *orig_sys_call_table(, %rax, 8)