如何在Linux上挂起send()/ recv()函数?

时间:2016-05-23 18:58:02

标签: c++ c unix elf abi

我试图在Linux上用C ++挂钩recv()send()函数。

我知道how to hook functions (github: zeek/subhook)。 但是,我希望了解如何查找recv()send()功能的帮助。地址(在运行时,或与版本无关的解决方案)。

我可以使用任何类型的文档或建议来帮助我理解这里涉及的机制。

[编辑]澄清:我不想使用LD_PRELOAD=因为我使用此工具注入我的共享库:linux-inject

3 个答案:

答案 0 :(得分:4)

请参阅What is the LD_PRELOAD trick?

基本上,您编写的方法与您要挂钩的方法具有相同的签名。在这种情况下sendrecv。然后,将LD_PRELOAD设置为指向新库。加载器将首先找到您的函数并调用它。

在您的库中,您可以包装原始代码,完全替换它,修改输入或输出,基本上任何东西。

对于一些示例代码,请参阅此文章 dlsym and ld preload

发送的一个例子是:

ssize_t (*original_send)(int sockfd, const void *buf, size_t len, int flags);
original_send = dlsym(RTLD_NEXT, "send");
return (*original_send)( /args/ );

答案 1 :(得分:1)

如果目标程序设计用于注射

一个场所是通过gdb注入。但是It's not trivial。但是你已经覆盖了它。

至于在运行时查找地址,您应该查看how gdb does it。您可能会发现一些已封装此行为的库。

如果你可以设计目标程序来挂钩

有更简单的方法可以实现这一点,例如LD_PRELOAD技巧和其他共享库技巧,可能还有无数其他技巧。但要获取recvsend的地址,您可以按照

的方式执行操作
#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>

int main()
{
  printf("pid %d\n", getpid());
  printf("Address of recv: %p\n", recv);
  printf("Address of send: %p\n", send);

  for (;;) {
    sleep(1);
  }
}

在我的系统上运行,

$ ./a.out
pid 21266
Address of recv: 0x7fff86abedf3
Address of send: 0x7fff86abee03

用gdb仔细检查,

$ gdb -p 21266
(gdb) p (void*)recv
$4 = (void *) 0x7fff86abedf3 <recv>

答案 2 :(得分:1)

考虑使用plthook 库。幸运的是,有一个例子如何在主页上挂钩recv。该库迭代所有load time relocations并替换给定模块的所有目标函数。

函数地址只是存储函数指令的地方。如果你想通过指针替换轻松地在Linux(ELF)上挂钩,你将不得不改变调用这个函数的所有地方,而不是函数本身。

如果您只想更改recv / send代码,请考虑trampolining这些功能。