Читайте также: |
|
Одним из способов изучения программного обеспечения в условиях отсутствия исходных текстов является дизассемблирование – процесс перевода двоичных команд процессора в удобочитаемые мнемоники этих команд.
Качественное дизассемблирование объемного программного продукта является достаточно трудной задачей, так как ассемблирование – перевод текста программы с языка программирования в машинные коды – однонаправленный процесс с потерями, и полное автоматическое восстановление исходного текста программы, как правило, невозможно.
Достаточно часто одна инструкция имеет несколько различных кодов операций. Например, инструкция ADD AX, 1 может быть ассемблирована в следующие коды микропроцессора x86:
05 01 00
83 C0 01
81 C3 01 00
Таким образом, при повторном ассемблировании восстановленного текста мы не можем гарантировано получить тот же самый код и полученная программа, скорее всего, откажется работать. Кроме того, любая попытка модификации дизассемблированного текста развалит программу окончательно. Дело в том, что ассемблер заменяет все метки на реальные смещения, т.е., иначе говоря, на константы. При внесении изменений в программу, необходимо скорректировать все ссылки на метки. Ассемблер это делает, руководствуясь директивой OFFSET. Но дизассемблер не может отличить смещения от обычных констант.
Например:
исходная программа | ассемблированный текст | дизассемблированный текст |
MOV BX, Label_1 JMP BX Label_1: | BB0001 FFE3 | MOV BX, 0100h JMP BX |
Дизассемблер неправильно восстановил исходный текст. Если после модификации программы Label_1 окажется по адресу, отличному от 100h, то переход произойдет на совершенно иной участок кода, может быть, даже в середину команды, что приведет к непредсказуемым результатам.
Следовательно, дизассемблер должен отследить, как используется те или иные константы, и при необходимости предварять их директивой OFFSET, что представляет собой серьезную проблему, для автоматических дизассемблеров.
По типу реализации интерфейса взаимодействия с пользователем, существующие дизассемблеры можно разделить на две группы – автономные и интерактивные.
Автономные дизассемблеры требуют от пользователя всех указаний до начала дизассемблирования и не позволяют вмешиваться непосредственно в сам процесс. Если же конечный результат окажется неудовлетворительным, пользователь либо вручную правит полученный листинг, либо указывает дизассемблеру на его ошибки и повторяет всю процедуру вновь и вновь, порой десятки раз. Такой способ общения человека с дизассемблером непроизводителен и неудобен, но его легче запрограммировать.
Интерактивные дизассемблеры обладают развитым пользовательским интерфейсом, благодаря которому приобретают значительную гибкость, позволяя человеку «вручную» управлять разбором программы, помогая автоматическому анализатору там, где ему самому не справиться – отличать адреса от констант, определять границы инструкций, области кода программы и данных и т.п.
Примером автономного дизассемблера является SOURCER, а интерактивного – IDA.
Интерактивный дизассемблер IDA Pro предназначен для дизассемблирования кода программы в мнемонические инструкции на языке ассемблера.
Дизассемблер IDA изначально проектировался как интерактивная среда, предназначенная для совместной работы с человеком. Преимуществом интерактивных дизассемблеров является то, что их трудно сбить каким-либо хитрым приемом, что возможно для дизассемблеров, работающих в автоматическом режиме.
IDA Pro поддерживает инструкции различных процессоров. Среди них все версии процессоров INTEL, Motorola, Z80 и многих других.
В IDA Pro возможно непосредственным образом в процессе интерактивного диалога указывать, является ли код программы, по заданному адресу, действительно кодом либо данными, т.к. точно это понять способен лишь человек.
Автономные дизассемблеры типа плохо справляются с анализом большого, порядка нескольких мегабайт, файла, а с шифрованным кодом не справляется вообще. Интерактивные дизассемблеры позволяют решить эту проблему. В IDA Pro реализован удобный C-подобный внутренний язык написания скриптов (IDC), позволяющий реализовать многие полезные действия (например, осуществлять дешифровку зашифрованного участка кода).
Для написания скриптов дешифровки, могут понадобиться, например, следующие команды.
PatchByte([Сегмент, Смещение], Значение); – заменить данные, находящиеся по адресу [Сегмент, Смещение] на Значение.
Byte([Сегмент, Смещение]) – получить значение по адресу [Сегмент, Смещение].
^ – обозначение функции XOR (побитовое сложение по модулю 2).
for(Начальное значение; Условие; Шаг) – цикл, изменяющий значение счетчика цикла от Начального значения на величину Шага до тех пор, пока выполняется Условие.
auto a – определение счетчика цикла с именем a.
Описание остальных команд IDC вы можете найти в файле-помощи IDA.
Дата добавления: 2015-07-08; просмотров: 488 | Нарушение авторских прав
<== предыдущая страница | | | следующая страница ==> |
Шифрование кода программы как универсальный метод противодействия отладке и дизассемблированию | | | Мы, Территоріальна Громада предлагаем расширить круг своих понятий и внести в его механизм построения реального, справедливого, прямого Народовластия, СамоДержавия. |