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

How to hook send() / recv() functions on Linux?

我正在尝试在 Linux.

上挂接 C++ 中的 recv()send() 函数

我知道how to hook functions (github: zeek/subhook)。 但我想要一些帮助来学习如何找到 recv()send() 函数的地址(在运行时,或使用 版本独立解决方案 )。

我乐于接受任何类型的文档或建议,以帮助我理解此处涉及的机制。


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

如果目标程序不是为注入设计的

一个地方是通过gdb注入。 It's not trivial,虽然。但你已经知道了。

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

如果你能设计出hooking的目标程序

有更简单的方法可以实现这一点,例如 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
 = (void *) 0x7fff86abedf3 <recv>

参见 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/ );

考虑使用 plthook library. Fortunately there is example how to hook recv on the main page. The library iterates over all load time relocations 并替换给定模块的所有目标函数。

函数地址就是存放函数指令的地方。如果你想通过指针替换轻松地在 Linux (ELF) 上挂钩某些东西,你将必须更改调用此函数的所有位置,而不是函数本身。

如果您只想更改 recv/send 代码,请考虑 trampolining 函数。