Подтвердить что ты не робот

Gdb break, когда программа открывает конкретный файл

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

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

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

4b9b3361

Ответ 1

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

В принципе, вы хотите установить условную точку останова.

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

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

break * 0x080482c8 

Затем вам нужно сделать это условным

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

Можно надеяться, что строка является константой где-то в программе или одной из библиотек, которые она загружает. Вы можете посмотреть в /proc/pid/maps, чтобы получить представление о том, что загружено и где, затем используйте grep, чтобы проверить, что строка действительно находится в файле, objdump -s, чтобы найти его адрес, и gdb, чтобы убедиться, что вы фактически нашел его в памяти, объединив большую часть адреса с картами с низкой частью из файла. (EDIT: возможно, проще использовать ldd для исполняемого файла, чем смотреть в /proc/pid/maps )

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

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

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

Затем вы можете ввести запустить и надеяться на лучший

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

Ответ 2

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

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

(Я пытаюсь найти, какие функции вызывают syscall open на "/dev/urandom" )

  • использовать ldd для исполняемого файла для поиска загруженных библиотек
  • grep через каждую команду lib (shell), которая ищет "urandom"
  • открыть файл библиотеки в шестнадцатеричном редакторе и найти адрес строки
  • узнать, как параметры передаются в syscalls (для open, файл является первым параметром. на x86_64 он передается в rdi - ваш пробег может меняться
  • теперь мы можем установить условную точку останова: break open if $rdi == _addr_
  • запустить программу и дождаться перерыва, чтобы нажать
  • запустите bt, чтобы увидеть обратную трассировку

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

Ответ 3

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

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

Возможно выполнение задания.