高级Linux Kernel Inline Hook技术分析与实现
[目录]
1. 简述
2. 更改offset实现跳转
3. 补充
4. 如何查杀
5. 实例
一、简述
目前流行和成熟的kernel inline hook技术就是修改内核函数的opcode,通过写入jmp或push ret等指令跳转到新的内核函数中,从而达到修改或过滤的功能。这些技术的共同点就是都会覆盖原有的指令,这样很容易在函数中通过查找jmp,push ret等指令来查出来,因此这种inline hook方式不够隐蔽。本文将使用一种高级inline hook技术来实现更隐蔽的inlinehook技术。
二、更改offset实现跳转
如何不给函数添加或覆盖新指令,就能跳转到我们新的内核函数中去呢?我们知道实现一个系统调用的函数中不可能把所有功能都在这个函数中全部实现,它必定要调用它的下层函数。如果这个下层函数也可以得到我们想要的过滤信息等内容的话,就可以把下层函数在上层函数中的offset替换成我们新的函数的offset,这样上层函数调用下层函数时,就会跳到我们新的函数中,在新的函数中做过滤和劫持内容的工作。原理是这样的,具体来分析它该怎么实现, 我们去看看sys_read的具体实现:
linux-2.6.18/fs/read_write.c
asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
{
struct file *file;
ssize_t ret = -EBADF;
int fput_needed;
file = fget_light(fd, &fput_needed);
if (file) {
loff_t pos = file_pos_read(file);
ret = vfs_read(file, buf, count, &pos);
file_pos_write(file, pos);
fput_light(file, fput_needed);
}
return ret;
}
EXPORT_SYMBOL_GPL(sys_read);
我们看到sys_read最终是要调用下层函数vfs_read来完成读取数据的操作,所以我们不需要给sys_read添加或覆盖指令, 而是要更改vfs_read在sys_read代码中的offset就可以跳转到我们新的new_vfs_read中去。如何修改vfs_read的offset呢?先反汇编下sys_read看看:
[root@xsec linux-2.6.18]# gdb -q vmlinux
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) disass sys_read
Dump of assembler code for function sys_read:
0xc106dc5a
0xc106dc5b
0xc106dc5d
0xc106dc5e
0xc106dc63
0xc106dc64
0xc106dc67
0xc106dc6a
0xc106dc6d
0xc106dc72
0xc106dc74
0xc106dc76
0xc106dc78
0xc106dc7b
0xc106dc7e
0xc106dc81
0xc106dc84
0xc106dc87
0xc106dc8a
0xc106dc8d
0xc106dc8e
0xc106dc90
0xc106dc95
0xc106dc98
0xc106dc9a
0xc106dc9d
0xc106dca0
0xc106dca3
0xc106dca7
0xc106dca8
0xc106dcaa
0xc106dcac
0xc106dcb1
0xc106dcb4
0xc106dcb6
0xc106dcb7
0xc106dcb8
0xc106dcb9
End of assembler dump.
(gdb)
0xc106dc90