LINUX.ORG.RU

Подмена системных вызовов


0

1

Есть закрытый код. Пытаюсь сделать так, чтобы сокет читал из файла, а не из сети. Т.е. подменяю системные вызовы socket(), recv() etc.

Написал тестовую прогу. Сделал LD_PRELOAD=./mylib.so ./test Моя прога работает на ура. Но когда подсовываю свою либу закрытой проге, то она делает вызовы recv() и данные там точно правильные, но такое впечатление, что она их считает некошерными.

Что вообще может «мешать» воспринимать проге данные, как правильные?

★★

Исходник не дашь? Я как раз похожое пытаюсь писать, только не с сокетами, а с execve. Только оно не хочет работать. У меня сервер на питоне отправляет 'ok', а клиент на си принимает, но при сравнении с «ok» говорит, что строки разные. И говорит, что получил строку длиной 4 символа.

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

>И говорит, что получил строку длиной 4 символа

Из которых, небось, первые два ok, а вторые cr+lf.

Или там unicode -> ascii.

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

Питон по-идее отправляет в юникоде. В каком виде си читают символы - хз. Но когда я пытался выводить принятое, выводит «ok».

vurdalak ★★★★★
()

Что вообще может «мешать» воспринимать проге данные, как правильные?

Посмотри strace, точно ты те _библиотечные_ вызовы подменяешь? Я вот как-то подменал open а оказалось надо open64. Возможно так же что та прога делает dlopen('libc.so.6') и берёт символы напрямую оттуда :).

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

Питон по-идее отправляет в юникоде.

Ты путаешь типы str и unicode. Из сети должен прилетать str. Ну и символ перевода строки учитывай. Сделай data.strip()

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

congestion_control> Ты посимвольно (коды симолов) выведи то, что тебе передали.

Ок. Приду домой, попробую.

vurdalak ★★★★★
()

Системные вызовы можно подменить только из ядра. Вы подменяете вызовы libc. Если программа собрана статически или делает int $0x80, то ваши подмены ей абсолютно до лампочки.

bvvv
()
Ответ на: комментарий от vurdalak

Да там ничего особенного ) Вот как-то так я подменяю recvfrom, например:

ssize_t recvfrom_orig(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
{
  unsigned long args[6];

  args[0] = sockfd;
  args[1] = (unsigned long) buf;
  args[2] = len;
  args[3] = (unsigned long) flags;
  args[4] = (unsigned long) src_addr;
  args[5] = (unsigned long) addrlen;
  return (__socketcall(SYS_RECVFROM, args));
}
....

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)
{
  //прочитать из файла в buf len символов
  return len;
}

kulti ★★
() автор топика

Как оказалось, в моем случае, у проги какая-то завязка на EAGAIN, т.е. должна вернуться ошибка, чтобы прога работала)) Буду копать дальше.

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

> должна вернуться ошибка, чтобы прога работала

Ужас-то какой - должна вернуться ошибка.

Там, значит, используется неблокирующий i/o (это я к тому, о чем читать / куда копать).

))


Лиспер?

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

спасибо, это я понимаю. просто сообщил, чтоб народ не думал зря

> ))

Лиспер?

нет, в джаббере от жены заразился

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

Откуда он в строке

ты же код не показываешь, я думал там сервер такое генерит(не угадал). Потом обычно в текстовых протоколах вставляют перевод строки чтобы можно было телнетом дебажать.

true_admin ★★★★★
()

я в далекие времена, еще в пору начала ветки ядра версии 2.4, пользовался исключительно подменой системного вызова на уровне ядра. работает железно. хоть статичская линковка, хоть инт 80... мимо моей функции не проходило :). на самом деле не так сложно написать ядерный модуль. по крайней мере так было 10 лет назад :).

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

Ну, раз это так просто, то киньте работающим примером с подсовыванием одних данных в сокет вместо других? Я помню, когда-то пытался такое делать, но там проблемы с kernel/user-space начались. Так у меня ничего и не вышло...

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

Предлагаю не подменять весь набор функций для работы с сетью. Лучше сделать по-другому: при создании соединения подменить адрес подключения на localhost:port, где повесить простой сервер, отдающий содержимое файла. Так оно будет надежнее.

ccoder
()
Ответ на: комментарий от kulti

>еще в пору начала ветки ядра версии 2.4

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

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

на протяжении 2.6 были существенные изменения

Были, мне, чтобы установить модуль ПЗС-камеры пришлось несколько дней поковыряться в интернете, чтобы исправить исходники (благо, основной функционал лежит в userspace и модуль был небольшой).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от kulti

Через loopback-интерфейс будет быстро. Я не знаю специфики, может и правда будет недостаточно, но в общем-то реализация очень простая и попробовать можно быстро. Возможно ничего и не надо писать, а завернуть исходящее соединение на локалхост средствами iptables, а в качестве сервера повесить nc (netcat). Может даже заработает.

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

с 2.6.2x подменить системные вызовы несколько проблемно - страницы памяти с syscall_table стоят с флажком ro, хотя был где-то код как его из ядра поменять на rw, дальше хук вешается как обычно. чтоб не гадать с символами «ok» - запущаешь сниффер и смотришь в байтовом представлении как идёт твоё «ok», там всё прояснится, то ли отправляется (ascii/utf).

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