Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing symbols without LD_PRELOAD

Tags:

c

linux

Is it possible to set hooks on system calls in runtime? In portable way, without asm, maybe some dynamic linker functions? I want to intercept system calls of 3rd party libraries. Don't want to use LD_PRELOAD, it needs external wrapper-launcher script setting env var

like image 659
user1940679 Avatar asked Oct 13 '25 11:10

user1940679


1 Answers

You can override a library call by redefining the function:

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

void abort(void)
{
  // If necessary, get a instance to the "real" function:
  void (*real_abort)(void) = dlsym(RTLD_NEXT, "abort");
  if (!real_abort) {
    fprintf(stderr, "Could not find real abort\n");
    exit(1);
  }
  fprintf(stderr, "Calling abort\n");
  real_abort();
}

with main

#include <stdlib.h>

int main(int argc, char** argv) {
  abort();
}

Resulting in:

$ ./a.out 
Calling abort
Aborted

If you want to do this in runtime for an arbitrary function (without compiling your own version of the function), you might try to use the relocation information of your ELF objects (executable and shared objects) and update the relocations at runtime.

Let's compile a simple hell world and look at its relocations:

$ LANG=C readelf -r ./a.out 

Relocation section '.rela.dyn' at offset 0x348 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000006008d8  000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

Relocation section '.rela.plt' at offset 0x360 contains 3 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000006008f8  000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
000000600900  000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main + 0
000000600908  000300000007 R_X86_64_JUMP_SLO 0000000000000000 __gmon_start__ + 0

Those are the relocations done by the dynamic linker: the first line of the .rela.plt tells the dynamic linker it needs to setup a PLT entry at 0x0000006008f8 for the puts symbol. In order to override the put function, we might find all occurrences of the puts symbols in all shared objects and relocate them to the suitable function.

like image 164
ysdx Avatar answered Oct 15 '25 02:10

ysdx