Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #95, НОЯБРЬ 2006 г.

Покорение вершин отладки

Крис Касперски

Хакер, номер #095, стр. 095-118-1

Трассировка во тьме с завязанными глазами

В этой статье мы продолжим наше погружение в gdb, исследуя его возможности с точки зрения хакера, отлаживающего двоичные файлы без исходных текстов. Мы рассмотрим технику изменения потока выполнения программы, точки останова и наблюдения, механизмы трассировки и средства работы с памятью. В общем, все то, что делает взломщиков счастливыми людьми.

Изменение потока выполнения

Программа, загруженная командой file (или указанная в командной строке), находится в бесформенном состоянии, представляющем собой всего лишь совокупность байт, записанных в выделенном регионе адресного пространства. Новый процесс для нее еще не создан, и трассировать ее невозможно. Во всяком случае, пока мы не дадим команду run или r, которой обычно предшествует установка точки останова на функцию main или start. Будучи запущенной, программа будет работать до тех пор, пока не встретит точку останова или не получит stop-сигнал (см. раздел «Обработка сигналов»). Применение команды run к уже запущенной программе приведет к ее перезапуску (в конфигурации по умолчанию отладчик запрашивает подтверждение).

Продолжить работу программы, остановленной по точке останова или по сигналу, можно командой continue (c), действующей так же, как и run, то есть работающей до сигнала/точки останова.

Чтобы передать управление по произвольному адресу, необходимо сделать jump (j), за которым следует адрес, имя функции или регистр. В частности, j *$pc по своему действию аналогична команде continue, j foo передает управление на метку/функцию foo (если только она присутствует в таблице символов), а j *0x80484AA прыгает на адрес 80484AAh. Если одни и те же адреса используются многократно, их можно загнать в пользовательскую переменную командой set $my_foo=0x80484AA, а затем использовать ее в качестве параметра команды jump – j *$my_foo. Кстати, отладчик soft-ice ничего подобного делать не умеет!

Команда until (u) продолжает выполнение программы вплоть до указанного адреса (например, u *0x080484ED), при достижении которого останавливается и передает управление отладчику. Как и jump, команда until поддерживает работу не только с метками и адресами, но и с переменными, значительно упрощая взлом. Без аргументов until аналогична команде nexti (см. раздел «Трассировка») — она переходит на следующую машинную команду, пропуская функции и циклы.

Рассмотрим фрагмент цикла, демонстрирующего сущность команды until

.text:080484EB jb short loc_80484EF ; на выход из цикла

.text:080484ED jmp short loc_8048532 ; к началу тела цикла

.text:080484EF lea eax, [ebp + var_28] ; первая команда за концом цикла

Команда until, отданная на строке 80484EBh, равносильна u *0x80484EF — она выполняет цикл и передает управление отладчику только по выходу из него. Очень удобно!

Если нам необходимо дождаться выхода из функции, автоматически остановившись при встрече c RET, то на этот случай предусмотрена команда finish, аналогичная команде P RET отладчика soft-ice. Вместо пошаговой трассировки программы, gdb просматривает фрейм предыдущей функции (это можно сделать командой backtrace или bt) и устанавливает точку останова на адрес возврата, что обеспечивает максимальную эффективность выполнения. Но если отладчику не удастся раскрутить стек и восстановить цепочку фреймов, тогда команда finish не сможет работать.

Содержание  Вперед на стр. 095-118-2
ttfb: 2.979040145874 ms