Tooprogram.ru

Компьютерный справочник
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Что такое дизассемблер

Введение в дизассемблирование

Базовые понятия дизассемблирования

Что такое дизассемблирование. Дизассемблирование – преобразование программы на машинном языке к ее ассемблерному представлению. Декомпиляция – получение кода языка высокого уровня из программы на машинном языке или ассемблере.

Декомпиляция – достаточно сложный процесс. Это обусловлено следующими причинами:

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

− Компиляция это операция типа множество-множество.Компиляция и декомпиляция могут быть выполнены множеством способов. Поэтому результат декомпиляции может значительно отличаться от исходного кода.

− Декомпиляторы в значительной степени зависимы от конкретного языка и библиотек. Обрабатывая исполняемый файл, созданный компилятором Delphi, декомпилятором, разработанным для C, можно получить фантастический результат.

− Необходимо точное дизассемблирование исполняемого файла. Любая ошибка или упущение на фазе дизассемблирования практически наверняка размножатся в результирующем коде.

Прогресс средств декомпиляции происходит медленно, но верно. Наиболее сложный на сегодняшний день декомпилятор IDA, будет рассмотрен ниже.

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

− анализ вредоносного программного обеспечения;

− анализ уязвимостей программного обеспечения с закрытым исходным кодом;

− анализ совместимости программного обеспечения с закрытым исходным кодом;

− отображение команд программы в процессе отладки.

Анализ вредоносного программного обеспечения. Разработчики вредоносного программного обеспечения вряд ли предоставят исходный код своего детища. А без доступа к исходному коду, будет довольно сложно определить поведение вредоносной программы. Существуют два основных метода исследования вредоносных программ — динамический и статический анализ. Динамический анализ заключается в исполнении программы в тщательно контролируемом окружении (песочнице) и записи каждого ее действия. Статический анализ основан на разборе исходного кода, который, в случае вредоносной программы, в основном состоит из дизассемблированных листингов.

Анализ уязвимостей. Для простоты, можно разделить процесс аудита безопасности на три стадии: поиск уязвимостей, анализ уязвимостей, и разработка эксплойта. Одни и те же шаги предпринимаются вне зависимости от того, имеется ли у вас исходный код; однако, уровень трудоемкости резко возрастает, когда в вашем распоряжении есть лишь исполняемый файл. Первый шаг — исследование потенциально уязвимых условий в программе. Это зачастую достигается использованием динамических техник, таких как фаззинг, однако также может быть реализовано (обычно со значительно большими усилиями) посредством статического анализа. Как только проблема обнаружена, требуется определить, является ли она уязвимостью и если да, то при каких условиях.

Листинг дизассемблирования помогает понять, каким образом компилятор расположил переменные в памяти. Например, может быть полезно узнать, что объявленный программистом 70-байтный массив символов при распределении памяти компилятором был округлен в сторону 80 байт. Листинги дизассемблирования также предоставляют единственный способ понять, объявлены ли переменные глобально или внутри функций. Понимание реального расположения переменных в памяти жизненно важно при разработке эксплойтов.

Анализ совместимости. Когда программы доступны только в виде исполняемых файлов, сторонним разработчикам крайне сложно обеспечить совместимость с ними своих программ, а также расширить их функциональность. Например, если производитель не предоставил драйвер для аппаратного устройства, то реверс инжиниринг – практически единственное средство для разработки альтернативных драйверов.

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

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

Как дизассемблировать. Типичные задачи, с которыми сталкивается дизассемблер: взять 100 КБ из исходного файла, отделить код от данных, преобразовать код к языку ассемблера, и главное ничего не потерять. В этот список можно добавить дополнительные пожелания, например, определение границ функций, распознавание таблиц переходов, выделение локальных переменных. Это значительно усложнит его работу. Качество результирующих листингов дизассемблирования определяется свойствами алгоритмов, а также уместностью их применения в конкретной ситуации.

Базовый алгоритм дизассемблирования

Шаг 1. Первым шагом в процессе дизассемблирования является идентификация кодового сегмента. Так как команды обычно смешаны с данными, то дизассемблеру необходимо их разграничить.

Читать еще:  Команда sub ассемблер

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

Шаг 3. Как только команда была обнаружена и декодирована, ее ассемблерный эквивалент может быть добавлен к результирующему листингу. После этого необходимо выбрать одну из разновидностей синтаксиса языка ассемблера.

Шаг 4. Далее необходимо перейти к следующей команде и повторить предыдущие шаги до тех пор, пока каждая команда файла не будет дизассемблирована.

Алгоритм линейной развертки

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

Главное преимущество алгоритма линейной развертки состоит в полном покрытии кодового сегмента. Одним из основных недостатков является невозможность распознать данные, если они совмещены с кодом. Это очевидно из листинга, демонстрирующего результат дизассемблирования функции при помощи данного алгоритма. Эта функция содержит конструкцию switсh. Компилятор принял решение реализовать switch как таблицу переходов. Более того, компилятор предпочел разместить таблицу переходов внутри самой функции. Конструкция jump по адресу 401250 ссылается на таблицу адресов начиная с 410257. К сожалению, дизассемблер рассматривает ее как набор команд и неверно генерирует соответствующее представление на языке ассемблера.

40123f: 55 pushebp

401240: 8bec movebp,esp

401242: 33 c0 xor eax,eax

401244: 8b 55 08 mov edx,DWORD PTR [ebp+8]

401247: 83 fa 0c cmp edx,0xc

40124a: 0f 87 90 00 00 00 ja 0x4012e0

401250: ff 24 95 57 12 40 00 jmp DWORD PTR [edx*4+0x401257]

401257: e0 12 loopne 0x40126b

401259: 40 inc eax

40125a: 00 8b 12 40 00 90 add BYTE PTR [ebx-0x6fffbfee],cl

401260: 12 40 00 adc al,BYTE PTR [eax]

401263: 95 xchg ebp,eax

401264: 12 40 00 adc al,BYTE PTR [eax]

401267: 9a 12 40 00 a2 12 40 call 0x4012:0xa2004012

40126e: 00 aa 12 40 00 b2 add BYTE PTR [edx-0x4dffbfee],ch

401274: 12 40 00 adc al,BYTE PTR [eax]

401277: ba 12 40 00 c2 mov edx,0xc2004012

40127c: 12 40 00 adc al,BYTE PTR [eax]

40127f: ca 12 40 lret 0x4012

401282: 00 d2 add dl,dl

401284: 12 40 00 adc al,BYTE PTR [eax]

401287: da 12 ficom DWORD PTR [edx]

401289: 40 inc eax

40128a: 00 8b 45 0c eb 50 add BYTE PTR [ebx+0x50eb0c45],cl

401290: 8b 45 10 mov eax,DWORD PTR [ebp+16]

401293: eb 4b jmp 0x4012e0

Алгоритм рекурсивного спуска

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

Команды, не влияющие на счетчик команд. После выполнения такой команды управление переходит непосредственно к следующей команде. Примерами такой команды может послужить арифметические, такие как add; Для подобных команд процесс дизассемблирования такой же как и при линейной развертке.

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

Команды безусловного перехода. Безусловные переходы приводят к нарушению последовательного порядка исполнения команд. Команда, получающая управление после выполнения безусловного перехода, может располагаться от него на значительном расстоянии. Кроме того, как видно из приведенного выше листинга, команды, следующие непосредственно за командой безусловного перехода не исполняются вообще. Таким образом, необходимость в их дизассемблировании отпадает.

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

Читать еще:  Структуры в си примеры

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

Алгоритм рекурсивного спуска может оказаться неэффективным в случае, если при возвращении из вызываемой функции поведение программы отклоняется от ожидаемого. Например, в коде функции может преднамеренно модифицироваться адрес возврата.

Команды возврата. В некоторых случаях, алгоритм рекурсивного спуска терпит неудачу. Команда возврата из функции (например, ret x86) не предоставляет информации о том, какая команда будет выполнена далее. Если бы программа была на самом деле запущена, управление было бы передано по адресу, расположенному на вершине стека. У дизассемблера нет возможности доступа к стеку. Вместо этого дизассемблирование внезапно останавливается. В этом случае алгоритм рекурсивного спуска обращается к списку отложенных адресов, и процесс дизассемблирования возобновляется. Этот рекурсивный процесс отражает смысл названия алгоритма.

Алгоритм рекурсивного спуска превосходно разделяет код и данные. Главным же недостатком такого подхода является неспособность распознавать ветви, образуемые таким командами как jump и call, использующими для адресации таблицы поиска. Несмотря на это, в сочетании с эвристиками для распознавания указателей на код, алгоритм рекурсивного спуска способен обеспечить хорошее покрытие кода в сочетании с прекрасным разделением кода и данных.

Дата добавления: 2018-06-27 ; просмотров: 2121 ;

Дизассемблер

главная программы pe explorer обзорный тур

Простота, ясность и удобство навигации

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

Мы попытались достичь уровня IDA Pro, при этом не требуя от пользователя специфических знаний и умений, поскольку большинство стадий процесса дизассемблирования в PE Explorer автоматизированы. Во многих случаях использование IDA Pro для быстрого анализа кода файла напоминает стрельбу из очень тяжёлой и дорогой пушки по очень маленьким воробьям. Мы же сделали просто хороший дизассемблер по очень доступной цене. И если ваша повседневная работа включает реверсинг и исследование уязвимостей программного кода, восстановление исходных кодов и поиск параметров, тестирование или изучение поведения неизвестных файлов, PE Explorer сэкономит вам немало часов и во многом упростит вашу работу.

Использование дизассемблера PE Explorer предполагает последующее редактирование полученного листинга вручную. Однако, чтобы избавить пользователя от значительного количества рутинной работы и уменьшить объём ручной правки, дизассемблер использует очень гибкий и интелектуальный алгоритм дизассемблирования, способный реконструировать ассемблерный код изучаемого исполняемого файла с высокой степенью достоверности.

Я очень впечатлён возможностями, появившимися в последней версии PE Explorer — и особенно дизассемблером.

Одной из причин, по которой я купил PE Explorer, был дизассемблер. Отличная вещь.

После сравнения PE Explorer с другими продуктами я полагаю, что выбрал самое лучшее предложение на рынке за свои деньги — вместо того, чтобы платить $400 за />

Отзывы пользователей

Основная проблема дизассемблирования заключается в правильности интерпретации изучаемых данных. Отделить код от данных — задача невероятно сложная, особенно когда код включает в себя специальные меры противодействия для затруднения дизассемблирования. Специально для таких случаев мы разработали особую модель алгоритма, позволяющую снизить ошибки определения типа данных.

Несмотря на то, что эта модель увеличивает время дизассемблирования, её результатом является значительное уменьшение ошибок, связанных с неверной интерпретацией кода/данных, и существеное сокращение времени, затрачиваемого на ручную корректировку полученного результата.

Процесс дизассемблирования

Дизассемблер запускается в своём отдельном окне, и вы можете переключаться из окна дизассемблера в основное окно PE Explorer. Дизассемблер поддерживает основные наборы инструкций Intel x86 и расширения MMX, 3D Now!, SSE, SSE2 и SSE3. В начале процесса окно Options предлагает выбрать следующие опции:

Нажатие кнопки Start Now запускает процесс, кнопка Start Later откладывает запуск.

Verify Offsets — При включении этой опции дизассемблер особо тщательно проверяет, является ли анализируемое значение смещением.

Reverse Offset Checking Order — По умолчанию, дизассемблер рассматривает необработанные данные как код, и только потом как смещения к данным. При включении этой опции дизассемблер будет рассматривать необработанные данные как данные.

В большинстве случаев включение этой опции либо ничего не изменит, либо сделает качество листинга хуже. Однако, в некоторых случаях (например, с программами, написанными на Visual Basic) изменение порядка определения смещений может дать лучший результат. Автоматизировать применение этой опции затруднительно, поэтому рекомендуется использовать эту опцию только в ситуациях, когда настройки по умолчанию приводят к неудовлетворительным результатам.

Find ANSI and Unicode Strings — При включении этой опции дизассемблер автоматически обнаруживает текстовые ANSI и Unicode строки длиннее 3-х символов. В отдельных случаях, если результаты анализа позволяют однозначно интерпретировать данные как строку, эта длина может быть и менее 3-х символов.

Find Alignment — Поскольку доступ к выравненным данным происходит быстрее, многие компиляторы выравнивают код, добавляя лишние команды, не влияющие не ход выполнения программы, такие как nop, mov eax,eax и т.п.
При включении этой опции дизассемблер интерпретирует подобный код/данные как выравнивание.

Forcible Find Offsets — При включении этой опции дизассемблер автоматически обнаруживает смещения к данным в коде, который остался нераспознанным после первого прохода по файлу.
Используйте эту опцию с осторожностью, так как правильно определить, являются ли найденные данные смещением или фрагментами кода/данных, довольно сложно. Не рекомендуется использовать эту опцию без особых причин.

Analyze Uprocessed Data — Во время дизассемблирования отдельные фрагменты кода по причине отсутствия явных на них ссылок могут оказаться нераспознанными. При включении данной опции дизассемблер проводит дополнительный анализ таких блоков и пытается определить, являются ли эти фрагменты кодом или данными. Включение этой опции улучшает качество листинга.

Окно Processing Info отображает информацию о ходе процесса дизассемблирования:

По окончании процесса в главном окне дизассемблера появляется дизассемблерный листинг исходного кода изучаемого файла. Этот листинг можно редактировать в окне или сохранить на диск для дальнейшей работы.

Нахождение всех текстовых строк внутри EXE файла

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

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

Нахождение VCL объектов и методов Delphi

Дизассемблер отображает список всех найденных VCL объектов и методов в отдельных закладках VCL Objects и VCL Methods:

Известные ограничения

Важно понимать, что PE Explorer не декомпилирует код. Он дизассемблирует код, т.е. преобразует машинный код в ассемблерный код. При этом он не генерирует код на С или С++ из полученного листинга. Сама по себе эта задача невероятной сложности, так еще при этом часто в исполняемом файле либо нет никаких упоминаний о том, какой язык программирования был использован для создания программы, либо оригинальный язык был совсем не С++.

Дизассемблирование файлов размером более 1 Мб может занять несколько минут. Во многом скрость зависит от возможностей вашего компьютера. В общем случае, для каждого байта дизассемблируемого файла требуется 40 байт памяти. Т.е. для файла размером в 1 Мб требуется 40 Мб памяти, для 2 Мб — 40 Мб памяти, и так далее.

Полученный дизассемблерный листинг не может быть заново скомпилирован «как есть». Мы не ставили перед собой задачи формировать листинг, который мог бы быть рекомпилирован. Это не имеет большого смысла для сколь-либо значимого размера входного файла. Нашей целью было получить продукт, способный БЫСТРО и достаточно качественно дать представление о содержимом исполняемого файла, обнаружить в нём интересующие исследователя места и проанализировать их. Получение же листинга, способного быть откомпилированным, представляется нам задачей мало применимой в реальной жизни в силу внушительных размеров современных исполняемых файлов и, как следствие, КРАЙНЕ ВЫСОКОЙ СЛОЖНОСТИ качественного анализа ВСЕХ данных, содержащихся в программе. Нам кажется, что имеет смысл вести разговор только о возможности извлечь какую-либо процедуру из листинга для использования ее в своих целях (естественно, в рамках действующего законодательства).

Скриншоты программы

Скачать 30-дневную пробную версию PE Explorer Купить лицензию

Ссылка на основную публикацию
Adblock
detector