简体   繁体   English

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

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

I'm trying to hook recv() and send() functions in C++ on Linux. 我正在尝试挂钩Linux上C ++中的recv()send()函数。

I know how to hook functions (github: zeek/subhook) . 我知道如何钩函数(github:zeek / subhook) But I would like some help to learn how to find recv() or send() functions' addresses (at runtime, or with a version independent solution ). 但是,我希望获得一些帮助,以学习如何查找recv()send()函数的地址(在运行时或使用版本无关的解决方案 )。

I'm open to any kind of documentation or advice that could help me to understand mechanisms involved here. 我乐于接受任何可以帮助我了解此处涉及的机制的文档或建议。


[EDIT] A clarification: I don't wanna use LD_PRELOAD= because I inject my shared library with this tool : linux-inject . [编辑]说明:我不想使用LD_PRELOAD=因为我使用此工具linux-inject注入了共享库。

See What is the LD_PRELOAD trick? 请参阅什么是LD_PRELOAD技巧? .

Basically you write a method with the same signature as the one you want to hook. 基本上,您编写的方法具有与要挂接的方法相同的签名。 In this case send and recv . 在这种情况下, sendrecv You then set LD_PRELOAD to point to your new library. 然后,您将LD_PRELOAD设置为指向新库。 The loader will find your function first and call it. 加载程序将首先找到您的函数并调用它。

In your library you can wrap the original code, completely replace it, modify inputs or outputs, basically anything. 在您的库中,您可以包装原始代码,完全替换它,修改输入或输出,基本上是任何东西。

For some example code see this turorial dlsym and ld preload 有关一些示例代码,请参见turorial dlsym和ld预加载

One example for send would be: 发送的一个示例是:

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

If the target program was not designed for injection 如果目标程序不是为注射设计的

One venue is to inject via gdb. 一种场所是通过gdb注入。 It's not trivial , though. 不过,这并非微不足道 But you've already got that covered. 但是您已经了解了这一点。

As for finding the addresses at runtime, you should check out how gdb does it . 至于在运行时查找地址,您应该检查一下gdb是如何做到的 You might find some libraries that have encapsulated this exact behaviour. 您可能会发现一些封装了此确切行为的库。

If you can design the target program for hooking 如果可以设计目标程序进行挂钩

There are simpler ways of achieving this, like the LD_PRELOAD trick and other shared library tricks, and probably countless others. 有更简单的方法可以实现此目的,例如LD_PRELOAD技巧和其他共享库技巧,并且可能还有无数其他方法。 But to get the addresses of recv and send , you could do something along the lines of 但是要获取recv的地址并send ,您可以按照以下步骤进行操作

#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);
  }
}

Running it on my system, 在我的系统上运行它

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

Double-checking with gdb, 用gdb仔细检查,

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

Consider using plthook library. 考虑使用plthook库。 Fortunately there is example how to hook recv on the main page. 幸运的是,有一个示例如何在主页上挂钩recv。 The library iterates over all load time relocations and replaces all the occurrences of the target function for a given module. 该库遍历所有加载时间重定位,并替换给定模块的所有出现的目标函数。

Function address is just the place where instructions for the function is stored. 功能地址只是功能说明的存储位置。 If you want to hook something on Linux (ELF) easily by pointer replace you will have to change all the places where this function is called, but not the function itself. 如果要通过指针替换轻松地在Linux(ELF)上挂接某些东西,则必须更改调用此函数的所有位置,但不能更改函数本身。

If you want to change only recv / send code, consider trampolining the functions. 如果只想更改recv / send代码,请考虑踩踏功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM