Что такое дизассемблер - IT Справочник
Llscompany.ru

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

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

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


Дизассемблеры и декомпиляторы исполняемых файлов

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


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

Начнем с популярного нынче дотнета. Не будет преувеличением сказать, что самый мощный на сегодняшний день инструмент для потрошения приложений на .NET — это бесплатный проект dnSpy. Он включает в себя декомпилятор C# и Visual Basic .NET, отладчик, редактор сборки с подсветкой синтаксиса, HEX-редактор и еще множество инструментов. Русский язык в наличии. Самую свежую версию можно всегда скачать с офсайта.


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

IDA Pro (сокращение от Interactive DisAssembler) — один из моих основных инструментов для реверс-инжиниринга и разбора файлов. Это интерактивный дизассемблер и отладчик с поддержкой множества форматов исполняемых файлов для большого числа процессоров и операционных систем. Чтобы перечислить все его возможности потребуется целая книга. Но даже тут возможности IDA не заканчиваются. Плагин Hex-Rays для IDA Pro позволяет декомплировать ассемблерный листинг в более-менее человекопонятный псевдокод, по синтаксису похожий на C. В некоторых случаях это значительно облегчает работу. Просто так приобрести IDA Pro частным лицам практически невозможно, и дело не только в непомерной цене, а в том, что автор придерживается абсолютно неадекватной политики в плане продаж. К счастью, несколько последних версий этого замечательного дизассемблера, несмотря на все трудности, были успешно слиты в свободный доступ. Это IDA Pro Advanced 6.8, последняя доступная версия, которая работает с 32-битными системами, а также IDA Pro Advanced 7.0 и IDA Pro Advanced 7.2 для 64-битных систем. Если по каким-то причинам вы не можете использовать варез, то на офсайте есть бесплатные демо-версии с урезанным функционалом.


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

IDR (Interactive Delphi Reconstructor) — бесплатный декомпилятор исполняемых файлов и динамических библиотек. В отличие от IDA Pro, этот декомпилятор создан специально для разбора файлов, написанных на языке Delphi. Сейчас проект прекратил развитие, если какие изменения и вносятся, то исключительно косметические. Исходники для доработки открыты. Лично я пользуюсь стабильным комплектом Interactive Delphi Reconstructor 2.6.0.1.


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

Еще один специализированный декомпилятор — VB Decompiler Pro. Он работает с программами (EXE, DLL, OCX), написанными на Visual Basic. В случае, если приложение собрано в p-code, декомпилятор может разобрать его практически до исходного кода. Но даже если приложение скомпилировано в native code, в этом случае VB Decompiler анализирует и восстанавливает довольно много инструкций, чтобы насколько это возможно приблизить ассемблерный код к исходному. Это сильно упростит задачу анализа алгоритмов исследуемой программы. Честные граждане могут воспользоваться бесплатной Lite-версией с офсайта, для любителей полных версий софта есть релиз VB Decompiler Pro 10.0. Антивирусы могут ругаться на активатор, но тут вы уже сами решайте что делать.

Конечно, это далеко не полный список инструментов для дизассемблирования и декомпиляции, который есть в свободном доступе. Например, та же набирающая популярность Ghidra от АНБ может составить конкуренцию IDA Pro с Hex-Rays. Но я в этой статье перечислил лишь те программы, которыми пользуюсь сам и которые упоминаются в статьях на этом сайте.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Читать еще:  Css focus within

Шаг 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 ; просмотров: 2129 ;

Что значит дизассемблировать? Только объясните понятно.

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

вот этот перевод и есть дизассемблирование.

По режиму работы с пользователем делятся на

Автоматические
Интерактивные
Примером автоматических дизассемблеров может служить Sourcer. Такие дизассемблеры генерируют готовый листинг, который можно затем править в текстовом редакторе. Пример интерактивного — IDA. Он позволяет изменять правила дизассемблирования и является весьма удобным инструментом для исследования программ.

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

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

По режиму работы с пользователем делятся на

Примером автоматических дизассемблеров может служить Sourcer[1]. Такие дизассемблеры генерируют готовый листинг, который можно затем править в текстовом редакторе. Пример интерактивного — IDA. Он позволяет изменять правила дизассемблирования и является весьма удобным инструментом для исследования программ.

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

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

Читать еще:  Shellexecute delphi примеры

Обычно однопроходный дизассемблер (как и построчный ассемблер) является составной частью отладчика.

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

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

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

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

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

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

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

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

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

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

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

Дизассемблер запускается в своём отдельном окне, и вы можете переключаться из окна дизассемблера в основное окно 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 Купить лицензию

Русский дизассемблер

Дизассемблирование — неотъемлемая часть мира программирования, как археология, история в мире человеческом. И если второе прошло уже несколько этапов развития — от машинного кодирования до блочно- модульного в языках высокого уровня, а теперь перешло и на уровень системного программирования в визуал-языках, то первое до сих пор топчется на первом этапе. Ведь до сих пор вспоминают SOURSER. И в той же IDA PRO, которая считается лучшей, человеку до сих пор приходится решать элементарные задачи — в ручную определять, где байты, а где коды. А ведь пора бы перейти и на блочно-модульное дизассемблирование с выходом на тексты языка высокого уровня. Причиной топтания на месте считаю неудачную идеологию дизассемблирования (линейную) в этих, да и других дизассемблерах тоже. Представляя свой дизассемблер RD16.exe, пытаюсь продемонстрировать и новую идеологию дизассемблирования (мозаичную), которая позволяет более эффективно и более качественно решать те же задачи. Полагаю, что и перспектива развития дизассемблирования открывается иная.

Читать еще:  Защита от нсд

История рождения

Происхождение Русского Дизассемблера довольно древнее. Это началось еще в Советские времена, когда IBMок у нас еще и не было, но появились первые любительские компьютеры. В частности «Специалист», если кто-то еще помнит. Тогда на его базе я сделал свой компьютер «Специалист_МХ», с RAMDISKом, с «операционной системой» по внешнему подобию «Нортона», с дисководами. Успел по тиражировать по стране. Вот тогда я и столкнулся с потребностью дизассемблирования. С одной стороны это прекрасная практика познания ассемблерного языка, и школа обучения писать на нем. С другой стороны это удобный способ адаптации программ к новым нуждам. А когда дело дошло до больших программ типа LAYOUT, BASIC, то потребовался дизассемблер более мощный. Вот тогда я и написал свой первый дизассемблер. Именно в нем я тогда применил и отработал свою идеологию дизассемблирования и весьма успешно. Правда, тогда я не думал, что она какая-то особенная, считал само собой разумеющейся.

Однако пришло время, «Специалист» тихо ушел из жизни. И я перешел уже на более современную технику. Так уж получилось, что первое, с чем я познакомился, оказался дизассемблер SOURSER. Ох уж и поплевался я тогда. Положить в основу автоматического дизассемблирования абсолютно неверную идеологию, буквально с точностью до наоборот. Впрочем, к первопроходцам все равно надо относиться с уважением. Им всегда труднее. Вот тогда я и решил не дать умереть своей идее, переложить ее на современный компьютер.

Путь был не легкий и не быстрый. Писать библиотеку команд тогда было просто немыслимо. Информации явно не хватало. Пришлось взять из SOURSERa версии 1.07. Дизассемблировал ее с помощью версии 3.07. Угрохал кучу недель, прежде чем получил приемлемый текст. Да и дальше довольно долго многие куски программ нельзя было трогать, пока не утряс все OFFSETы и прочее.

В итоге родился RD16, в котором от SOURSERa осталась только библиотека команд. Набор процессоров тоже сохранен, правда, все их не проверял, не на чем было. Однако теперь тип процессора определяется автоматически. В итоге теперь на RD16 туже работу можно сделать и за один вечер. Кстати, свои программы не плохо проверять дизассемблером. Видны становятся многие ошибки в программе. Да и мусора выплывает не мало. Случается, процедуры, ранее используемые, а потом выключенные, остаются.

Идеология дизассемблирования

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

В SOURSERe основное внимание было уделено первой функции — автоматичности. Однако эффективность машинной работы была низка. Да и откуда она могла взяться при примитивном линейном алгоритме — сплошняком декодируй все байты файла, а потом гадай, где реальные коды, а где ложные. Даже человеку не просто решить эту задачу. И он то, чаще всего, применяет метод «научного тыка», по наитию. А как машину научить этому наитию?

В IDA PRO внимание уже уделили второй функции — интерактивности. И наработали мощный ресурс для ручной работы. Однако примитивный алгоритм машинной работы остался в общем прежним. И потому немалая часть этого ресурса направлена на компенсацию неэффективной машинной работы.

Все программы состоят из двух частей — области кода и области данных. И задача дизассемблирования прежде всего разобраться — что и где. Нагружать человека этой работой неразумно. Слишком уж она рутинна и объемна. Поэтому разделение труда должно быть не только количественное, а, прежде всего, качественное. Ясно, что человек умнее любой машины. Поэтому и заниматься он должен самой умной работой, оставив машине всю примитивную и рутинную. Иначе говоря, машина должна выявлять машинную функцию байтов кода, а человек ее смысловую функцию.

Главной частью программы, конечно, является код, а область данных, как приложение к нему и потому как бы вторична. Именно это представление сыграло злую шутку с разработчиками дизассемблеров. Они свое представление передали и дизассемблеру в виде обобщенного принципа. Вся дизассемблируемая программа является ОБЛАСТЬЮ КОДА, и задача машины в автоматическом режиме выявить области данных. А для того чтобы машина решила задачу в этом режиме четко и однозначно, ей должны быть даны также четкие и однозначные инструкции. А их увы, просто не существует при той идеологии. Потому мир дизассемблирования и топчется на месте.

Русская идеология

В русском дизассемблере подход прямо противоположный. Вся дизассемблируемая программа представлена как ОБЛАСТЬ ДАННЫХ. И задачей дизассемблера является наоборот выделить область кода. А что останется, то и будет областью данных. И здесь на первый вопрос машины — а с чего начать, где взять первый байт кода? — ответ четкий и однозначный. У любой программы есть точка входа и где находится ее адрес тоже известно. Поэтому первая инструкция проста — бери стартовый адрес. Он указывает на первый байт кода. Следующая инструкция — декодируй первый байт. Далее анализируй. Если команда простая, типа MOV, ADD, значит за ней следующий байт кода. Тогда шагай на него и снова декодируй. Если встретилась команда JMP, тогда инструкция — за нее шагать нельзя. Там еще не ясно что. Но, у команды JMP есть операнд, который четко указывает на область кода. Соответственна и инструкция будет однозначна — бери адрес перехода и продолжай шагать с новой области кода. Если встретилась команда RET, или функция DOS — завершить процесс, тогда остановись и оглянись назад. Возможно, по ходу процесса встречались условные переходы. Они возможно указывают еще на не пройденные области кода. Тогда их надо пройти. А уж когда все адреса кода отработаны, тогда заверши процесс. Настало время представить результат человеку для творческой работы.

Разумеется, по ходу процесса будут встречаться команды CALL вызова процедуры. На первый взгляд ситуация не сложная. Эта команда предполагает возврат на место после нее. А значит запомни адрес вызова и шагай дальше. Однако, на практике не во всех процедурах авторы предусматривают этот возврат. Они, пусть и не часто, но могут завершиться функцией DOS — завершить процесс. А это значит, после такой команды CALL продолжения кода может и не быть. Возможны и другие варианты, например текстовые сообщения, после команды CALL, и только после этого сообщения продолжение кода. По этой причине дизассемблеру дана четкая инструкция — при первой встрече всегда прерви текущую дорогу кода, войди в процедуру и изучи ее по выше описанному алгоритму. А по результату принимай решение. Если есть хотя бы одно нормальное завершение процедуры командой RET, тогда вернись из нее и продолжи предыдущую траекторию кода. Иначе прервись.

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

Помимо основного процесса есть и попутные, параллельные. Например, не маловажной задачей является выявление OFFSETных меток. Здесь дизассемблеру дана инструкция — при встрече команд обращающихся к памяти, обрати внимание, какой регистр используется для этого. Затем оглянись назад и найди место, где была последняя загрузка в этот регистр, и в этом месте оставь самому себе дополнительную инструкцию — автоофсет. На следующем проходе она будет отработана. Разумеется, машине не всегда удается решить эту задачу, поэтому на втором проходе машине дана инструкция — все места загрузки регистров без автоофсета пометь, как проблемные, в помощь человеку.

Подробнее об интерактивном режиме, распаковке файлов в процессе дизассемблирования можно узнать в пакете программы RD16. Она выставлена в разделе «дополнения к языкам программирования».

Ссылка на основную публикацию
ВсеИнструменты 220 Вольт
Adblock
detector