logo
PASOIB

6.2. Дизассемблирование программ с помощью интерактивного дизассемблера Ida Pro

Интерактивный дизассемблер IDA PRO, как и всякий дизассемблер предназначен для дизассемблирования кода программы в мнемонические инструкции на языке ассемблера. Рабочее окно IDA представлено на рис. 6.2.

Большим удобством Ida Pro является то, что он «сворачивает» стандартные библиотечные функции, что во многом упрощает навигацию по файлу, позволяя втиснуть больше информации в тесное пространство экрана. «Развернуть» функцию можно, подведя к ней курсор и нажав “+”, или для сворачивания “-”.

Кроме этого, IDA способна находить перекрестные ссылки, вызываемые из кода. На основе сигнатурного анализа, IDA умеет распознавать различные библиотечные операторы., например, “ostream::operator<<”.

Дизассемблер IDA изначально проектировался как интерактивная среда, предназначенная для совместной работы с человеком. Преимуществом интерактивных дизассемблеров является то, что дизассемблеры, пытающиеся выполнить весь процесс автоматически, легко сбить каким-либо хитрым приемом. Человека же сбить не так легко.

Рис. 6.2. Рабочий интерфейс дизассемблера Ida Pro

В IDA реализован удобный С-подобный внутренний язык написания скриптов, позволяющий реализовать многие полезные действия (например, осуществить дешифровку зашифрованного участка кода).

Ida Pro поддерживает инструкции для различного вида процессоров. Среди них – все версии процессоров INTEL, Motorola, Z80.

Пример использования дизассемблера IDA Pro приведен ниже.

Пусть у нас имеется следующий COM файл размером 292 байт. Код данного файла представлен на рис. 6.3.

Рис. 6.3. Код исследуемого файла

З агрузим данный файл в дизассемблер IDA, после чего получим следующую распечатку (рис 6.4).

В идим, что дизассемблирование произведено не совсем до конца. IDA дизассемблировала только первые две команды. Дело в том, что для того, чтобы правильно распознать остальную часть кода, потребовался бы нетривиальный интеллектуальный алгоритм. За неимением последнего, IDA прекратился процесс, ожидая дальнейших команд от пользователя. Многие дизассемблеры пытаются дизассемблировать дальше, и, как правило, неверно. Попытаемся указать для IDA, что делать дальше.

Если приглядеться к первым двум командам, то можно увидеть, что инструкция JMP в строке 103h вызывает переход по адресу 106h. Для того, чтобы объяснить это IDA, необходимо добавить новую перекрестную ссылку. Это можно сделать так.

В меню “View” выбрать пункт “Cross references” и нажать INSERT.

В

Рис. 6.4. Текст файла после первоначального дизассемблирования

поле “From” указать адрес, с которого происходит прыжок (в нашем случае seg000:0103).

В поле “To” указать адрес, куда происходит прыжок (в нашем случае seg000:0106).

Этого же самого эффекта можно добиться более быстрым путем – подвести указатель к адресу 106h и нажать клавишу “C”. Тем самым мы укажем, что с данного адреса идет участок кода. Однако недостаток этого варианта состоит в том, что непонятно, с какого места этот участок кода будет получать управление.

Комментарии в дизассемблированном коде имеют очень большое значение, особенно в больших проектах. Например, в нашем случае, в строке 103h можно поставить комментарий, говорящий о том, что при выполнении инструкции JMP SI, значение регистра SI=106h. Для осуществления этого, подведем курсор к строке 103h, нажмем клавишу “:” и введем текст комментария “SI=106h”.

С адреса 106h идет следующий участок кода.

loc_0_106:

mov si, 114h

Загрузка в si смещения 114h

lodsw

Загрузка в AX слова, на которое указывает регистр si

xchg ax,cx

Обмен значений регистров ax и cx

push si

Заносим si в стек

loc_0_10C:

xor byte ptr [si], 66h

Расшифровываем байт, находящийся по адресу, на который указывает si

inc si

Увеличиваем si на 1

loop loc_0_10C

Замыкаем цикл

jmp si

Переходим на адрес, находящийся в регистре si

Анализируя данный участок, видим, что данный участок осуществляет расшифровку некоторого фрагмента программы, находящегося с адреса 116h, при этом длина фрагмента хранится по адресу 114h и занимает 1 слово. Подведем курсор к адресу 114h и будем нажимать клавишу “D”, пока тип хранимых данных не изменится на «Слово» - «dw». Видим, что длина зашифрованного фрагмента равна 100h байт.

Если проанализировать команду jmp si, находящуюся по адресу 112h и выполняемую после расшифровки, то можно увидеть, что управление передается на команду, находящуюся за зашифрованным фрагментом. Адрес этой команды равен 116h+100h=216h.

Подведя курсор к адресу 216h и нажав клавишу “C”, мы получим следующий код, который выполняется после расшифровки.

call $+3;

Заносим в стек регистр IP

pop cx;

Извлекаем из стека регистр IP

pop si;

Извлекаем из стека начало расшифрованных данных

sub cx, si;

Вычисляем длину расшифрованного участка (+3 байта)

mov di, 100h;

push di;

Заносим в стек адрес 100h, на который будем передавать управление

repe movsb;

Переносим расшифрованный участок кода на адрес 100h

retn;

Передаем управление на адрес 100h

Общий смысл данной последовательности команд – перемещение расшифрованного фрагмента памяти по адресу 100h и передача на него управление.

Попытаемся узнать, что представляет собой зашифрованный участок кода. Для этого напишем скрипт на внутреннем языке IDA, который выполняет расшифровку.

Следует отметить, что для доступа к произвольной ячейке памяти в IDA необходимо знать сегмент, в котором она расположена, и ее смещение. Seg000 в действительности не нулевой сегмент, а символическое имя. Для того, чтобы узнать базовый адрес, соответствующий данному сегменту, необходимо воспользоваться меню View/Segments. Вызвав его, видим, что ему соответствует адрес 1000h (рис. 6.5).

Рис. 6.5. Просмотр базового адреса сегмента

Для написания скрипта, осуществляющего расшифровку программы, вызовем консоль Shift+F2. В нем вводим следующий текст (рис. 6.6).

auto a;

auto temp;

for (a=0x116;a<0x116+0x100;a++)

{

temp=Byte(MK_FP(0x1000,a));

temp=temp ^ 0x66h;

PatchByte(MK_FP(0x1000,a),temp);

}

Рис. 6.6. Ввод скрипта, осуществляющего расшифровку программы

После расшифровки, перейдем на адрес 122h, укажем на то, что с этого адреса начинается текстовая строка (клавиша “A”), после чего расшифрованный фрагмент примет следующий вид:

seg000:0116

mov ah,9;

seg000:0119

or al,1;

seg000:011B

int 21h;

Печать строки DOS

seg000:011D

xor ax,ax;

Обнуление регистра ax

seg000:011F

int 16h

Задержка вплоть до нажатия произвольного символа клавиатуры

seg000:0121

Retn

seg000:0122

db ‘Hello, IDA PRO! $’

Видим, что IDA PRO обладает многими полезными функциями, позволяющими значительно облегчить дизассемблирование программ. IDA PRO является очень мощным средством как для разработчиков ПО, так и для взломщиков.