GDB перерыв, когда программа открывает определенный файл - PullRequest
20 голосов
/ 03 мая 2011

История вопроса: при запуске программы под strace я замечаю, что / dev / urandom 'open' ed. Я хотел бы знать, откуда поступает этот вызов (он не является частью самой программы, он является частью системы).

Итак, используя gdb, я пытаюсь прервать (используя catch syscall open) выполнение программы при вызове open, чтобы я мог увидеть обратную трассировку. Проблема в том, что open вызывается много , как несколько сотен раз, поэтому я не могу сузить конкретный вызов, открывающий / dev / urandom. Как мне сузить конкретный звонок? Есть ли способ фильтрации по аргументам, и если да, то как мне сделать это для системного вызова?

Любой совет был бы полезен - может быть, я все об этом ошибаюсь.

Ответы [ 3 ]

14 голосов
/ 03 мая 2011

GDB является довольно мощным инструментом, но имеет некоторую кривую обучения.

По сути, вы хотите установить условную точку останова.

Сначала используйте флаг -i, чтобы связатьили objdump -d, чтобы найти адрес открытой функции, или, более реалистично, что-то в цепочке получения, например, в plt.

установить точку останова по этому адресу (если у вас есть символы отладки, вы можетевместо этого используйте их, пропуская *, но я предполагаю, что вы этого не сделаете - хотя вы вполне можете иметь их для библиотечных функций, если ничего больше.

break * 0x080482c8 

Далее вам нужно сделать его условным

(В идеале вы могли бы сравнить строковый аргумент с желаемой строкой. Я не получал, чтобы это сработало в течение первых нескольких минут попытки)

Будем надеяться, что мы можем предположить, что строка является константой где-то впрограмма или одна из библиотек, которые она загружает. Вы можете посмотреть в / proc / pid / maps, чтобы получить представление о том, что загружено и куда, а затем использовать grep, чтобы убедиться, что строка действительно находится в файле, objd.ump -s, чтобы найти его адрес, и gdb, чтобы убедиться, что вы действительно нашли его в памяти, комбинируя верхнюю часть адреса из карт с нижней частью из файла.(РЕДАКТИРОВАТЬ: вероятно, проще использовать ldd в исполняемом файле, чем искать в / proc / pid / maps)

Далее вам нужно будет кое-что узнать о abi платформы, над которой вы работаете, в частности, как аргументыпрошло.В последнее время я работал над arm, и это очень хорошо, так как первые несколько аргументов просто заносятся в регистры r0, r1, r2 ... и т. Д. X86 немного менее удобен - кажется, они идут в стек, т. Е. *($ esp + 4), * ($ esp + 8), * ($ esp + 12).

Итак, давайте предположим, что мы находимся на x86, и мы хотим проверить, что первый аргумент в esp + 4 равен адресу, который мы нашли для константы, которую мы пытаемся перехватить.Только esp + 4 - это указатель на указатель на символ.Поэтому нам нужно разыменовать его для сравнения.

cond 1 *(char **)($esp+4)==0x8048514

Затем вы можете набрать run и надеяться на лучшее

Если вы поймете состояние точки останова и оглянетесь вокругс информационными регистрами, и команда x для проверки памяти кажется правильной, тогда вы можете использовать команду return, чтобы выполнить резервное копирование стека вызовов, пока не найдете то, что узнаете.

5 голосов
/ 05 декабря 2016

Как сказал Андре Пуэль:

break open if strcmp($rdi,"/dev/urandom") == 0

Может сделать работу.

4 голосов
/ 30 мая 2014

(Адаптировано из редактирования вопроса)

После Ответ Криса , вот процесс, который в итоге дал мне то, что я искал:

(я пытаюсь выяснить, какие функции вызывают системный вызов open для "/ dev / urandom")

  1. использовать ldd в исполняемом файле для поиска загруженных библиотек
  2. grep через каждую библиотеку (команду оболочки), ищущую 'urandom'
  3. открыть файл библиотеки в шестнадцатеричном редакторе и найти адрес строки
  4. выяснить, как параметры передаются в системных вызовах (для открытия файлпервый параметр. на x86_64 он передается в rdi - ваш пробег может варьироваться
  5. , теперь мы можем установить условную точку останова: break open if $rdi == _addr_
  6. запустить программу и дождаться, пока разрыв достигнет
  7. run bt чтобы увидеть обратную трассировку

После всего этого я обнаружил, что g_random_int () и g_rand_new () из glib используют urandom. Gtk + и ORBit вызывали эти функции - если бы кто-нибудь быллюбопытно.

...