LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1968|回复: 12

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

[复制链接]
发表于 2008-11-2 16:29:20 | 显示全部楼层 |阅读模式
具体是这样的,比如用户调用read,write系统函数,我如何把read,write函数的地址改成我的自定义函数的地址,然后我会在自定义的函数中自己做一些处理,之后我会调用真正的read,write,而且这在用户层是完全完全透明的。有谁知道这种技术吗?
发表于 2008-11-2 19:31:42 | 显示全部楼层
google: Linux API Hooking
回复 支持 反对

使用道具 举报

发表于 2008-11-3 16:43:11 | 显示全部楼层
ptrace系统调用。应该能满足你需要,包括查看修改read的参数。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2008-11-4 11:25:55 | 显示全部楼层
Post by souldump;1903308
ptrace系统调用。应该能满足你需要,包括查看修改read的参数。

ptrace只能用在一个特定的程序上,我的想法是只需要覆盖一次read,write系统调用,这个系统的所有程序都会调用我定义的read,write.
回复 支持 反对

使用道具 举报

发表于 2008-11-5 19:58:36 | 显示全部楼层
直接找到CODE修改read,write函数不行么?

偶是菜鸟~
回复 支持 反对

使用道具 举报

发表于 2008-11-6 11:07:36 | 显示全部楼层
内核里可以拦截系统调用,
用户层可以直接覆盖(貌似), 我试了一下,一些不明白的地方帮我解释解释:


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <dlfcn.h>

  6. ssize_t (*old_write)();
  7. // old_write = 0xb7ed71a0; 这样硬覆盖不成功, 能够实现吗?

  8. ssize_t write(int fd, const void *buf, const size_t count);

  9. ssize_t write(int fd, const void *buf, const size_t count) {
  10.   printf("this is my write!!!\n");
  11.   old_write(fd, buf, count);
  12. }

  13. int main(void) {
  14.   void *handle;
  15.   handle = dlopen("libc.so.6", RTLD_LAZY);
  16. // libc.so为什么不行?/usr/lib/libc.so /lib/libc.so.6不一样
  17.   if (!handle) {
  18.     fprintf(stderr, "%s\n", dlerror());
  19.     exit(2);
  20.   }
  21.   dlerror();
  22.   old_write = dlsym(handle, "write");
  23.   write(1, "asd\n", 4 );
  24.   dlclose(handle);
  25.   return(0);
  26. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2008-11-6 11:30:01 | 显示全部楼层
依葫芦画瓢第二版:



  1. #include <stdio.h>
  2. #include <string.h>

  3. #define write my_write

  4. unsigned int my_write(int fd, char *buf, int size);

  5. unsigned int my_write(int fd, char *buf, int size) {
  6.   unsigned int ret;
  7.   printf("haha, u r in my write\n\n");
  8.   __asm__("movl $4, %%eax; int $0x80;"
  9.           : "=r" (ret)
  10.           : "r" (fd), "r" (buf), "r" (size)
  11.           : "%eax"
  12.           );
  13.   return ret;
  14. }

  15. int main(void) {
  16.   char *buf = "hahaha\n";
  17.   unsigned int size = strlen(buf);
  18.   unsigned int ret;

  19.   write(1, buf, size);
  20.   return(0);
  21. }

复制代码
回复 支持 反对

使用道具 举报

发表于 2008-11-6 12:22:29 | 显示全部楼层
当进行了覆盖后, 原始的 write 可以通过 dlopen() 打开 libc 直接加载到某一个指针上
回复 支持 反对

使用道具 举报

发表于 2008-11-13 00:06:46 | 显示全部楼层
dlopen的hook其实是一种欺骗系统的方法,其实道理很简单:你写了write就会调用你的函数,而不会去找libc的。所谓的dlopen只是为了实现“继承”原始函数的功能。

再者,楼主说的是覆盖系统调用,而大家介绍的是覆盖库函数,这在有些时候区别还是有的
回复 支持 反对

使用道具 举报

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

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

使用道具 举报

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

本版积分规则

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