Giter Club home page Giter Club logo

elf-hook's People

Contributors

bokic avatar laanwj avatar shoumikhin avatar umarcor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

elf-hook's Issues

Hooking multiple functions causes SEGV

I'm trying to hook the posix socket api

elf_hook(handle, base_address, "socket", hook_socket);
elf_hook(handle, base_address, "bind", hook_bind);
elf_hook(handle, base_address, "connect", hook_connect);
elf_hook(handle, base_address, "getpeername", hook_getpeername);
elf_hook(handle, base_address, "getsockname", hook_getsockname);
elf_hook(handle, base_address, "getsockopt", hook_getsockopt);
elf_hook(handle, base_address, "listen", hook_listen);
elf_hook(handle, base_address, "recv", hook_recv);
elf_hook(handle, base_address, "recvfrom", hook_recvfrom);
elf_hook(handle, base_address, "recvmsg", hook_recvmsg);
elf_hook(handle, base_address, "send", hook_send);
elf_hook(handle, base_address, "sendmsg", hook_sendmsg);
elf_hook(handle, base_address, "sendto", hook_sendto);
elf_hook(handle, base_address, "setsockopt", hook_setsockopt);
elf_hook(handle, base_address, "shutdown", hook_shutdown);
elf_hook(handle, base_address, "socketpair", hook_socketpair);

I can hook the first 6 functions

hooked(socket) original_function(0x7f8279c3c936)
hooked(bind) original_function(0xff04f3a7a808)
hooked(connect) original_function(0x4a8e56)
hooked(getpeername) original_function(0x4a8ff0)
hooked(getsockname) original_function(0x4a9126)
hooked(getsockopt) original_function(0x4a92c7)

and then it seg faults

#0  0x00000000004b2b59 in elf_hook \
    (module_filename=0x1498200 "/src/build/elfhook/libtest_api.so", \
     module_address=0x7f8279c3c000, \
     name=0x5671b2 "listen", \
     substitution=0x4a96a5 <hook_listen(int, int)>) at /src/elfhook/elf_hook.c:479
479             *(size_t *)(((size_t)module_address) + rel_plt_table[i].r_offset) = (size_t)substitution;  \
    //and replace it with the substitutional

Hooking a function which isn't used by the shared library causes a SEGV

Shared library does nothing:

class TestAPI
{
public:
    void work() {}
};

Here I hook the socket function in TestAPI:

#include <iostream>
#include "test_api.h"
#include "elf_hook.h"
#include <dlfcn.h>
#include <string.h>
#include <sys/socket.h>

int hook_socket(int domain, int type, int protocol)
{
    int fd = socket(domain, type, protocol);
    printf("socket: fd(%d) domain(%d) type(%d) protocol(%d)\n", fd, domain, type, protocol);
    return fd;
}

int main()
{
    TestAPI api;

    const char* filename = "/src/build/elfhook/libtest_api.so";

    void* handle = dlopen(filename, RTLD_LAZY);
    if (!handle)
        return 1;

    void* base_address = 0;
    if (get_module_base_address(filename, handle, &base_address) != 0)
        return 1;

    elf_hook(filename, base_address, "socket", (void*)hook_socket);

    api.work();

    return 0;
}

Running it seg faults:

$ ./elfhook/elfhook.bin 
Segmentation fault (core dumped)

GDB stack trace:

(gdb) where
#0  0xffff808868a96e0e in ?? ()
#1  0x00007f7797984c17 in _dl_fini () at dl-fini.c:235
#2  0x00007f7796720fe8 in __run_exit_handlers (status=0, listp=0x7f7796aaa5f8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true) at exit.c:82
#3  0x00007f7796721035 in __GI_exit (status=<optimized out>) at exit.c:104
#4  0x00007f7796707837 in __libc_start_main (main=0x409c31 <main()>, argc=1, argv=0x7ffe2f6cd6f8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffe2f6cd6e8) at ../csu/libc-start.c:325
#5  0x0000000000409b19 in _start ()

I'm running glibc-2.23:

$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.23-0ubuntu3) stable release version 2.23, by Roland McGr

According to the glibc source

  215           /* Is there a destructor function?  */
  216           if (l->l_info[DT_FINI_ARRAY] != NULL
  217               || l->l_info[DT_FINI] != NULL)
  218             {
  219               /* When debugging print a message first.  */
  220               if (__builtin_expect (GLRO(dl_debug_mask)
  221                         & DL_DEBUG_IMPCALLS, 0))
  222             _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n",
  223                       DSO_FILENAME (l->l_name),
  224                       ns);
  225 
  226               /* First see whether an array is given.  */
  227               if (l->l_info[DT_FINI_ARRAY] != NULL)
  228             {
  229               ElfW(Addr) *array =
  230                 (ElfW(Addr) *) (l->l_addr
  231                         + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr);
  232               unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val
  233                         / sizeof (ElfW(Addr)));
  234               while (i-- > 0)
  235                 ((fini_t) array[i]) ();         // this is the line that seg faults
  236             }
  237

If I change TestAPI::work to actually call socket, then it works fine

class TestAPI
{
public:
    void work() 
    {
        socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    }
};

Running now uses the hooked socket function, and no seg fault

$ ./elfhook/elfhook.bin 
socket: fd(3) domain(2) type(1) protocol(6)

Is there a way to hook functions that may not be called in the shared library, and not have the app seg fault?

Hook the entrypoint (first level) function

I've sucessfully used this library to replace func in the following shared library:

#include <stdio.h>

void func() {
  printf("func!\n");
}

void wrapfunc() {
  func();
}

with the following test.c:

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

#include "elf_hook.h"

#define LIBFUNC_PATH "./libfunc.so" //position dependent code

void wrapfunc();
void hook() {
  printf("hook!\n");
}

void set_hook(void * handle) {
  void *base = NULL;

  if (NULL == handle) {
    fprintf(stderr, "Failed to open \"%s\"! %s\n", LIBFUNC_PATH, dlerror()); exit(1);
  }
  if(get_module_base_address(LIBFUNC_PATH, handle, &base)) {
    fprintf(stderr, "Failed to get module base addresses\n"); exit(1);
  }
  void *orig = elf_hook(LIBFUNC_PATH, base, "func", hook);
  if (NULL == orig) {
    fprintf(stderr, "Redirection failed!\n"); exit(1);
  }
}

int main() {

  wrapfunc();

  void *handle = dlopen(LIBFUNC_PATH, RTLD_LAZY);
  set_hook(handle);

  wrapfunc();

  dlclose(handle);
  return 0;
}

through:

#!/usr/bin/env sh

set -e

cd $(dirname $0)

gcc -g3 -fPIC -shared -o libfunc.so libfunc.c
gcc -g3 -I../ELF-Hook -L${PWD} -o test test.c ../ELF-Hook/elf_hook.c -lfunc -ldl
LD_LIBRARY_PATH="$(pwd):$LD_LIBRARY_PATH" ./test

However, when I try to replace wrapfunc instead of func (i.e. elf_hook(LIBFUNC_PATH, base, "wrapfunc", hook)), I get a Redirection failed! error. Is this a supported use case?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.