2

I'm trying to hook recv() and send() functions in C++ on Linux.

I know how to hook functions (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).

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.

ivaigult
  • 6,198
  • 5
  • 38
  • 66
Jules Lamur
  • 2,078
  • 1
  • 15
  • 25
  • And your question is? Show us what you have tried do far. – orbitcowboy May 23 '16 at 19:02
  • @orbitcowboy I didn't try anything, I googled about my question, but all I found is about Windows... My question is **How to find `recv()` or `send()` functions' addresses at runtime.** – Jules Lamur May 23 '16 at 19:06
  • @Chad Could you go further ? I only see in `LD_PRELOAD=` a way to inject your library... – Jules Lamur May 23 '16 at 19:11
  • 1
    send and recv seem to be syscall wrappers. Perhaps they are inlined in your program, which will make it impossible to "hook" them by a preloading trick. What *exactly* do you wanna intercept? The *syscall* `recv` and `send` respectively, or the glibc syscall-*wrapper*? – Johannes Schaub - litb May 23 '16 at 19:25
  • @Johannes Schaub - litb `recv` and `send` are libc functions – ivaigult May 23 '16 at 20:19

3 Answers3

6

See What is the LD_PRELOAD trick?.

Basically you write a method with the same signature as the one you want to hook. In this case send and recv. You then set LD_PRELOAD to point to your new library. 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

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/ );
Community
  • 1
  • 1
Paul Rubel
  • 26,632
  • 7
  • 60
  • 80
1

If the target program was not designed for injection

One venue is to inject via 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. 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. But to get the addresses of recv and send, you could do something along the lines of

#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 -p 21266
(gdb) p (void*)recv
$4 = (void *) 0x7fff86abedf3 <recv>
csl
  • 10,937
  • 5
  • 57
  • 89
1

Consider using plthook library. Fortunately there is example how to hook recv on the main page. 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.

If you want to change only recv/send code, consider trampolining the functions.

ivaigult
  • 6,198
  • 5
  • 38
  • 66