LINUX.ORG.RU

Подмена символов из libc


0

0

Возникла проблема: в целях отладки мне нужно подменить некоторые
символы в Libc таким образом, чтобы вместо оригинальной функции
вызвалась моя, что-то напечатала, а затем вызывала "настоящую"
функцию. Я делаю это посредством LD_PRELOAD.

Но это получается, если только у символа есть синоним. Вопрос такой:
как подменить символы, у которых нет синонимов? Ну например, я пишу
маленькую библиотеку mysocks.so:

#include <stdio.h>
int accept (int __fd, void *__addr, int *__addr_len) {
  printf("mysocks::accept(fd=%d, addr=%X, addr_len=%X, *addr_len=%X)\n", __fd, __addr, __addr_len, *__addr_len);
  int r = __libc_accept(__fd, __addr, __addr_len);
  printf("mysocks::accept(fd=%d, addr=%X, addr_len=%X) returned %d\n", __fd, __addr, __addr_len, r);
  return r;
}
int bind (int __fd, void *__addr, int __len) {
  printf("mysocks::bind(__fd=%d, __addr=%X, __len=%X)\n", __fd, __addr, __len);
  int r = __libc_bind(__fd, __addr, __len);
  printf("mysocks::bind(__fd=%d, __addr=%X, __len=%X)=%d\n", __fd, __addr, __len, r);
  return r;
}

У accept() есть синоним __libc_accept(), а у bind() - нет! Так что
загрузка этой библиотеки с LD_PRELOADК не работает.

Как же мне поступить с bind()?

anonymous

Да, у меня тоже есть такая проблема -- как вызвать оригинал перехваченного вызова.

Я для себя ее решал "в лоб" -- подсовывал свою libc (тогда и LD_PRELOAD не нужна). Наверняка имеется более простой способ, но я его придумать не смог (времени не было :))

Die-Hard ★★★★★
()
Ответ на: комментарий от anonymous

anonymous (*) (22.06.2004 12:28:32):

> dlopen()/dlsym() спасли меня :)

То есть подгрузить оригинальную libc с помощью dlopen() и вытащить оригинальный адрес через dlsym()?

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

Можно посмотреть пример в пакете checkinstall. Оно точно работает. AFAIR там даже без dlopen-а обходилось как-то.

DonkeyHot ★★★★★
()
Ответ на: комментарий от Die-Hard

2Die-Hard: 

> То есть подгрузить оригинальную libc с помощью dlopen() и вытащить
> оригинальный адрес через dlsym()?

Да :)

Вот кусочек моего кода:

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

int inited=0;

void *libc = NULL;

int (*libc_bind)(int __fd, void *__addr, int __len) = NULL;
int (*libc_listen) (int __fd, int __n) = NULL;
.............................

static void init() {
  if(inited)
    return;

  libc = dlopen("libc.so.6", RTLD_LAZY);
  assert(libc);

  libc_bind = dlsym(libc, "bind");
  assert(libc_bind);
  ......................................


int bind (int __fd, void *__addr, int __len) {
  init();

  printf("mysocks::bind(__fd=%d, __addr=%X, __len=%X)\n", __fd, __addr, __len);
  int r = (*libc_bind)(__fd, __addr, __len);
  printf("mysocks::bind(__fd=%d, __addr=%X, __len=%X)=%d\n", __fd, __addr, __len, r);
  return r;
}

.................................

Работает прекрасно! :)

anonymous
()
Ответ на: комментарий от Die-Hard

можно без dlopen(). RTLD_NEXT. пример, перехват puts():

#include <dlfcn.h>

int puts(const char        int (*libc_puts)(const char *);

        printf("HOOKED!!!\n");

        libc_puts = dlsym(RTLD_NEXT, "puts");

        return libc_puts(s);
}

таким образом нам даже не надо знать, в какой библиотеке
перехватываемая функция.

idle ★★★★★
()
Ответ на: комментарий от idle

что-то с форматированием. попробую повторить.

int puts(const char *s)
{
        int (*libc_puts)(const char *);

        printf("HOOKED!!!\n");

        libc_puts = dlsym(RTLD_NEXT, "puts");

        return libc_puts(s);
}

idle ★★★★★
()
Ответ на: комментарий от idle

idle (*) (22.06.2004 13:53:38):

Many thanks!

Вот оно, правильное решение! И, главное, даже для дураков разжеваное:

Из man dlsym:

There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT. The former will find the first occurrence of the desired symbol using the default library search order. The latter, which is usable only from within a dynamic library, will find the next occurrence of a function in the search order after the current library. This allows one to provide a wrapper around a function in another shared library.

Век живи, век учись... :(

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.