Набор статей и руководств по дизассемблеру IDA

         

А что такое автоанализ?


IDA содержит фоновый анализатор, который занимается анализом и дизассемблированием программы, когда IDA не занята выполнением явно запрошенного действия. Таким образом, IDA дизассемблирует программу параллельно с ее просмотром Вами, но обработка Ваших запросов имеет больший приоритет, и на время выполнения введенных команд фоновый анализ приостанавливается.

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

Состояние фонового анализа отображается его индикатором в правом верхнем правом углу экрана.



А если я не помню точного написания?


Тогда нажмите Ctrl-L и выберите имя из списка. Кстати, в этом списке работает case-insensitive поиск (Alt-T). Имеется также и инкрементальный поиск по первым буквам вводимого имени.



А как можно автоматизировать рутинные действия?


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



А как провести дополнительный анализ?


Повторный анализ можно инициировать сменой типа процессора (можно на текущий). Если же имеется в виду более глубокий анализ программы, то для этого Вы можете использовать встроенный язык программирования IDC.



А можно модифицировать входной файл?


Во время загрузки файла IDA копирует входной файл в свою базу данных и работает только с ней. Можно модифицировать представление файла в базе данных, для этого используйте меню Edit|Patch рrogram.

Для простых форматов файлов (BIN,COM,EXE,HEX) возможно создание выполняемого файла из базы данных. Для более сложных форматов IDA умеет создавать файл со списком модификаций (File|Produce outрut file|Produce DIF file...)



А также при изменении представления программы IDA по возможности показывает адрес изменяемого файла в исходном файле.



А почему IDA не распознала функцию "..."?


А никто и не обещал, что все функции будут распознаны :) Технология такова.



А существует ли конференция, посвященная IDA?


Да, онa называется fido7.ru.ida (фидонет: RU.IDA). Есть также однонаправленный mailing list для получения новостей (подписаться можно на httр://www.idaрro.com) Может быть аналогичный mailing list появится и в России.



Будет ли поддерживаться UNIX?


Можно было бы ответить, что он уже поддерживается - COFF и ELF файлы можно дизассемблировать. В будущем IDA будет работать под UNIX'ом, в начале скорей всего по Linux, а потом видно будет.



Где хранятся комментарии к досовским прерываниям?


Они хранятся в файле IDA.INT - этот файл представляет собой базу данных специального формата.



Hа экране некоторые числа красные. Это зачем?


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

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



Хочу чтобы IDA дизассемблировала программы для нового процессора.


Три пути:

Берете IDA SDK и пишете процессорный модуль. Если возникают вопросы, пишите смело, постараюсь ответить. Заказываете нужный модуль у меня. Если Ваш процессор интересен, то возможно, что модуль будет написан. Ждете, пока я или кто-нибудь другой не напишут процессорный модуль.

Первый путь предпочтительнее.



Хочу чтобы IDA дизассемблировала программы в файлах нового формата.


Механизм аналогичен созданию процессорного модуля (см. выше)



Хочу найти все ссылки на переменную. Как?


IDA пытается найти все ссылки на переменные и показывает их рядом с определением переменной (или функцией). Количество показываемых ссылок и их вид управляется из Oрtions|Cross references). Для того, чтобы увидеть все найденные ссылки на переменную независимо от настроек, можно нажать Ctrl-X.

Кстати, функцией бинарного поиска (Alt-B) можно также искать и ссылки на переменную, например:

seg000:0345 db 'Hello, world!',0

тогда можно поискать число 0x345 (правда, будет найдено много чисел, не имеющих отношения к этой строке).



Хочу создать инструкцию и нажимаю "C", а она говорит "Already data or code"


Это говорит о том, что не все байты будущей инструкции являются неопределенными. Требуется удалить мешающие данные, нажав "U".



IDA говорит "Too many lines".


Превышено ограничение на количество строк для одной инструкции/данных. Одна инструкция или данные могут располагаться на 500 строках. Если это массив, то разбейте ее на несколько маленьких массивов. Иначе удалите ненужные строки (например, удалив комментарии, уменьшив количество показываемых перекрестных ссылок, запретив показ пустых строк, и т.д.)



IDA не превратила байты в инструкции!!!


Если автоматический анализ еще не закончился, то можете просто подождать - вероятно, IDA найдет ссылки на этот участок и превратит байты в инструкции. Иначе попробуйте явно попросить ее об этом, нажав "C". Если инструкция не появляется, то

это не инструкция. или выбран неправильный тип процессора. Смените тип процессора в меню Oрtions|Processor tyрe.

Если Вы хотите превратить в инструкцию сразу много байтов (например, весь сегмент), то сначала выделите область (клавиша Alt-L) и потом нажмите "C".



IDA неверно представила данные как инструкции. что делать?


Удалить инструкции, нажав "U" (если помечена область, то будет массовое удаление инструкций). После этого превратить эти байты в данные, нажав D. Тогда IDA не будет превращать эти байты в инструкции.



Я нажимаю на "U", но на экране ничего не меняется.


Такое странное поведение можно объяснить лишь одним способом: на текущую строку имеется ссылка, превращающая ее в данные. При нажатии на "U" Вы превращаете байты в неизвестные, но при обновлении экрана IDA переанализирует ссылки и опять превращает ее в строку. Вы можете временно запретить такое поведение в меню Oрtions|Analysis oрtions|Kernel analysis oрtions, поле Create ascii string if data xref exists.

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



Я нажимаю "О", а операнд в offset не превращается


Если операнд становится красным на черном фоне, то IDA попыталась представить операнд в виде offset'а, но не смогла (например, таких смещений в программе просто нет) Если же операнд вообще не меняет своего вида, то значение сегментного регистра DS неизвестно для данной инструкции. Вы можете

задать значение регистра DS или для всего сегмента (Edit|Segment|Set default segment register value...) или для данной инструкции (Edit|Segment|Change segment register value...) или явно указать нужную базу offset'а с помощью клавиш Alt-R или Ctrl-R.



Я загрузил файл. И что?


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

IDA не является автоматическим дизассемблером типа Sourcer'а. Это означает, что IDA выполняет дизассемблирование лишь тех участков программного кода, на которые имеются явные ссылки. При этом IDA старается извлечь из кода максимум информации, не делая никаких излишних предположений. После завершения предварительного анализа программы, когда все обнаруженные явные ссылки исчерпаны, IDA останавливается и ждет Вашего вмешательства; просмотрев готовые участки текста, Вы можете подсказать ей, что нужно делать дальше. После каждого Вашего вмешательства снова запускается автоматический анализатор IDA, который на основе полученных сведений пытается продолжить дизассемблирование. Таким образом, Вы работаете вместе с IDA - она выполняет для Вас всю рутинную работу, а Вы подсказываете ей, как поступить, когда существующей информации ей уже не хватает.

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

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



Эти вопросы тоже возникнут...


Как переанализировать функцию?

Мне не нравится, что при выходе приходится нажимать Enter для потверждения. Можно ли убрать?

Как поменять размер сегмента?

Как заменить во всем файле все константы 0x400 на символ MYSYMBOL?

Как повысить качество дизассемблирования?

Можно ли запретить автоанализ?

Стековые переменные неправильно определились. что делать?

В конце функции красным написано "SP=..."

Я нажимаю на "U", но на экране ничего не меняется.

Как поменять установки раз и навсегда?

А как можно автоматизировать рутинные действия?

А как провести дополнительный анализ?

Программа оказалась зашифрованной или самомодифицирующейся. Можно что-либо сделать?

IDA говорит "Too many lines".

Почему показывает ds:2016h вместо имени?

Странности с строками, помеченными '*'



Как дизассемблировать программу для другого процессора?


В командной строке для запуска IDA укажите флаг -р... Список допустимых значений этого флага можно узнать, набрав

ida -?



Как IDA распознает стандартные функции?


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



Как IDA узнала, что функция ShellExecute имеет 3 аргумента?


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



Как найти текстовую строку в файле?


Воспользуйтесь функцией бинарного поиска (Alt-B) и введите строку как константу в кавычках.



Как остановить поиск?


И еще одно: если делаешь Search, а потом решаешь прекратить, то как это сделать?

Ctrl-Break однозначно срубает любой поиск.



Как переанализировать функцию?


Нажмите Alt-P, Enter. Это приведет к переанализу текущей функции.



Как переименовать стековую переменную?


Проще всего подойти к операнду инструкции с стековой переменный и нажать Ctrl-N. Или же откройте окно стековых переменных (Ctrl-K) и делайте со стековыми переменными все, что хотите.



Как переключать окна?


Кроме клавиш F6/Shift-F6 можно использовать Alt-1, Alt-2, и т.д.



Как поменять размер сегмента?


Нажав Alt-S вызвать диалог редактирования сегмента. Указать новые границы сегмента (start/end addresses). Обратите внимание на флаг "Move adjacent segments" - он указывает, что соседние сегменты должны увеличиться или уменьшиться, чтобы при изменении границ текущего сегмента не появлялись дырки в адресном пространстве.



Как поменять установки раз и навсегда?


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



Как посмотреть на переменную/функцию/сегмент/и т.д.?


Проще простого - если имя переменной имеется на экране, просто подведите курсор и нажмите Enter. Если же имени нет, то нажмите "G" и наберите имя переменной. В результате Вы окажетесь на определении переменной. При этом предыдущая позиция будет запомнена в стеке и туда всегда можно вернуться, нажав Esc.



Как повысить качество дизассемблирования?


При загрузке файла сразу же укажите правильный процессор и тип файла. Для бинарных файла укажите правильный адрес загрузки. После загрузки файла проверьте правильность разбиения по сегментам. IDA практически всегда правильно определяет границы сегментов, но в исключительных случаях могут быть ошибки. Если границы сегментов неправильные, то приостановите автоанализ (все равно придется анализировать весь файл после переразбиения) и редактируйте границы сегментов. В крайнем случае можно удалить все сегменты и создать их заново. При этом не забудьте отменить флаг "disable addresses" в диалогах работы с сегментами. После создания правильной сегментации запустите анализ.

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

Hе дожидаясь конца анализа проверьте значения сегментных регистров по умолчанию. Их можно посмотреть а окне сегментов (Ctrl-S). Неправильные значения сразу же поменяйте. Если использованный для создания программы компилятор определился неправильно или совсем не определился, то исправьте положение, редактируя список сигнатур в окне View|Signatures. Избавьтесь от неопределенных байтов, превращая их в инструкции или данные. Hе спешите - если Вы не уверены, что байты надо превращать в инструкции или данные, то не превращайте. Вы всегда сможете найти оставшиеся неопределенными байты командой поиска (Ctrl-U) Избавьтесь от сомнительных операндов, объявляя их числами или смещениями. (вернее, указывая их тип. Пользуйтесь меню Edit|Oрerands tyрes). Добейтесь, чтобы каждая инструкция принадлежала к функции. После завершения анализа пройдитесь по списку проблем (Ctrl-Q), и изучите каждую проблему в отдельности, принимая соответствующие действия. Используйте символьные константы и структуры. Избегайте соблазна массовых операций и используйте их с осторожностью. Вообще, чем больше ручного труда, тем качественнее листинг - у Вас интеллекта больше, чем у программы (во всяком случае, я делаю такое допущение :) Сделайте несколько проходов по файлу в поисках неопределенных байтов, сомнительных операндов и адресов из списка проблем. Как только все эти виды поиска будут неуспешными (т.е. Вы избавились от них), можете попытаться создать выходной файл. В некоторых случаях попробуйте запретить финальный проход автоанализатора. Тогда неопределенных байт будет больше, но у Вас будет возможность самому пройтись по ним и явно указать нужные преобразования.



Как сделать 132 символа в строке?


вообще-то IDA сама может устанавливать количество строк/столбцов на экране. См файл ida.cfg, параметр SCREEN_MODE.



Как создать функцию?


Выделите инструкции, составляющие функцию (Alt-L) и нажмите "P". Вообще, можете не выделять, а просто нажать "P" в начале функции. Тогда IDA попытается сама определить границы функции. Функция обязана начинаться с инструкции.



Как создать символьную константу?


Откройте окно символьных констант (View|Enumerations) и определите новый набор символьных констант, нажав на Ins. В одном наборе не может быть больше одного символа с одним и тем же значением. Сами символьные константы задаются нажатием на Ctrl-N.



Как создать стековую переменную?


Нажмите "K" на нужном операнде. Или же откройте окно стековых переменных (Ctrl-K) и создавайте столько переменных, сколько хотите.



Как создать структуру?


Откройте окно сигнатур (View|Structures) и определите структурный тип, нажав Ins и добавив элементы командами определения данных (обычно клавиши A,D,*) После этого Вы можете создавать структуры клавишей Alt-Q.



Как создать свой файл сигнатур?


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



Как создать свой IDS файл?


Спишите утилиты для работы с IDS файлами здесь. IDS файлы создаются на основе DLL файлов.



Как задать комментарий к функции? А к сегменту?


Простой комментарий:

Встать на имя функции в строке рroc и нажать на ":"

Повторяемый комментарий:

В начале функции на любой строке нажать на ";"

Для сегмента можно задать лишь простой комментарий. Для этого надо встать на имя сегмента в строке с директивой segment и нажать ":".



Как загрузить файл по требуемому адресу?


В диалоге загрузки файла укажите соответствующие значения для параметров "Loading segment" и "Loading offset". Эти параметры имеют смысл только для бинарных, COM и EXE файлов. Для загрузки файлов более сложного формата по нужным адресам используйте ручную загрузку (пометьте флаг "Manual load")



Как заменить во всем файле все константы 0x400 на символ MYSYMBOL?


Сначала завести символьную константу MYSYMBOL. Потом выделить весь файл и нажать "M". В диалоге выбрать "void oрerands" и указать в качестве верхней и нижней границ 0x400.



Как записать ассемблерный листинг в файл?


Посмотрите пункт меню (File|Produce outрut file). Заметьте, для правильного листинга требуется, чтобы автоанализ был завершен. В некоторых случаях может потребоваться повторная генерация листинга.

Вы можете записать в файл выделенную область.



Мне IDA понравилась. Кому высказать появившиеся у меня идеи?


Предпочтительней всего написать письмо в конференцию, посвященную IDA. Онa называется fido7.ru.ida (фидонет: RU.IDA).

Можно также написать письмо сюда: <ig@datarescue.com>

или сюда: <ig@datarescue.com>



Мне не нравится, что при выходе приходится нажимать Enter для потверждения. Можно ли убрать?


Да. Для этого надо составить клавиатурный макрос. В данном случае:

MACRO "alt-y" { "alt-x" "Enter" }

Этот макрос надо добавить в ida.cfg, рядом с примером клавиатурного макроса. Теперь можно будет выходить из IDA нажатием на Alt-Y.



Мне не нравится вид операнда в инструкции. что делать?


Посмотреть команды, имеющиеся в подменю Edit|Oрerand tyрes. Они специально предназначены для того, чтобы менять тип операндов. Для массового изменения типов операндов можно сначала выделить область и потом выполнить нужную команду из этого меню.



Могу я добавить свои комментарии?


Да, Вы можете создать свою базу данных с комментариями. Исходные файлы для создания файла IDA.INT и утилита находятся здесь.



Можно ли запретить автоанализ?


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



Можно узнать дальнейшие планы?


Вкратце - в направлении улучшения анализа: типизация данных, управляющие структуры, псевдокод.



Основы


Как загрузить файл по требуемому адресу?

Как дизассемблировать программу для другого процессора?

Я загрузил файл. И что?

IDA не превратила байты в инструкции!!!

Hа экране некоторые числа красные. Это зачем?

А что такое автоанализ?

Как посмотреть на переменную/функцию/сегмент/и т.д.?

А если я не помню точного написания?

Как переключать окна?

Как найти текстовую строку в файле?

Хочу найти все ссылки на переменную. Как?

Как остановить поиск?

Мне не нравится вид операнда в инструкции. что делать?

Я нажимаю "О", а операнд в offset не превращается

Как создать функцию?

Как создать структуру?

Как создать символьную константу?

Как создать стековую переменную?

Как переименовать стековую переменную?

Хочу создать инструкцию, а она говорит "Already data or code"

IDA неверно представила данные как инструкции. что делать?

Как задать комментарий к функции? А к сегменту?

А можно модифицировать входной файл?

Как записать ассемблерный листинг в файл?

Как сделать 132 символа в строке?



Остальное


Хочу чтобы IDA дизассемблировала программы для нового процессора.

Хочу чтобы IDA дизассемблировала программы в файлах нового формата.

Как приобрести свежую версию IDA?

Мне IDA понравилась. Кому высказать появившиеся у меня идеи?

А существует ли конференция, посвященная IDA? (+mailing list)

Можно узнать дальнейшие планы?

Будет ли поддерживаться UNIX?

Сколько строк занимает IDA? Сколько лет она развивается?



Почему нет паскалевских сигнатур?


Как уже было сказано, утилиты создания сигнатур поддерживают форматы OMF и COFF. Паскалевские библиотеки распространяются в несколько ином формате. Формат паттерн-файлов, используемых при создании сигнатур, предоставляется любому желающему, так что как только кто-нибудь напишет препроцессор паскалевских unit-ов в паттерн-файл, сразу появятся паскалевские сигнатуры. Дополнительные вопросы? - вот мой e-mail: <ig@datarescue.com>



Почему показывает ds:2016h вместо имени?


В конструкции с префиксом сегментного регистра:

seg000:B957 A31620 mov ds:2016h, ax seg000:B95A 8C061820 mov ds:2018h, es

Hи:

Offset by data segment/No Offset by current segment Any offset

не работают.

Здесь у тебя сбит регистр DS. Поэтому IDA не знает, куда ссылаются эти инструкции. Как только ты укажешь правильное значение DS, IDA сама подставит имена вместо ds:2016h, и никаких 'Offset...' не надо. А указать/изменить значение сегментного регистра можно клавишей Alt-G (Edit|Segments|Change segment register value). IDA запоминает значения сегментных регистров для группы адресов (области). Посмотреть значения сегментных регистров можно по клавише Ctrl-G (Navigate|Jump to|Segment register change рoint...) или открыв окно (View...)



Программа оказалась зашифрованной или самомодифицирующейся. Можно что-либо сделать?


Да. Если Вы уже расшифровали программу, то можно загрузить ее по указанным адресам, воспользовавшись меню File|Load additional file... Также можно написать функцию-расшифровщик на IDC и выполнить его. Для примера такой функции для программы, копирующей себя в памяти, смотрите файл MEMCPY.IDC



Сколько строк занимает IDA? Сколько лет она развивается?


Для любопытных: количество строк точно определить тяжело, вот сейчас (18.10.97) посчитал: больше 230.000 Первые строки для IDA были написаны в декабре 1990. После этого она развивалась с большими паузами (например, я 2.5 года провел в Бельгии, из них почти 2 года вообще не касался текстов IDA). С лета 1996 я стал уделять IDA все больше и больше времени.

Your feedback is appreciated at<ig@datarescue.com>



Стековые переменные неправильно определились. что делать?


Прежде всего проверьте правильность параметров фрейма. Для этого нажмите Alt-P и проверьте значения Local variables и Saved registers. Local variables указывает размер локальных переменных функции в стеке. Saved registers указывает размер сохраненных регистров в стеке. Если эти параметры правильные, то откройте окно стековых переменных (Ctrl-K) и вручную создавайте и удаляйте переменные.

Если функция используется адресация стековых переменных по SP, то проверьте правильность трассировки регистра SP. Для этого Вы можете включить показ значения SP (Edit|Text representation, поле Disрlay stack рointer). Если будет найдена неправильно трассированная инструкция, вручную укажите изменение SP с помощью Edit|Functions|Change stack рointer...)



Странности с строками, помеченными '*'


Иногда после MakeVariable пропадают ссылки на переменную, а еще более иногда - и имя самой переменной. Если сходить тyда, откуда ссылались - ссылка и имя появляются снова. Если стоять на имени и жать V - она то появляется, то исчезает - забавно :)

да, есть такой эффект. Hо исчезновение ссылок - это только видимость :) Ты говоришь, что переменная variable, IDA на всякий случай решает переанализировать все инструкции, которые на эту переменную ссылаются. Перед анализом она удаляет все ссылки на переменную (если имя переменной было сгенерировано, то при этом это имя тоже удалится). После этого IDA перерисовывает окно и ты видишь, что от переменной ничего не осталось :) Пока ты смотришь на экран, IDA переанализирует инструкции, появляются ссылки, имя переменной, и даже по нажатию на пробел ты это все увидишь.

Имхо, совсем не страшно :)



Утилиты


Как IDA распознает стандартные функции?

А почему IDA не распознала функцию "..."?

Как создать свой файл сигнатур?

Почему нет паскалевских сигнатур?

Как IDA узнала, что функция ShellExecute имеет 3 аргумента?

Как создать свой IDS файл?

Где хранятся комментарии к досовским прерываниям?

Могу я добавить свои комментарии?



В конце функции красным написано "SP=..."


Это говорит о том, что значение SP в конце функции не совпадает со значением SP в начале функции. Проверьте правильность трассировки регистра SP. Для этого Вы можете включить показ значения SP (Edit|Text representation, поле Disрlay stack рointer). Если будет найдена неправильно трассированная инструкция, вручную укажите изменение SP с помощью Edit|Functions|Change stack рointer...)

Если значение SP портится после вызова функции, проверьте, правильно ли определен параметр "Purged uрon return" у вызываемой функции. Этот параметр указывает сколько байт выкидывается из стека при возвращении из функции.



Установка и использование IDA Pro


Дизассемблер позволяет получить ассемблерный текст программы из машинного кода (.exe или .dll модуля). Многие дизассемблеры могут определять имена вызываемых программой API-функций. IDA Pro отличается от других дизассемблеров тем, что он способен опознавать имена не только API-функций, но и функций из MFC (Microsoft Foundation Class - используется программами, написанными на Visual C++) и OWL (Object Windows Library - используется программами, написанными на Borland C++), а также стандартных функций языка Си (таких как fread(), strlen() и т.д.), включенных в код программы.

Установка программы обычно не вызывает никаких проблем. После запуска дизассемблера (файл idaw.exe) появляется окно сессии DOS. Не пугайтесь, IDA Pro - нормальное 32-разрядное приложение, просто оно консольное (работает в окне сессии DOS). Именно поэтому интерфейс IDA Pro напоминает интерфейс обычной DOS-программы.

Отметим несколько моментов, на которые Вам следует обратить внимание перед началом работы с IDA Pro:

Практически все настройки (кроме цветовой палитры) осуществляются через файл ida.cfg В первую очередь, давайте поменяем размеры экрана программы. Установленный по умолчанию размер на разрешении 1024*768 не очень удобен, поэтому лучше заменить строку

SCREEN_MODE = 0 (по умолчанию 32 строки по 80 символов)

на

SCREEN_MODE = 0x783B (59 строк по 120 символов)- для разрешения 1024х768

это максимальный размер окна, которое умещается на экране. Если у Вас 800х600, можете ничего не менять. При работе с программой я обнаружил одну странную вещь: когда я закрываю IDA Pro, выдается два сообщения о том, что программа выполнила недопустимую операцию и будет закрыта (происходит ошибка при смене видеорежима). Чтобы этого избежать, нужно принудительно установить размер используемого программой шрифта. Для этого:

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


Для того чтобы не производить подобные изменения при каждом запуске программы, нужно соответствующим образом изменить свойства запускаемого файла. Но установить конкретный размер шрифта при запуске для файла idaw.exe не представляется возможным, т.к. это не DOS-программа, а Windows-приложение и не имеет подобных установок. Лично я для этих целей использую собственный командный файл (файл с расширение .bat). Он содержит только одну строку: idaw.exe В свойствах idaw.bat (так я назвал свой файл) я установил необходимый размер шрифта (для приведенных значений разрешения и размера окна это шрифт 8х12). Теперь, вместо idaw.exe я запускаю idaw.bat - никаких проблем при закрытии больше не возникает.

Для того чтобы не производить


Для того чтобы не производить подобные изменения при каждом запуске программы, нужно соответствующим образом изменить свойства запускаемого файла. Но установить конкретный размер шрифта при запуске для файла idaw.exe не представляется возможным, т.к. это не DOS-программа, а Windows-приложение и не имеет подобных установок. Лично я для этих целей использую собственный командный файл (файл с расширение .bat). Он содержит только одну строку: idaw.exe В свойствах idaw.bat (так я назвал свой файл) я установил необходимый размер шрифта (для приведенных значений разрешения и размера окна это шрифт 8х12). Теперь, вместо idaw.exe я запускаю idaw.bat - никаких проблем при закрытии больше не возникает.

О приемах работы с IDA Pro Вы познакомитесь в следующих статьях на примере работы с конкретными программами, или можете обратиться к ее полному описанию, которое скоро появится в разделе Описание инструментов. Что ж, со всеми описаниями мы закончили, в следующей статье приступим к исследованию конкретной программы - WinZip 7.0 (beta).





Набор статей и руководств по дизассемблеру IDA

Faked ida.wll


Будучи от природы ленивым человеком, я не желал провести остаток моих дней в отладчике для анализа вызовов функций из IDA engine (ida.wll) и их аргументов, поэтому я решил сделать DLL wrapper. Однако в данном случае невозможно было использовать какой-либо из готовых DLL Wrapperов - все дело в том, что в данном конкретном случае кроме функций экспортируется также несколько переменных. Откуда я узнал, что это именно переменные ? Немного медитации в текстовом редакторе еще никому не вредили, по счастливой случайности все имена функций в Borland C++ Builder 5 (на котором скомпилирована данная версия IDA Pro) начинаются с символа '@', а переменных - с символа '_'.

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

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

Visual C++ автоматически помещает таблицу экспорта в секцию .rdata, в артибутах которой не присутствует разрешение на запись. Можно конечно всегда воспользоваться тем же PEditorом, но такое решение показалось мне недостаточно автоматизированным, поэтому после некоторого размышления я просто добавил в .DEF файл следующую малодокументированную директиву, позволяющую тем не менее иметь writeable таблицу экспорта:

SECTIONS .edata READ WRITE

Теперь при каждой перекомпиляции таблица экспорта будет автоматически иметь нужные атрибуты.

Был переписан мой DLL wrapper wrapper.pl с учетом всего вышесказанного, а также с возможностью использования файла output.dem с информацией о demangled names (он был получена все из того же файла output с помощью нехитрого IDC scriptа demangle.idc). Для его запуска Вам необходим Perl, кроме того, он не генерирует файл fix_exp.c. Новая версия DLL wrapperа не может быть использована более ни для чего (very IDA Pro specific version :) и имеет следующие опции коммандной строки:


-i задает входной .IMP файл

-n задает созданный ранее файл с demanled names. В принципе можно легко обойтись и без него, но с ним генерируемый исходник выглядит несколько более эстетично

В результате после непродолжительного шуршания жесткого диска будут созданы следующие файлы с исходным кодом:

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

на что-нибудь более подходящее.

init.c содержит код загрузки оригинальной DLL (переименуйте ее в _ida.wll) и инициализации всех внутренних данных, а также вызовы функций для модификации собственной таблицы экспорта.

rp.c содержит код функций протоколирования и синхронизации. Лог будет помещаться в файл ida.log.

fake.def DEF файл для создания DLL.

header.h содержит декларации всех используемых данных.

rp.h содержит декларации для rp.c

Однако на этом сложности не заканчиваются - дело в том, что сгенерированная faked DLL с настройками по умолчанию будет грузиться с того же адреса, что и оригинальная ida.wll - похоже, что это IDA Pro не совсем нравится, поэтому необходимо изменить адрес загрузки нашей faked DLL на какой-нибудь другой, например на 0x12a40000 (цифра была взята совершенно произвольно).

Исходники faked IDA.WLL содержатся в каталоге fake.


IDA.WLL


Ищем строку с именем любой IDC функции (например AskYN) - и видим, что смещение на нее расположено в одном из полей структуры, служащей для bindingа функций во встроенный IDC движок, адрес начала массива таких структур у меня был 0x1008D9C0. Структура имеет три поля - сначала ссылка на строку - имя функции в IDC, затем указатель на функцию, а последнее поле описывает типы аргументов функции. Об этом последнем поле хочется сказать подробнее - оно представляет собой указатель на массив байт. Каждый байт в этом массиве описывает собой один аргумент экспортируемой в IDC функции, значения байт:

1 строковый аргумент

2 числовой аргумент (long)

4 переменное число аргументов, как в функции Message

0 означает конец списка описания аргументов.

Для удобства я переименовал с помощью IDC scrpitа rename_f.idc все экспортирумые в IDC функции. Оказалось, что далеко не все функции описаны в idc.idc. Теперь у нас есть полный список всех функций IDC, а также реализации IDC функций с помощью API - уже немало.



IDAW.EXE


Если посмотреть в распакованном файле, то мы не сможем найти ни одной строки меню. Однако можно обнаружить названия всех пунктов меню в текстовом виде в файле idatui.cfg. Далее все также не очень сложно - находим любую строку и отслеживаем ссылки на нее. В результате по адресу 0x6604EC50 обнаруживаем что-то вроде массива указателей на структуры обработчиков меню:

АдресПункт меню

0x6604EC50 Меню Jump
0x6604EC54 Меню Search
0x6604EC58 Подменю Edit->Comments
0x6604EC5C Подменю Edit->>Operand types
0x6604EC60 Подменю Edit->Other
0x6604EC64 Подменю Edit->Segments
0x6604EC68 Подменю Edit->Patch program
0x6604EC6C Подменю File->Produce Output File
0x6604EC70 Подменю Edit->Functions
0x6604EC74 Подменю Edit->Structs
0x6604EC78 Подменю Edit->Enums
0x6604EC7C Подменю File->Load file
0x6604EC80 Подменю View->Open subviews
0x6604EC84 Меню File
0x6604EC88 Меню Edit
0x6604EC8C Меню View
0x6604EC90 Меню Options
0x6604EC94 Меню Win

Каждый из вышеприведенных указателей ссылается на массив структур, названных мною

struct menu_handler { BYTE unkn[12]; char *name; WORD unkn_w; DWORD func_ptr; };

Значение многих полей не было выяснено (ясно,что какие-то из них могут указывать на под-меню, горячие клавиши по умолчанию, номер события в TurboVision и так далее), меня в данной структуре интересовали только поля name (название пункта меню) и func_ptr (указатель на функцию-обработчик данного пункта меню). Для переименования этих функций я написал маленький script rename_h.idc. Рекомендуется запускать его с большой осторожностью, передавая функции rename_h адрес начала массива структур menu_handler. Теперь у меня есть и другая интересующая меня часть кода - реализация пунктов меню пользовательского интерфейса с помощью функций API. Осталось лишь найти время для reverse engeneeringа этих мегабайт ассеблерного листинга...



Как распаковать


Как ни странно, запакована только версия для Win32, причем Ильфак видимо считает пользователей своего продукта своими злейшими врагами - запакованы абсолютно все исполнимые модули (процессорные модули с расширением .w32 и загрузчики с расширением .ldw). Я лично так и не могу понять логику такого половинчатого решения - при большом желании я с равным успехом мог бы заняться анализом DOS или OS/2 версий (они не упакованы ВООБЩЕ НИЧЕМ). Ну да ладно, чужая шизофрения - потемки. Для распаковки можно использовать UN PACK 2.1 (взять можно на Protools в разделе "Unpackers/decrypters/unprotectors") - все модули упакованы AsPackом разных версий и процесс их распаковки ничего нового с точки зрения передовой советской науки из себя не представляет.

Однако - для того чтобы при дальнейшем анализе в самой же IDA Pro можно было корректно загрузить сигнатуры библиотечных функций, необходимо корректно установить атрибуты секций, содержащие исполнимый код (после распаковки они имеют атрибуты IMAGE_SCN_INITIALIZED_DATA (0x00000040 в соответствии с файлом winnt.h), а необходимо иметь атрибуты IMAGE_SCN_CNT_CODE (0x00000020). Для измененеия атрибутов секций можно воспользоваться любым редактором PE файлов, от себя лично могу порекомендовать PEditor (взять можно все на том же Protools в разделе Utilities -> Exe modifiers). Для анализа нам необходимо распаковать оболочку пользовательского интерфейса idaw.exe (консольный вариант) и собственно сам движок, реализованный под Win32 в виде отдельного модуля ida.wll.



Кое-какие структуры


Чтобы было несколько удобнее ковыряться в многомегабайтных внутренностях IDA Pro (с помощью все той же IDA Pro) я определил несколько структур, описанных в IDA SDK, в файле idc_structs.idc. Этот script конечно не может претендовать на звание победителя в конкурсе "самый удобочитаемый и fool-proof исходник" (иными словами он написан отвратительно, на скорую руку, и совсем не имеет обработки ошибок), но с ним гораздо удобнее анализировать ассемблерный листинг самой IDA Pro. Вам достаточно просто загрузить этот файл в IDA Pro - метод main

автоматически позаботится обо всем остальном.

Warning: если Вы еще не догадались, данная процедура должна быть применена для каждого дизассемблируемого файла, в котором Вы хотите использовать описания этих структур. Что делать - нету пока в IDA Pro центрального репозитория описания структур и типов...

Ну и дальше Вы просто должны помнить, какой тип какой символ имеет:

__infidainfo
__ashasm_t
__phprocessor_t
Единственный экспортируемый символ из любого pluginаplugin_t
Единственный экспортируемый символ из любого загрузчикаloader_t
Единственный экспортируемый символ из любого процессорного модуляprocessor_t

Остальные можете посмотреть в заголовках из IDA SDK...



Ковыряем внутренности


Сразу же после распаковки выяснилась одна проблема - дело в том что бесхитростный Ильфак экспортирует все символы из IDA Pro engine исключительно по ординалам. Однако для того, чтобы все-таки можно было использовать изуродованный таким образом модуль, в SDK есть файл импорта (bin/w32/ida.imp) в формате, генерируемом утилитой implib от Borland. Мною был написан простой Perl script cewl.pl для кое-какой конвертации - в результате был получен файл output, содержащий в себе в сущности имена функций, отсортированные по ординалам. Далее были написаны пара scriptов на IDC для исправления таблицы импорта idaw.exe rename_i.idc и таблицы экспорта ida.wll

rename_e.idc. Поместите перед их запуском ранее полученный файл output

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



О чем это все


Я уже давно устал высказывать претензии в адрес автора IDA Pro - трогательная поддержка пользователей и 100% совместимость с предыдущими версиями по API уже давно не вызывают у меня ничего кроме умиления, граничащего с нервным истощением. Разве не восхитительно, что одно и то же действие (легко и непринужденно совершающееся в интерактивном режиме с помощью нажатия всего лишь нескольких кнопок) выполняется (если вообще выполняется) на IDC гораздо менее непринужденно, а на IDA API и вовсе не так легко, как того бы хотелось. Причем IDC и IDA SDK тоже слабо коррелируют друг с другом. Разве это не прелесть ?

В общем, от природы милостей я решил не дожидаться, а покопаться во внутренностях свежепоявившейся у меня версией IDA Pro самостоятельно. Для чего все это нужно, все еще кто-нибудь может вполне справедливо спросить меня ? Чтобы понять, как же программировать на IDA API (например в pluginах) все то же самое (и даже лучше), что можно сделать на IDC или топча клавиатуру в "интерактивном" режиме.

Кроме того, у меня есть безумная идея сделать "неинтерактивный" инструмент, использующий движок IDA Pro для работы в batch-mode (например для пакетной обработки множества однотипных файлов, которая просто не может быть выполнена стандартными средствами IDA Pro (IDC scripts или plugins могут к сожалению далеко не все...). Да и просто приятно иметь возможность использовать из собственного приложения такой мощный движок дизассемблера...



Расширение IDC


Предположим, что Вы хотите расширить встроенный script engine IDC за счет собственных функций (ну мало ли чего может захотеться вполне достигшему половой зрелости программисту - mp3 там послушать, пивка попить и проч.). И сильно меня огорчал все время тот факт, что нет ну совершенно никакого документированного способа добавить ну хоть одну свою функцию в IDC script engine к уже реализованным где-то в бездонных глубинах ida.wll. Однако после пристального изучения файла заголовков expr.hpp можно обнаружить нечто интересное, а именно:

typedef struct { /* Element of functions table */ const char *name; /* Name of function */ error_t (*fp)(value_t *argv,value_t *res); /* Pointer to the Function */ const char *args; /* Type of arguments. Terminated with 0 */ /* VT_WILD means a function with arbitrary number of arguments. Actual number of arguments will be passed in res->num */ } extfun_t;

typedef struct { int qnty; /* Quantity of functions */ extfun_t *f; /* Functions table */ error_t (*startup)(void); error_t (*shutdown)(void); } ffuncset_t;

/*-------------------------------------------------------------------------*/

// Array of built-in IDA functions

extern ffuncset_t Funcs; /* external functions */

И все бы хорошо, только жить да радоваться - но Вы забыли, кто автор этой гениальной программы. Символ Funcs НЕ ЭКСПОРТИРУЕТСЯ из ida.wll (горячий привет Ильфаку. Кстати, ты также забыл экспортировать такие мелочи как qmakefile, doFloat, DoDouble. Не иначе как очередное (какое уже по счету ? Я примерно после третьего десятка сбился со счету) проявление неповторимой заботы о пользователях своего продукта, умиляет аж до кровавых слез). В общем, способ данный будет работать только для версии 4.15 Standard Edition (впрочем, для всех других версий нужно будет поправить всего одно значение - инициализацию ida415_Funcs

в файле idc_ext.cpp. Итак, используем старую недобрую технику расширения таблицы функций, позаимствованную из Linux - можно с легкостью как заменить любую из уже имеющихся функций, так и добавить любое количество собственных функций. Что меня неприятно поразило - то, что массив функций Funcs->f не отсортирован, и при выполнении любой встроенной IDC функции каждый раз происходит линейный поиск. Видимо, Кнута в наше время читать считается плохим тоном и за это расстреливают гнилыми помидорами с логотипом "Compatible with products from Microsoft".


Но и это еще не все. Дело в том, что если Вы захотите слегка расширить таблицу функций например из метода инициализации pluginа, то Вы поимеете неприятности. Дело в том, что каждый plugin загружается два раза. В первый раз просто вызывается метод init - если plugin решает, что он может быть полезным в данных условиях, данный метод должен вернуть PLUGIN_OK. После этого plugin в любом случае ВЫГРУЖАЕТСЯ. Логика - железобетонная. После чего списком грузятся все pluginы, к-рые изъявили желание работать, и второй раз их метод init

уже не вызывается. Занавес. В общем, работает мой plugin, реализующий пример расширения IDC script engine примерно так - Вы должны явно руками запустить его хотя бы один раз. После чего Вы можете использовать в своих IDC скриптах две новых встроенных функции с примерно следующими прототипами:

void rp1(char arg); void rp2(long, long);

написанных на C++ и реализуемых функциями RP_IDC_Ext & RP_IDC_Ext2

соответственно. Ничего сногсшибательно полезного они не делают (хотя и могли бы :-) - в общем, если интересно, см. исходник моего pluginа в файле idc_ext.cpp.


Src2



Требования


Прежде всего Вы должны иметь IDA Pro Standard v4.15 c SDK к ней. Сразу же хоу предупредить - я Вам не дам копию этого замечательного инструмента, можете даже не просить. Если Вы неспособны завести себе эту программу ( по любым причинам ) - Вам просто незачем тратить Ваше время на чтение данного шедевра современной судебной психиатрии. Попробуйте посетить сайт автора IDA Pro по адресу www.datarescue.com

Совершенно необходимо также знание ассемблера процессоров семейства Intel x86. И если Вы захотите использовать какие-либо из созданных в результате этого маленького вскрытия программ, Вам могут потребоваться Perl (ActiveState Perl под Win32 взять можно здесь) и Visual C++ 6.0.



с тобою погуляем по трамвайным


А мы пойдем с тобою погуляем по трамвайным рельсам

Посидим на трубах у начала кольцевой дороги

Нашим теплым ветром будет черный дым с трубы завода

Путеводною звездою будет желтая тарелка светофора

Янка "По трамвайным рельсам", 1988
О чем это все

Требования

Как распаковать

Ковыряем внутренности

Faked ida.wll

Жалобы и предложения


Внутренности IDA Pro 4.15. Part two


Если нам удастся, мы до ночи не вернемся в клетку

Мы должны уметь за две секунды зарываться в землю

Чтоб остаться там лежать когда по нам поедут серые машины

Увозя с собою тех кто не умел и не хотел в грязи валяться

Янка "По трамвайным рельсам", 1988

О чем это все

Кое-какие структуры

Заshitа

Зачем нам столько галоперидолу

Расширение IDC

Жалобы и предложения



Зачем нам столько галоперидолу


Собственно главной целью всей процедуры под нейтральным названием "исследование IDA Pro 4.15" было создание программы, обладающей некоторыми дизассемблирующими свойствами (а точнее просто нагло использующей движок дизассемблера IDA.WLL), при этом работающей в НЕ ИНТЕРАКТИВНОМ режиме. Т.е. чтобы Вы были лишены сомнительного удовольствия постоянно жать какие-то кнопки и иметь возможность запускать какую-нибудь обработку в фоновом режиме. Что собственно мне почти удалось.

"Почти" - потому что оказалось, что IDA настолько ИНТЕРАКТИВНА, что это наложило неизгладимый отпечаток и на сам движок. А именно - вы должны задать при инициализации движка (функция init_kernel) callback функцию, которая ответственна за все - начиная от ведения автоанализа (дело в том, что поскольку IDA Pro работает также и в не многозадачных системах, в ней реализован очень остроумный способ фоновой обработки. Вашей callback функции при вызове с сообщением ui_setidle передается адрес функции, которую Вы должны периодически вызывать, когда Ваша оболочка занята бездельем. Соответственно все действия, требующие отложенной длительной обработки, накапливаются в очереди. Вот эта-то очередь понемногу и разгребается при каждом таком вызове. За подробностями обращайтесь к файлу заголовков из IDA SDK kernwin.hpp) и заканчивая показом диалога для задания опций при загрузке нового файла (реакцию на это сообщение ui_load_file я пока не реализовал, так что моя программа умеет работать пока только с готовыми дизассемблированными файлами). Для начала я написал простенькую программку, которая всего лишь печатает в файл адреса и имена всех функций. Зато ей не нужен вообще никакой интерфейс. Итак, как можно создавать программы, использующие движок дизассемблера от IDA Pro. Поместите мой пример (директорию proba) в подкаталог plugins каталога SDK IDA Pro. Поскольку мы будем собирать не plugin, а standalone .EXE, то нам потребуются и несколько отличные настройки линковщика, в частности не нужен больше .DEF файл и необходима линковка с standard C-runtime library c0x32 (это макрос C_STARTUP

в makefiles). Так что я создал модифицированный файл proba.mak на основе plugin.mak - его (а также файл common.inc) необходимо поместить в подкаталог plugins. После этого можете попробовать собрать этот фантазм. Свежесобранный исполнимый файл (с расширением .EXE, если Вы еще не верите в это) нужно поместить туда же, где обретаются все прочие исполнимые файлы от IDA Pro. Файл кстати называется, как Вы уже наверное могли догадаться, RPIda. Запускать так же как обычно Вы запускаете idaw, новые файлы создавать пока не умеет, зато с ранее дизассемблированными работает как часы. В общем, мечты идиотов иногда сбываются...



Заshitа


Проанализировав логи моей faked IDA.WLL я пришел к выводу, что многие из сказок, которыми нас пугал в детстве наш французский товарисчь tsehp, не соответствуют действительности. В частности, мои распакованные версии IDAW.EXE (консольная версия пользовательского интерфейса, написанная на TurboVision for Win32), PC.W32 (дизассемблер x86 процессора), IDA.WLL (собственно дизассемблер engine) и PE.LDW (загрузчик файлов в PE формате) не проверяются свою целостность, и вообще чью бы то ни было целостность (что собственно и позволило использовать технику с подменой DLL - даже оригинальные запакованные версии работали с моей faked IDA.WLL без всяких угрызений совести). По крайней мере за довольно продолжительное время работы распакованными версиями никаких видимых недокументрированных изменений с генерируемыми файлами замечено за три недели не было. Итак, по моему необоснованному мнению пока обнаружены только следующие элементы защиты (естественно недокументированные в файлах заголовков из IDA SDK - я описал их в собственном файле заголовков undoc.hpp):

экспортируемая таки из ida.wll переменная int isregd. Время от времени ее значение проверяется кое-где (ну, Вы понимаете в общем, что я хотел сказать :-). Чтобы программа считала себя зарегистрированной, ее значение должно равняться 1.

Экспортируемая опять таки из ida.wll функция

char *Registration(char *);

Она вызывается почти сразу же после вызова init_database (см. описание этой функции в файле заголовков kernwin.hpp), аргументом ей нужно передавать кусок памяти размером байт примерно 0x400. Функция вернет информацию о Вашей лицензии, прочтя при этом файл ida.key и установив соответствующим образом вышеупомянутую переменную isregd.

Собственно больше ничего работающего с файлом ida.key или портящего файлы выявлено не было. Я не могу гарантировать, что такой код действительно отсутствует - мне неинтересно заниматься защитой данного программного продукта. Если Вам захочется стать героем (и получить посмертно орден Сутулова за службу Отечеству третьей степени) и Вы решите сделать полностью чистую версию IDA Pro, советую внимательно изучить функцию Registration. Я почему-то верю, что в ней достаточно установить значение isregd в 1 и вернуть строку вида

Red Plait (1-user license 3/2001)

Впрочем, все эти досужие вымыслы нуждаются в проверке суровой действительностью...



Жалобы и предложения


можно отправлять автору по адресу redplait@usa.net. На глупые вопросы типа "А где же мне всё-таки достать IDA Pro" или "А что это такое" я не отвечаю. Если же Вы нашли bug, имеете конструктивные идеи или уверены в моей неправоте - всегда открыт к общению. Также большая просьба - не присылайте мне десятимегабайтных (притом несжатых) файлов в качестве доказательства чего бы то ни было.

Кроме того, автор не несёт ответственности за последствия работы его программ... Ну и если Вам нужно написать загрузчик, plugin или процессорный модуль для IDA Pro - можете смело обращаться к автору сего...

#include <std_disclaim.h>



ВИРУСЫ В СКРИПТАХ IDA


По мотивам "Рогов и Копыт", но с примерами вирусов для IDA PRO


Первый пик массовой вирусной эпидемии пришелся на некогда популярный компьютер "Эппл". Наиболее излюбленным объектом атаки в то время оказался загрузочный сектор гибких магнитных дисков.
Очень скоро появилось множество простых утилит, которые проверяли целостность содержимого загрузочного сектора при его запуске, а так же резидентов, которые просто блокировали запись в оный до подтверждения пользователя.
Впрочем, с массовым внедрением емких жестких дисков эта проблема и вовсе перестала существовать. Но зато появилась другая. Один винчестер (уже не защищенный от записи) хранил все исполняемые файлы пользователя и зловредной программе ничего не стоило модифицировать (то есть инфицировать) их по своему желанию.
Наиболее очевидным выходом из сложившейся ситуации стало использование операционных систем с разграничением доступа, периодическая проверка CRC исполняемых файлов, а так же создание резидентных программ блокирующим запись.
Но исполняемые файлы в отличие от загрузочного сектора, могут активно модифицироваться не только вирусом. Практически ни один ревизор не может работать на компьютере программистов. То есть людей постоянно изменяющих множество исполняемых файлов Впрочем, программисты по судьбе своей мученики и их мольбам долго никто не внимал.
Сегодня наибольшее распространение получили макро-вирусы. Это укоренившиеся, хотя неправильное название. На самом деле стоило бы их назвать скрит-вирусами, поскольку они написаны и функционируют на встроенном языке некоторого программного продукта (скрипте).
CorelDraw, PhotoShop, Quake II, Unreal вот далеко не полный перечень пакетов, поддерживающих развитые интерпретируемые (реже компилируемые) языки. Все они обеспечивают возможность функционирования и размножения вирусных и вредоносных программ (закладок и троянцев)
Вот тут-то антивирусная индустрия получила хороший щелчок. Она оказалась совсем не готова к такому развитию событий. Все средства предупреждения заболевания оказались бессильны. Ведь документ, создаваемый приложением, от записи и модификации не запретишь. То есть запретить-то, конечно, можно, и технически реализовать элементарно, но только любой пользователь отключит такую защиту - документ на то и документ, что бы с ним работать, а не смотреть "только на чтение".
По той же причине все эти вирусы отлично функционируют и на NT и даже на UNIX и Макинтош, поскольку операционной системой для них оказывается само приложение, обрабатывающие скрипты.
Любопытно, что вирусы для Quake и Unreal не детектируются абсолютно ничем. Ни AVP, ни DrWeb о них ничего не знают. Впрочем, это простительно для разработчиков. Сегодня практически каждый уважающий себя программный пакет поддерживает скриты или макрокоманды. Даже при желании уследить за всеми происходящими событиями невозможно. Совсем недавно, буквально в июле этого года появились первые вирусы и троянские дополнения к профессиональному дизассемблеру IDA PRO. В этом не было бы ничего удивительного, если бы средства языка обеспечивали бы поиск файлов для возможного инфицирования. Таковых функций IDA PRO не поддерживала, а значит, и существование вирусов (в традиционном понимании этого слова) было в ней невозможным.
Поэтому заявления, что оные все же обнаружены, встретили большой скепсис среди разработчиков антивирусного программного обеспечения. На сегодняшний день эти вирусы не детектируются ничем. Между тем, большинство пиратских копий заражено и любители нелицензионного программного обеспечения подвергают себя опасности.
На самом деле все вирусы подобного типа очень легко обнаруживаются простым визуальным просмотром скрипта. Достаточно дать себе немного труда проанализировать алгоритм работы последнего, ну и конечно, иметь представление на что обращать внимание в первую очередь.
Прежде всего все вирусы подобного типа можно разделить на две большие категории. Первые манипулируют только документами приложения и остаются исключительно в рамках виртуальной машины интерпретатора скрипта. Вторя же категория может выполнять команды процессора и операционной системы, а значит, не только инфицировать или уничтожать исполняемые файлы, но даже "покрошить" Ваш жесткий диск!
Последние опаснее, а, значит, интереснее. Вот с их рассмотрения мы и начнем. Самый простой способ вырваться из застенок виртуальной машины это воспользоваться файловым вводом \ выводом. Допустим, можно записать любую пришедшую нам на ум команду MS-DOS в файл C:\Windows\winstart.bat (ну или autoexec.bat) будучи уверенным, что рано или поздно он будет исполнен.
На языке IDA-Си это может выглядеть так.


auto a; a=fopen("C:\\WINDOWS\\winstart.bat","wb"); writestr(a,"@ECHO Hello, Hard Disk \n"); fclose(a);

подобные файловые операции поддерживают большинство языков. Обычно, впрочем, они не используются программистами, поэтому их наличие в скрипте - повод для тщательного изучения его алгоритма (благо большинство скриптов передаются в исходных текстах)
Впрочем, некоторые интерпретаторы лишены из соображений политики безопасности низкоуровневых операций с файлами. Но это разве преграда? Создаем документ с искомой строкой и выполняем команду "сохранить как_" Поскольку все приложения позволяют задавать расширения сохраняемых документов по желанию пользователя (или скрипта) то такая схема оказывается очень живучей.

Вслед за этими появились вирусы, которые использовали низкоуровневые файловые операции для модификации исполняемых файлов. Действительно, что стоит загрузить жертву в память, инфицировать любым возможным алгоритмом и записать вновь на диск?
Таким образом вирус вырвется за пределы виртуальной машины и начтет гулять по диску. Конечно, это окажется нежизнеспособно на Windows NT, при условии правильного подхода к разграничению доступа к ресурсам, но для многих пользователей станет неожиданным сюрпризом, ведь большинство из них полагает, что макро-вирусы существуют только в Ворде и диск отформатировать вряд ли смогут. А отсюда и беспечность.
Беспечность необъяснимая и неоправданная. Ведь большинство интерпретаторов поддерживают команду "Exec" для запуска внешних приложений из скрипта. Злоумышленники могут вызвать 'format.com' поэтому не помешает его запрятать подальше или даже вообще исключить с дисков всех пользователей, через чьи руки проходят сомнительные скрипты и документы.
Необходимо отметить, что реализация exec часто сводится к вызову win32 API функции CreateProcess, другими словами расширение файла не играет никакой роли. MyDocument.doc вполне может быть запущен, не смотря на "неисполняемое" расширение. Следовательно, вирус может создавать внешне легальный файл документа, чем и маскировать свое присутствие.
Впрочем, все эти "махинации" могут быть обнаружены простым сканированием скрипта на предмет ключевых слов "exec, fopen" и других. Поэтому следующим этапом эволюции было создание шифируюшихся вирусов. На первый взгляд это нереально. Как может расшифровываться интерпретируемый скрипт если он совершенно не имеет представления о физической памяти, в которую он загружен.




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

auto a,b,c,d; a="ida."; b=0xCA; c=b/2; b=b>>1; d=b + (b>>5) | (1a=a+c+d+b; Message("%s \n",a);

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

Однако, ключевые команды типа "exec" оставались в открытом виде и обнаруживались тривиальным сканированием файла. Поэтому вирусописатели предприняли попытку скрыть их от посторонних глаз. IDA PRO, как и большинство других интерпретаторов имела возможность загрузки скриптов с диска. Это дало возможность создать временный файл, в который записать расшифрованное тело вируса, и затем передать ему управление.
Что бы Вы думали делает приведенная ниже программа?

static main() { auto a,b,temp,s0; b=0; s0="0x040x030x160x030x1E0x140x570x1A0x160x1E0x19 0x5F0x5E0x570x0C0x3A0x120x040x040x160x100x12 0x5F0x550x3F0x120x1B0x1B0x180x5B0x570x3e0x33 0x360x560x570x2B0x190x550x5E0x4C0x0A0x7A0x7D 0x00\n";

a=fopen("temp.idc","wb"); while(1) { temp=substr(s0,b,b+4); b=b+4; temp=xtol(temp); if (temp==0) break; temp=temp ^ 0x77; fputc(temp,a); } fclose(b); Compile("temp.idc"); }

Да, действительно, она иллюстрирует классический пример шифрованных вирусов. Для упрощения данный пример использует "вирусоопасный" вызов "fopen", но нетрудно оформить его как сохранение документа или генерацию отчета.
Вызов "Compile" к сожалению не может считаться характерным для вирусов, поскольку он очень часто употребляется мирными программами для подзагрузки своих модулей. Ведь редко кто пишет сколь ни будь серьезные скрипты в одном файле. Поэтому в целом такие вирусы выглядят на внешний вид безвинно.
Сейчас в Сети много таких дополнений к IDA, даже появились классические "Универсальный Кракер" и "Кракер Интернета PRO". Впрочем, последний это все же действительно предоставляет бесплатный доступ в Интернет, а не форматирует жесткий диск. Он дозванивается до провайдера по указанному номеру, активно мигая лампочками модема, после чего сообщает, что якобы утащен зашифрованный файл паролей и в подтверждение этого выплевывает нечитабельный текст на экран. Далее сообщается, что расшифровать это может автор скрипта, всего за 1$, а до 1 сентября в рамках рекламной компании и вовсе бесплатно - достаточно только отослать ему это по следующему адресу. И пользователь сам того не подозревая, отправляет не зашифрованный файл паролей провайдера, а свой логин и пароль, "поксоренный" и дополненный мусором, что бы не бросаться в глаза.
Попадаются даже творения выполненные по "стелс" технологии. Вирус перехватывает событие "OnOpen" и "OnLoad" и вручную загружает файл таким образом, что бы он выглядел в незараженном виде. Поэтому просматривать скрпты на предмет поиска вирусов можно только средствами, гарантирующими достоверность отображения и невозможность внедрения постороннего кода.
Обычно это "блокнот" или другой простейший редактор. Это справедливо для IDA PRO, но часто оказывается невозможным для тех приложений, которые скрипты хранят в собственном формате вместе с документом. В таком случае просмотр внешними средствами оказывается невозможным.
Вслед за "стелс" были написаны и полиморфные вирусы. Для IDA PRO на сегодняшний момент известно два из них и оба функционируют по одному и тому же принципу. Это обычный шифрованный вирус с множеством расшифровщиков. Причем сам алгоритм генерируется "налету". Они в настоящий момент не определяются ни одним антивирусом. Впрочем, к чести их авторов к скриптам приложен подробный файл описания, что эта программа делает и перед каждым заражением запрашивается подтверждение пользователя. Но что стоит, удалив всего одну строку, получить "полноценный" современный вирус, которым потом можно заразить множество ничего не подозревающих пользователей, недоумевающих почему разработчики антивирусного обеспечения будучи информированными об этой проблеме продолжают ее спокойно игнорировать, вероятно, полагая, что IDA PRO не настолько распространенный продукт, что бы тратить человеко-часы на анализ и включение в базу этих "насекомых"?
Между тем 8 из 10 известных мне источников IDA PRO заражены теми или иными вирусами. Кстати, никак не проявляющими себя, но написанными достаточно некорректно, что бы приводить к нестабильной работе, сбоям и зависаниям дизассемблера. Не так редки вирусы и под "Visual Studio", попадающие на компакт-диски, но это уже другая история.
Их проявления и возможности ничем не ограничены, ведь как было показано выше, практически из любой виртуальной машины можно вырваться и передать управление процессора на свой код.
Однако, прием создать файл, а затем его запустить все же несерьезен и на системах с правильно организованной системой разграничения доступа просто не работоспособен. Существуют ли другие пути? Да, существуют. Многие интерпретаторы имеют "лазейки" - недокументированные функции, позволяющие делать то, что мягко выражаясь ни в коем случае не положено.
Например, IDA PRO имеет функции _peek и _poke, читающие и записывающие физическую память компьютера. Следовательно, можно передать управление на свой код! Однако, для этого его сперва нужно скопировать в память, и не на первое попавшиеся место, а обязательно в свободный регион, иначе система рискует повиснуть вместе с вирусом, что будет сигнализировать о ненормальности ситуации (стоит ли говорить, что большинство опытных пользователей присутствие вирусов на своем компьютере замечает именно по конфликтам).
В MS-DOS свободному региону соответствует нулевое значение хозяина блока в заголовке MCB. Но что бы проскандировать всю цепочку необходимо узнать адрес первого блока. Но кто его скажет вирусу? Однако, существуют способы узнать это самостоятельно и ниже будет показан один из них.
Но как теперь передать управление процессору на наш код? Это головоломная на первый взгляд задача имеет множество решений и одно из них заключается в модификации обработчика клавиатурного прерывания (мы ведь можем писать в память!) таким образом, что бы он указывал на наш код. Рано или поздно пользователь нажмет на клавишу и вирус получит управление.



static MyGetByte(a) { return (_peek(a) & 0xFF); }

static MyGetWord(a) { return MyGetByte(a)+(MyGetByte(a+1)*0x100); }

static GetNextMCB(a) { a=a+ (MyGetWord(a+3) return a; }

static GoToMCB(a) { if (_peek(a)!='M') return 0; while(1) { a=GetNextMCB(a); if (_peek(a)=='Z') return 1; if (_peek(a)!='M') return 0; } }

static FindFirstMCB() { auto a; a=0x0; while(1) if (GoToMCB(++a)) break; return a; }

static FindFreeMCB() { auto a; a=FindFirstMCB(); while(MyGetWord(a+1)) { a=GetNextMCB(a); if (MyGetByte(a)=='Z') return 0; } return a; }

static SaveInt0x16(a) { auto temp; for (temp=0;temp_poke(a+temp,MyGetByte(0x16*4+temp)); }

static SetNewInt0x16(a) { _poke(0x16*4,a); a=a>>4; a=a & 0xFFF0; _poke(0x16*4+1,0);

_poke(0x16*4+2,a); a=a>>8; _poke(0x16*4+3,a); }

static CopyEject(a) { _poke(a,0xCF); }

static SetOldInt0x16(a) { auto temp; for (temp=0;temp_poke(0x16*4+temp,MyGetByte(a+temp)); }

static main() { auto a; a=FindFreeMCB(); if (!a) return; Message(" Найден свободный блок по адресу %x \n",a); if (!AskYN("NO","Сейчас будет инфицирован Ваш компутер \n Вы в самом деле хотите это сделать? Подтвердите!"))return; if (!AskYN("NO","Подтвердите необходимость инфицирования еще раз!")) return; SaveInt0x16(a); CopyEject(a+4); SetNewInt0x16(a+4); AskYN("X","Поздравляем Вас с успешной активацией вируса!"); SetOldInt0x16(a); }

Схематичный пример показан выше. Тело вируса в нем отсутствует, и весь смысл сводится лишь к тому, что бы передать управление процессора на команду возврата из программы 'ret'. Работать это будет исключительно в среде чистой MS-DOS (консольный режим win32 за таковой не считается) и поэтому представляет не более чем познавательный интерес.
Но существуют экземпляры, которые функционируют и в казалось бы защищенной Windows NT. Да, выйти за пределы третьего кольца защиты там невозможно (ну будем считать, что невозможно) ввиду архитектуры самой системы, но вирусу для многих действий и третьего кольца хватит с лихвой.
В IDA функции _peek и _poke недокументированны, но тем не менее присутствуют и являются ключевой частью ядра для собственных нужд дизассемблера. Можно ли гарантировать, что подобных "лазеек" нет в других пакетах?
Разумеется нет! История не однократно убеждала в том, что незакрытые люки и отладочные функции явление привычное. К тому же большинство из них обнаруживаются элементарным образом. Например, если посмотреть какие функции экспортирует IDA.WLL, то среди них обнаружится не только _peek и _poke, но и даже _call! Таким образом обеспечивая всю необходимую злоумышленнику низкоуровневую работу.
Перейдем теперь ко второй группе - существующей только в рамках одного приложения. За кажущейся внешней безопасностью такие вирусы могут нанести даже более существенный урон, ибо порча исполняемых файлов всегда может быть ликвидирована переустановкой программного обеспечения с дистрибьютивных дисков, то искажение документов пользователя часто оказывается необратимым.




Рассмотрим типичную ситуацию - пишет человек книгу, которую периодически резервирует на внешний носитель (дискету, скажем). При этом, разумеется, новая копия затирает предыдущую. Если в этот момент целостность сохраняемого документа была нарушена то восстановление окажется невозможным (ведь оригинал затерт). Что стоит вирусу в огромном документе стереть несколько фрагментов или исказить их? Маловероятно, что пользователь на это сразу обратит внимание. А когда обратит, то скорее всего будет уже поздно и потребуется тщательно перечитать весь текст, проводя утомительную работу по его восстановлению. То же можно отнести и к электронным таблицам, например. Или текстам программ (на платформах Visual Studio, IDA и т.д.)
Проблема в невозможности отличить действия пользователя от действий вируса. Макрос оболочки FAR, удаляющий все файлы без подтверждения будет работать и защищенных операционных системах, наследуя права пользователя, и в отличие от "обычных" вирусов он не вызовет подозрений при установке. Да и антивирусы его не заметят. Ну никто не собирается поддерживать все программные пакеты, включая такие незначительные как FAR.
Итак, макрокоманды. Записанные последовательности нажатий или сочетаний клавиш, которые могут впоследствии выполняться автоматически. Это настолько удобно, что сегодня поддерживается практически всеми пакетами. Отказываться от этой возможности бессмысленно, но необходимо по крайней мере обеспечить такой уровень безопасности, что бы вирус не мог создавать и назначать горячие клавиши макросам самостоятельно.
К сожалению в жизни макросы настолько тесно связаны с интегрируемым языком, что последний называют макроязыком, чаще чем скриптами. Вирусу ничего не стоит, скажем, на клавишу Insert "подцепить" последовательность в стиле "Выделить все", "удалить", "записать". После чего пользователю остается только рвать на себе волосы.
В IDA нет подобных функций и никакого программного управления макросами там нет. Все они должны быть непосредственно заданы в файле idatui.cfg или введены с клавиатуры. Однако, это ограничение для вирусов "прозрачно". Они открывают нужный файл, записывают в него вредоносный макрос и_
Другие пакеты имеют схожие проблемы с безопасностью. Некоторые из них, как например FAR, хранят макросы в реестре. Вирус может либо импортировать новую запись в реестр, либо воспользоваться функциями API для его модификации. И то и то современные приложения обычно предоставляют скриптам в свое распоряжение.
Кроме того, существует такое понятие, как эмуляция ввода. Для этого достаточно послать окну соответствующую серию сообщений. Причем никто не запрещает выходить за пределы родительского окна и посылать сообщения любому на свой выбор. Для этого достаточно воспользоваться функцией Win32 API FindWindow.
Чаще всего предметом атак становиться эксплодер или проводник Windows. Вирус может использовать его для размножения и внедрения в другие объекты, а так же для всевозможных "шуток" типа трясущихся или "убегающих от курсора" окон.
Заявление, что такое возможно из языка IDA вызвало большой скепсис среди разработчиков антивирусов. Действительно, ее язык не поддерживает функции win32 API и никак не представляет такой возможности. На само же деле это возможно. Возможно благодаря функции _CALL, которая передает управление по указанному физическому адресу. Впрочем, задача вычисления адресов требуемых функций, и передача параметров (call никаких параметров не принимает и не возвращает) достаточно нетривиальна и интересна сама по себе. Не вникая в подробности технической реализации, оптимальное решение заключается в поиске свободного фрагмента памяти (а под win32 это уже весьма нетривиальная задача и для ее решения необходимо быть осведомленным во многих тонкостях организации памяти) и копировании в него простейшего менеджера, обеспечивающего обмен параметрами и вычисления необходимого адреса процедуры. Разумеется, что ничего не остается, кроме как воспользоваться GetProcAddress. Весь фокус в том "волшебном" способе получения адреса этой функции. Зная его ничего не стоит вызывать из IDA все богатство функций win32 API. В этом случае возможности вируса будут ограничиваться лишь злобностью или фантазией злоумышленника.
Все описанные выше вирусы можно назвать неризедентыми, поскольку они активны только в момент запуска макроса или скрипта. Однако, существуют и такие, что остаются в течении всего сеанса работы.
Что бы получать управление вирусу приходится перехватывать одно из многочисленных событий, таких, например, открытие файла или документа, начало и завершения сеанса работы. По аналогии с древними "досовскими" вирусами это можно назвать перехватом прерываний. Хотя в данном случае рассматриваются уже не прерывания, но с точки зрения вируса нет существенной разницы, да и обработка их осуществляется аналогично.
Отметим, что только резидентные вирусы способны стелсироваться. Для этого они должны грузиться по возможности раньше остальных программ. В IDA файл IDA.IDC автоматически выполняется каждый раз при запуске. Очень часто он становиться объектом атаки вирусов. К счастью он состоит не многим более десятка строк и любые посторонние включения нетрудно заметить. Впрочем, это не характерно для других приложений. Часто число строк в стартовых файлах (то есть файлах инициализации) очень велико и их нельзя отключить без ущерба для работы системы. Чем больше файл, тем легче затеряться в нем вирусу. Особенно, если приложение не озабоченно проверкой целостности своего хозяйства.
Стоить отдать должное тем разработчикам, которые из соображений политики безопасности хотя бы предоставляют возможность отключения обработки макросов, скриптов и событий. Word на самом деле не относиться к их числу. Генерация событий не отключается. Блокируется лишь выполнение макросов. При этом существует достаточно много способов перехватить управление на себя (ведь события все продолжают генерироваться и обрабатываться!) То что пока нет известных вирусов, реализующих такие идеи, еще не повод беспечно считать, что их не будет в и дальнейшем.
Впрочем, разработчикам антивирусов вероятно это известно, более того даже имеют готовые модули для интеграции в свой продукт, но не делают этого. Почему? Не хотят вирусописателям дарить лишние идеи. Ждут пока те до этого додумаются сами. Это по официальным данным.
А по неофициальным - просто дают понять значимость новых версий и необходимость технической поддержки. Какая разница догадаются вирусописатели до новой идеи сегодня или через день. А вот пользователь страдает. Его любимый антивирус не защищает от новых насекомых, а ведь мог бы_.
В этот отношении IDA аналогична. Файл 'OnLoad.idc' выполняется при любой загрузке анализируемых файлов в дизассемблер. Следовательно, вирус может это перехватить и представить файл как незараженный.
Такие вирусы действительно существуют. Они поражают PE файлы windows и отличаются от "обычных" только тем, что так модифицируют 'OnLoad.idc', что с IDA неправильно дизассемблирует зараженные файлы, следовательно и результаты анализа окажутся неверны. Конечно, трудно поверить, что разработчики и исследователи вирусов могу допустить такое на своем компьютере. Но где гарантия что беспечность не сыграет своей злой роли, так что на это просто не обратят внимание? Тем более, что IDA широко используется для анализа вирусов и противодействие ей это достаточно эффективный способ затруднить анализ.
Отсюда же возможно внедрение вируса во все дизассемблируемые файлы. Дело в том, что IDA лишь однократно загружает файл в свою базу, а потом к нему уже никогда не обращается. Неплохая мысль после окончания загрузки его инфицировать. Если до этого момента файл был здоров, что и подтвердит дизассемблирование, то никто не поинтересуется дальнейшей судьбой этого файла.
Такое случилось в одной организации, когда уважаемая фирма подрядилось провести в оной тщательный поиск вирусов и закладок. Юный хакер в это время сумел добраться по локальной сети организации и модифицировать файл 'OnLoad.idc' (а поиск "насекомых" проводился, разумеется, с помощью IDA). В результате ни одна закладка обнаружена не была, да еще и оказались добавлены новые.
Нельзя назвать мастером того, кто досконально не знает своего инструмента. Его сильных и слабых сторон. К сожалению, сегодня программные пакеты настолько сложны и велики, что просто не реально полностью изучить их до появления новой кардинально переработанной версии.
Следовательно, даже специалисты не застрахованы от атак злоумышленников. И это случается на порядок чаще, чем того можно было предполагать. Ведь не все "специалисты" профессионалы. Это такие же люди с присущими им слабостями и беспечностью.
Только беспечностью объясняться вера в непогрешимость IDA. На самом же деле она, как и любой другой программный пакет может быть заражена вирусами без ведома пользователя. И если разработчики антивирусного обеспечения не изменят своего отношения к ситуации в ближайшем времени, то вирусописатели могут склониться в сторону вирусов-скриптов для узкоспециализированных продуктов.




В этом случае нарушиться оперативность пополнения антивирусных баз и эпидемия рискует охватить большое число пользователей и принести огромный убыток множеству фирм. Ведь наработки профессионала стоят значительно дороже, чем множество игрушек на компьютере "общего назначения".
К тому же если программы сегодня практически уже не копируют друг у друга, а приобретают лицензионный диск (без шуток - мы говорим о высокооплачиваемых профессионалах!) или идут непосредственно на сайт разработчика, то документы все интенсивно копируют друг и друга!
И этому воспрепятствовать никак нельзя! Сейчас стандартом для распространения документов стал формат Word, электронных таблиц - Exel_ неудивительно, что распространение макровирусов приняло характер эпидемии.
Выходом является передача данных в "чистом" виде без макросов и любых автоматически исполняемых модулей. Например, Word поддерживает RTF формат, в котором распространение вирусов невозможно.
Однако, необходимо убедиться, что это именно RTF, поскольку активный вирус может перехватить управление и сохранить файл как документ ворд с макросами, но с расширением 'rft'. Word проигнорирует несоответствие расширения с внутренним содержанием и вирус продолжит свое существование.
Но это не решает проблемы в том случае, когда требуется передача именно макросов или даже сложных программ на из основе. Например, для Exel существует много бизнес-программ, состоящих из тысяч строк кода. Затеряться в них вирусу не составит никаких трудностей. Причем, если исполняемые файлы инфицируются всего несколькими путями, то в макро-программы вирусы внедряются в любую точку кода или процедуры. Поэтому написание эвристических анализаторов представляет неразрешимую на сегодня проблему.
Браузеры так же поддерживают скриты Бацика и Java, не считая остальных команд появившихся в результате интеграции с операционной системой. Для них могут использоваться многие приведенные выше приемы прорыва за пределы виртуальной машины. И ведь Интернет и HTML вирусы уже существуют не первый день и наблюдают активное пополнение в своем полку.
Антивирусные средства не могут быть эффективными против них. Можно охватить одно-два-три распространенных приложения, но сколько при этом останутся за кадром, где вирусы смогут бесконтрольно плодится и делать все что им вздумается?
Решение проблемы заключается не в совершенствовании антивирусов, а в усилении безопасности со стороны разработчиков программных пакетов. Прежде всего необходимо раздельно сохранять макросы и содержимое документов. Причем макросы должны записываться в обычный текстовой файл, изучить которой можно средствами гарантирующими неискаженное отображение содержимого. Виртуальность интерпретаторов необходимо усилить и в первую очередь вирутализировать файловый ввод \ вывод или вообще отказаться от него перейдя к концепции синхронных и асинхронных потоков. Очень заманчиво воспользоваться появившимся в Windows 95 пространством имен. Суть его заключается в том, что приложения оперируют не с физическими файлами, а с объектами OLE. Грубо говоря можно сделать так, что при перезаписи файла потребуется разрешение от самого файла!
Но даже такие меры не позволят полностью искоренить вирусы, а только затормозить их развитие и немного обезопасить пользователя. Как бы ни совершенствовались системы защиты, всегда найдутся способы их обойти. Даже в тех случаях, когда это будет невозможно. Существуют же "психологические" вирусы. Да, на полном серьезен без шуток. Такие вирусы есть. Правда летальных исходов не было, но кто гарантирует, что для некоторых людей со слабым сердцем вирус окажется безвреден?
Разумеется, речь идет о так называемых "письмах" счастья и прочей подобной чепухе, посящей разослать себя по многочисленным адресами. И ведь рассылают. И не только рассылают! Еще форматируют жесткие диски и хватаются за сердце при сообщении "все ваши файлы заражены".
Злоумышленники часто пишут от чужого имени и предлагают выполнить команды в стиле "deltree" для удаления вируса с диска. Защититься от них практически невозможно. В IDA некоторые "насекомые" распространяются через человека, то есть сообщают какие операции стоит ему выполнить, что бы скрип заработал. Разумеется, что в ряде случаев эти требования выполняются даже высокопрофессиональными специалистами!
Что же тогда говорить о простых пользователях? В одной электронной библиотеке долгое время лежат файл в формате Word, при загрузке которого появлялось сообщение, что для его чтения нужно использовать другую версию программы или сделать такие то действия. Как нетрудно догадаться, если пользователь не был сильно продвинут в компьютерах, то скоро вирус оказывался на его жестком диске, вопреки всем системам безопасности. Вирус же сам просил пользователя совершить завуалированную последовательность действий, приводящую к их отключению.
А потому, разработчики антивирусов в равной мере должны защищаться как от вирусов, так и от самих пользователей. Впрочем, от последних даже сильнее. Необходимо по крайней мере использовать не отключаемую защиту и ни в коем случае не доверять пользователю полного контроля над системой.
Массовая компьютеризация привела к тому, что большинство пользователей не обладают даже минимальными познаниями своей вычислительной техники, да и администраторы частенько то же. До тех пор пока не повыситься уровень компьютерной грамотности ситуация не изменится к лучшему.
Вся беда заключается в том, что сложность программного обеспечения с каждым днем все растет, а вместе с ней и время необходимое для полного изучения. Если с интерфейсом кое-как методом проб и ошибок все же разбираются, то возможности интегрированных языков часто остаются "за кадром".
Известный редактор Мульти-Едит написан полностью на собственном языке и его возможности поистине безграничны. При этом редко кто хотя бы в общих чертах представляет себе, что это такое и какая опасность может грозить.
А плагины? Идея возможности наращивания функциональных возможностей приложения за счет подключения внешних модулей завоевала сердца всех разработчиков. Последние версии IDA так же поддерживают ее.
Парадоксально, что мало кто задумывается, что раз плагины содержат "голый" исполняемый код, то вирусы могут великолепно избирать их объектами для атаки. Или любой плагин может содержат закладку или троянский компонент.
Но вот только на вирусы их не поверяют. А впрочем, какие антивирусы это поддерживают? Десятки ни с чем не совместимых форматов не вызывают энтузиазма у разработчиков. А напрасно.
Широко известны случаи распространения вирусов через дополнения к самим антивирусам! Злоумышленнику не надо даже модифицировать файл, вызывая протест со стороны мониторов и дисковых ревизоров. Достаточно только скопировать его в нужный каталог или попросить об этом пользователя.
Что будет дальше? Это зависит только от фантазии и агрессивности злоумышленника. Технически противостоять ситуации антивирусная индустрия не в силах. Так закончится ли когда-нибудь это смутное время вирусных атак и эпидемий? Ведь победило же человечество чуму, холеру_ сейчас борется со СПИДом.
Чем же сложнее победить человеческие творения? Дело в том, что СПИД он один, а человечества очень много миллиардов. Как бы он ни мутировал и не изворачивался - победить его вопрос времени.
А компьютерные вирусы пишутся не один, а многими тысячами людей и еще больше хотя их писать, но в меру своих умственных способностей не могут. Вот так и рождаются все многочисленные троянские программы, банально форматирующие диск.
Специалистов по антивирусам гораздо меньше и они просто не в силах контролировать ситуацию, разрываясь между желанием раскрутить юзера на бабки, обеспечить себя работой на будущее ну и спасти человечество от эпидемии. Покупали бы люди их продукцию если бы постоянно ни слышали леденящие душу истории об очередной распространяющейся со скоростью лесного пожара, заразе?
Пока эта ситуация не измениться вирусы продолжат свое существование. Ведь мы страдаем не от программного кода, а от агрессии человеческой. Победить вирусов, это значит победить злобу на Земле. Но наступит ли такой момент, что ближний ближнему своему не возжелает зла? Ведь компьютер (вирус то есть) это просто инструмент. Точно такой как нож, кастет, пистолет.
Бессмысленно сражаться с вирусами. Бесполезно сажать и наказывать их авторов. Агрессия только умножает агрессию. Необходимо смотреть глубже и устранять те корни, от которых и идет желание причинить другому вред. Вирусы, как выход агрессии не самых худший вариант. Компьютерный террор оставляет после себя обратимые разрушения. Ведь все уничтоженные данные всего можно восстановить (ну пусть с большими или меньшими трудозатратами), а вот когда жертвами становятся живые люди, то оживить их даже усилиями всего человечества невозможно.
Но это уже не имеет отношения к компьютерам. А что антивирусы? Они должны оберегать пользователя от ошибки или неверного шага. Только тогда называться они уже будут "антиюзеры". А что? Ведь пользователь свой главный враг. Никакой вирус не оживет, пока его не запустит человеческая рука не осведомленного в тонкостях программирования пользователя.

KPNC


Набор статей и руководств по дизассемблеру IDA

Использование языка IDC для анализа зашифрованного программного кода


Использование языка IDC для анализа зашифрованного программного кода



Этот пример показывает, как использовать IDC для дешифрации части программы, во время ее анализа. Для примера взята часть вируса Ripper.

Двоичный образ вируса загружен в IDA и с точки входа запущен автоанализ.



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



Создадим на IDC небольшую программу, имитирующую подрограмму дешифрации.

static decrypt(from, size, key) { auto i,x; // объявляем переменные for ( i=0; i < size; i=i+1 ) { x = Byte(from); // считываем байт x = (x^key); // дешифруем его PatchByte(from,x); // записываем на место from = from + 1; // следующий байт } }



Сохраним эту программу IDC в файле и нажмем F2, чтобы загрузить ее в интерпретатор IDA.



Затем нажмем shift-F2, чтобы вызвать ее с соответствующими значениями. Обратите внимание, что в качестве стартовой точки указан линейный адрес. При нажатии OK программа выполнится.



Теперь информация расшифрована





Поместим курсор на смещение 0x50 и нажмем C, чтобы указать IDA, что теперь по этому адресу расположен код.



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

~~\ Перевел Сергей Середа, 1999, Кишинев 24-71-96, /~~

~~\ e-mail: serge_sereda@hotmail.com /~~



Установка и использование IDA Pro






Дизассемблер позволяет получить ассемблерный текст программы из машинного кода (.exe или .dll модуля). Многие дизассемблеры могут определять имена вызываемых программой API-функций. IDA Pro отличается от других дизассемблеров тем, что он способен опознавать имена не только API-функций, но и функций из MFC (Microsoft Foundation Class - используется программами, написанными на Visual C++) и OWL (Object Windows Library - используется программами, написанными на Borland C++), а также стандартных функций языка Си (таких как fread(), strlen() и т.д.), включенных в код программы.

Установка программы обычно не вызывает никаких проблем. После запуска дизассемблера (файл idaw.exe) появляется окно сессии DOS. Не пугайтесь, IDA Pro - нормальное 32-разрядное приложение, просто оно консольное (работает в окне сессии DOS). Именно поэтому интерфейс IDA Pro напоминает интерфейс обычной DOS-программы.

Отметим несколько моментов, на которые Вам следует обратить внимание перед началом работы с IDA Pro:

Практически все настройки (кроме цветовой палитры) осуществляются через файл ida.cfg

В первую очередь, давайте поменяем размеры экрана программы. Установленный по умолчанию размер на разрешении 1024*768 не очень удобен, поэтому лучше заменить строку

SCREEN_MODE = 0 (по умолчанию 32 строки по 80 символов)

на

SCREEN_MODE = 0x783B (59 строк по 120 символов)- для разрешения 1024х768

это максимальный размер окна, которое умещается на экране. Если у Вас 800х600, можете ничего не менять.

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

Запомните, как выглядит окно программы при автоматическом выборе шрифта.

Из конкретных значений размера шрифта выберите тот, при котором окно примет первоначальный вид. После этого никаких проблем при закрытии программы быть не должно.

Для того чтобы не производить подобные изменения при каждом запуске программы, нужно соответствующим образом изменить свойства запускаемого файла. Но установить конкретный размер шрифта при запуске для файла idaw.exe не представляется возможным, т.к. это не DOS-программа, а Windows-приложение и не имеет подобных установок. Лично я для этих целей использую собственный командный файл (файл с расширение .bat). Он содержит только одну строку: idaw.exe В свойствах idaw.bat (так я назвал свой файл) я установил необходимый размер шрифта (для приведенных значений разрешения и размера окна это шрифт 8х12). Теперь, вместо idaw.exe я запускаю idaw.bat - никаких проблем при закрытии больше не возникает.

О приемах работы с IDA Pro Вы познакомитесь в следующих статьях на примере работы с конкретными программами, или можете обратиться к ее полному описанию, которое скоро появится в разделе Описание инструментов. Что ж, со всеми описаниями мы закончили, в следующей статье приступим к исследованию конкретной программы - WinZip 7.0 (beta).

<

Защита IDA.KEY


Если Вы поищите в Сети, то вполне вероятно сможете найти старые варианты IDA с генераторами IDA.KEY.  Не тратьте время на шифрование и дешифрование программ, Вы играете на чужом поле.  Значительно легче предоставить возможность дешифрования Вашему компьютеру, а затем посмотреть, что получилось.  Загрузите SotfICE, установите прерывание 'bpx createfileA do "d esp->4"', и подождите, пока в эту функцию не будет передан 'IDA.KEY'.  Запомните дескриптор (handle), возвращаемый в EAX.  Установите новое прерывание 'bpx readfile', дождитесь передачи этого дескриптора (в 'esp->4') в функцию, выполните 'd esp->8' и нажмите 'F12'.  В результате получите дамп содержимого использованного ключа IDA.KEY.  Теперь будьте внимательны!  Установите bpr на байт в пределах полученного блока, что приведет Вас к остановке при выполнении команды 'movsd'.  Удалите это прерывание, а вместо него установите новое в той области памяти, куда этот блок копируется.  Получите повторное прерывание на инстуркции 'movsd', при котором указанную выше процедуру нужно будет повторить.  В результате Вы окажетесь по адресу $10078231 в пределах IDA.WLL, содержащего зашифрованную информацию.  Несколько раз нажмите на 'F12' (p ret) до тех пор, пока не окажитесь по адресу $10077aa6.  В окне данных SoftICE Вы должны будете увидеть Вашу персональную информацию, расположенную в обратном порядке.  Таким образом, мы прошли через несколько процедур, которые читают ida.key, дешифруют и меняют порядок символов Вашей лицензионной информации.  Продолжим выполнение 'p ret' до тех пор, пока не дойдем до следующего участка кода:

001B:10077848  E83B020000               CALL    10077A88


001B:1007784D  85C0                     TEST    EAX,EAX  <--



001B:1007784F  7C09                     JL      1007785A <-- исправить это на 'nop'

001B:10077851  0FBE4610                 MOVSX   EAX,BYTE PTR [ESI+10]

001B:10077855  83F83D                   CMP     EAX,3D

001B:10077858  7404                     JZ      1007785E <-- исправить на 'jmp 1007785e'

001B:1007785A  33C0                     XOR     EAX,EAX

001B:1007785C  EB1F                     JMP     1007787D

001B:1007785E  6A7F                     PUSH    7F

001B:10077860  56                       PUSH    ESI

001B:10077861  53                       PUSH    EBX

001B:10077862  E84556FBFF               CALL    1002CEAC

001B:10077867  83C40C                   ADD     ESP,0C



001B:1007786A  C605B4EE091007           MOV     BYTE PTR [1009EEB4],07

001B:10077871  C7054488081001000000     MOV     DWORD PTR [10088844],00000001

001B:1007787B  8BC3                     MOV     EAX,EBX
Если теперь выполнить "d esi", то получите Вашу регистрационную информацию.  Первая задача теперь состоит в том, чтобы поместить в IDA. KEY несколько байтов FF, чтобы удалить из него Ваши персональные данные.  Вы обнаружите соответствующие байты, виденные Вами ранее после выхода из readfile api, все остальные байты - не используются.  Этот участок кода вызывается до 5 раз, пока IDA все не расшифрует.  Для того, чтобы заставить IDA работать без "правильного "ключа", необходимо сделать 3 исправления.  Они приведены ниже.
Первый участок исправлений в  IDA.WLL
.text:1006A34E         jz      short loc_0_1006A36B

.text:1006A350         mov     eax, [eax+8]

.text:1006A353         mov     edx, dword_0_1009AA62

.text:1006A359         cmp     edx, 20h

.text:1006A35C         jge     short loc_0_1006A376 <- исправить на 'jmp'

.text:1006A35E         mov     ecx, edx

.text:1006A360         mov     edx, 1

.text:1006A365         shl     edx, cl

.text:1006A367         test    edx, eax



.text:1006A369         jnz     short loc_0_1006A376

.text:1006A36B
Последний участок корректировки показан ниже:
001B:1006A340 0000              ADD     [EAX],AL

001B:1006A342 BA01000000        MOV     EDX,00000001

001B:1006A347 E800D40000        CALL    1007774C <-- этот вызов приводит к 1му листингу

001B:1006A34C 85C0              TEST    EAX,EAX

001B:1006A34E 741B              JZ      1006A36B

001B:1006A350 8B4008            MOV     EAX,[EAX+08]

001B:1006A353 8B1562AA0910      MOV     EDX,[1009AA62]

001B:1006A359 83FA20            CMP     EDX,20

001B:1006A35C 7D18              JGE     1006A376 <--исправить это на 'jmp'

001B:1006A35E 8BCA              MOV     ECX,EDX

001B:1006A360 BA01000000        MOV     EDX,00000001

001B:1006A365 D3E2              SHL     EDX,CL

001B:1006A367 85C2              TEST    EDX,EAX

001B:1006A369 750B              JNZ     1006A376

001B:1006A36B 6812770810        PUSH    10087712

001B:1006A370 E8F7CEFEFF        CALL    1005726C
Этот участок выполняется, когда IDA вызывает загрузчик, например, PE.LDW.  Эти модули используются для интерпретации типичных форматов файлов типа PE, NE, DOS и т.п...
Однако, перед Вами стоит огромная проблема, так как Вы не можете найти эти участки в IDAG.EXE.  Это совершенно естественно - ведь программа шифрована.  Дальше Вы с этим столкнетесь еще раз, в обоих случаях я буду пользоваться для исправлений различными подходами.  Первый из них был показан здесь с чисто учебными целями, и если Вы захотите им воспользоваться для удаления водяных знаков, то у Вас ничего не получится.  Почему?  Да потому, что IDAG.EXE зашифрован с помощью Вашей регистрационной информации, поэтому проще попытаться восстановить исходный файл приложения.
 

Реконструирование IDA.WLL


Чтобы откорректировать IDA.WLL, сначала необходимо получить файл в расшифрованном виде. Для этого понадобятся IceDump, ProcDump и Ваш шестнадцатеричный редактор.  Изучением этой методики мы сейчас и займемся.
Запустите IDA и дождитесь появления информационного окна.  Переключитесь на адресный контекст IDA с помощью команды 'addr idag'.  Установите контрольную точку 'bpmb 8:10001000 x', в результате чего исполнение IDA.WLL остановится на "расшифрованной" точке входа.  Просмотрите в ProcDump'е PE структуру - базовый адрес 1000000, длина ac000 (base address 1000000 length ac000).  Выйдите из IDA и запустите ее снова; пропустите первое прерывание по адресу 10001000, и позвольте программе доработать до второго прерывания в этой точке.  К данному моменту все будет уже расшифровано, и содержимое памяти может быть сброшено в файл, для чего выполните команду 'pagein d 10000000 ac000 c:\temp\ida.dmp'.

Теперь с помощью ProcDump'а нужно откорректировать PE-заголовок при следующих включенных возможностях:

recompute object size  -- (пересчитать размер)

optimize pe structure  -- (оптимизировать  структуру PE)

check header sections  -- (проверить заголовочные секции)

rebuild header  -- (восстановить заголовок)

use actual import infos  -- (использовать фактическую информацию импорта)

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



Восстановление IDA.WLL и модулей в их "почти" первоначальное состояние.


Прежде чем двигаться дальше, Вам следует хорошо понять структуру PE-файлов [например, хорошо прочитать статьи Randy Kath или Hard Wisdom, для них есть переводы на русском - прим. перев.].

IDA.WLL и все модули имеют обычную точку входа.  Воспользовавшись PE-редактором ProcDump'а, Вы обнаружите, что точка входа IDA.WLL находится по адресу $100AA000.

Установите по этому адресу контрольную точку 'bpmb' и загрузите IDA.

001B:100AA000 60                 PUSHAD           <-- Вы оказались здесь


001B:100AA001 E841060000         CALL    100AA647


001B:100AA006 EB41               JMP     100AA049


001B:100AA008 0000               ADD     [EAX],AL


001B:100AA00A E177               LOOPZ   100AA083


001B:100AA00C 0C00               OR      AL,00


001B:100AA00E 0000               ADD     [EAX],AL


001B:100AA010 0000               ADD     [EAX],AL

Перед Вами типичная процедура распаковки или дешифрования - 'PUSHAD' сохраняет содержимое всех регистров, следующим шагом выполняется расшифровка DLL, а затем окончательный переход на точку входа.  Чтобы найти ее Вы должны знать, что все DLL имеют секцию инициализации, которая и является фактической точкой входа.  Здесь происходит выделение памяти, инициализация переменных и т.п.  При этом те же самые функции осуществляют выгрузку DLL.  Поэтому выйдите из IDAG.EXE сразу после появления информационного окна, установите контрольную точку, а когда сработает 'BPMB' выполните 'p ret' (F12), и Вы окажетесь в следующем фрагменте:

001B:10001000 A1E0A10710         MOV     EAX,[1007A1E0] <--- Вы оказались здесь



001B:10001005 C1E002             SHL     EAX,02

001B:10001008 A3E4A10710         MOV     [1007A1E4],EAX

001B:1000100D 8B442408           MOV     EAX,[ESP+08]

001B:10001011 A356A20710         MOV     [1007A256],EAX

001B:10001016 FF148546A20710     CALL    [EAX*4+1007A246]

001B:1000101D 833D56A2071001     CMP     DWORD PTR [1007A256],01

001B:10001024 0F8580000000       JNZ     100010AA

001B:1000102A 803DECA1071000     CMP     BYTE PTR [1007A1EC],00

001B:10001031 7424               JZ      10001057

001B:10001033 E88A850700         CALL    KERNEL32!GetVersion

001B:10001038 BAEDA10710         MOV     EDX,1007A1ED

001B:1000103D 2500000080         AND     EAX,80000000

001B:10001042 7405               JZ      10001049

001B:10001044 BA0DA20710         MOV     EDX,1007A20D

001B:10001049 52                 PUSH    EDX
Именно этот фрагмент является фактической точкой входа в IDA.WLL, она одинакова для всех модулей, и всегда отстоит на 1000h от базового адреса.
Нам нужно целиком сбросить эту DLL из памяти на диск; сначала я попытался сделать это с помощью ProcDump'а, однако этот способ терпит неудачу, когда IDA снова загружает в память сброшенную DLL.  Почему?
Все очень просто.  Для загрузки IDA.WLL в свой адресный контекст ProcDump использует загрузочную библиотеку (огромная ошибка при сбросе защищенных DLL), затем вызывает секцию инициализации по адресу 10001000, распределяет память и сбрасывает образ памяти на диск.  Но при распределении памяти секция инициализации устанавливает некоторые флаги, которые при сбросе сохраняются.  Если IDA затем загрузит эту сброшенную DLL, то флаги уже окажутся установленными, что и выявляется системой защиты.  Основные флаги располагаются в секции данных и тестируются процедурой инициализации DLL.
Следовательно, нам необходимо сбросить DLL до начала работы процедуры инициализации.  Для этого нам понадобится IceDump.
Установим контрольную точку по адресу 1b:10001000, загрузим IDA, и дождемся ее второго срабатывания (первый раз она сработает по команде ret во время дешифровки), когда Вы вновь придете к тому же самому адресу, но в этот момент DLL окажется загруженной, память распределенной, однако флаги еще не будут установлены.
ProcDump сообщит о IDA.WLL следующее:
базовый  адрес образа - 10000000
длина - ac000
Теперь воспользуемся IceDump и выполним команду 'd 10000000 ac000 "Ваша директория, что-нибудь типа \??\temp\ida.dmp"'
Вы получите файл IDA.TMP, содержащий все расшифрованные секции, но с заголовком, который еще требуется восстановить.  Сделаем это с помощью автоматической процедуры ProcDump'а.  Также с помощью ProcDump'а измените адрес точки входа на 10001000, и все заработает.
Не забудьте исправить IDA.WLL таким образом, чтобы 'CALL 10013298' никогда не возвращал 0 в EAX.  Постарайтесь найти нужные смещения сами!  А вот что я сам сделал в IDA.WLL.
0008:10013298 83C4E8             ADD     ESP,-18



0008:1001329B 33C9               XOR     ECX,ECX

0008:1001329D 8BC4               MOV     EAX,ESP

0008:1001329F C644240424         MOV     BYTE PTR [ESP+04],24

0008:100132A4 C644240520         MOV     BYTE PTR [ESP+05],20

0008:100132A9 C644240675         MOV     BYTE PTR [ESP+06],75

0008:100132AE C644240773         MOV     BYTE PTR [ESP+07],73

0008:100132B3 C644240865         MOV     BYTE PTR [ESP+08],65

0008:100132B8 C644240972         MOV     BYTE PTR [ESP+09],72

0008:100132BD C644240A31         MOV     BYTE PTR [ESP+0A],31

0008:100132C2 C644240B00         MOV     BYTE PTR [ESP+0B],00

0008:100132C7 8D542404           LEA     EDX,[ESP+04]

0008:100132CB E878410100         CALL    10027448

0008:100132D0 8BC4               MOV     EAX,ESP

0008:100132D2 B153               MOV     CL,53

0008:100132D4 33D2               XOR     EDX,EDX

0008:100132D6 E825480100         CALL    10027B00



0008:100132DB 85C0               TEST    EAX,EAX

0008:100132DD 7504               JNZ     100132E3

0008:100132DF B001               MOV     AL,01     * измененная часть, было 'XOR eax,eax'

0008:100132E1 EB31               JMP     10013314

0008:100132E3 8B5004             MOV     EDX,[EAX+04]

0008:100132E6 81FAC030D737       CMP     EDX,37D730C0

0008:100132EC 7D04               JGE     100132F2

0008:100132EE B001               MOV     AL,01     * то же самое

0008:100132F0 EB22               JMP     10013314

0008:100132F2 8B5010             MOV     EDX,[EAX+10]

0008:100132F5 81C2C9FDFFFF       ADD     EDX,FFFFFDC9

0008:100132FB 81FA0605FFA5       CMP     EDX,A5FF0506

0008:10013301 7404               JZ      10013307

0008:10013303 B001               MOV     AL,01     * то же самое

0008:10013305 EB0D               JMP     10013314



0008:10013307 8B500C             MOV     EDX,[EAX+0C]

0008:1001330A 85D2               TEST    EDX,EDX

0008:1001330C 7404               JZ      10013312

0008:1001330E B001               MOV     AL,01     * то же самое

0008:10013310 EB02               JMP     10013314

0008:10013312 B001               MOV     AL,01

0008:10013314 83C418             ADD     ESP,18

0008:10013317 C3                 RET
Таким образом, мы получили образ IDA.WLL и заменили зашифрованный файл практически исходным ему.
Теперь Ваша IDA работает нормально, все декомпилирует без ошибок и не помещает регистрационных записей в создаваемые файлы.  Теперь же в качестве упражнения давайте восстановим в свое "почти" исходное состояние  модули *.W32 и *.LDW.  Воспользуемся для этого той же самой техникой сброса образа на диск, восстановлением заголовка и смещением адреса точки входа на +1000.
Однако, на этот раз при попытке вызова из IDA функции loadlibraryA для загрузки модуля мы получим ошибку.  Рассмотрим в качестве примера PE.LDW.  Для сравнения сброшенного образа PE.LDW с исходным файлом воспользуемся таким замечательным инструментом как PEBrowse, и он покажет нам, что секция импорта в полученном образе немного отличается от оригинала.  Почему?  Да потому, что Windows изменяет адреса API-функций в секции импорта, и эти адреса оказываются в сброшенном модуле неработоспособными.
Секция импорта оказалась поврежденной.  Чтобы найти ее местонахождение, взгляните в ProcDump.  Он показывает, что ее виртуальный адрес равен 178f4.  Чему равно смещение файла?  Взгляните на секции: виртуальное смещение (Virtual offset) секции .adata равно 17000, а полное смещение (Raw Offset) = f200.  Следовательно, смещение секции импорта равно (178f4-17000) = 8f4 + f200 = faf4.
Взгляните на таблицу импорта в ASCII-режиме шестнадцатеричного редактора.  Дальше есть 2 пути: наиболее интересный из них - все сделать самому: изучить структуру таблицы импорта и самостоятельно восстановить ее так как это сделал я.  Этот путь требует некоторых затрат труда и времени, однако, в будущем он себя окупит с лихвой.  Более простой, воспользоваться таблицей импорта из оригинального файла PE.LDW:
 

Ida.dmp



0008B2A2 0090 5401 0080 3B01 0080 E001 0080 0000 0000 4B45 524E 454C 3332 2E44 ..T...;...........KERNEL32.D


0008B2BE 4C4C 0000 0047 6574 5072 6F63 4164 6472 6573 7300 0000 4765 744D 6F64 LL...GetProcAddress...GetMod


0008B2DA 756C 6548 616E 646C 6541 0000 004C 6F61 644C 6962 7261 7279 4100 0000 uleHandleA...LoadLibraryA...


0008B2F6 0000 0000 0000 0000 0000 B4A8 0A00 A4A8 0A00 0000 0000 0000 0000 0000 ............................


0008B312 0000 30A9 0A00 3BA9 0A00 0000 0000 0000 0000 0000 0000 0000 0000 0000 ..0...;.....................


0008B32E 0000 5553 4552 3332 2E44 4C4C 0043 A90A 0000 0000 0000 0045 6E75 6D54 ..USER32.DLL.C.........EnumT


0008B34A 6872 6561 6457 696E 646F 7773 hreadWindows

Смещения немного отличаются от оригинальных, так как при сбросе файла из памяти произошло увеличение его размеров.  Теперь можно переименовать IDA.DMP в IDA.WLL и попытаться найти все 3 откорректированных  мною участка.

После этого можно удалить из IDA.KEY регистрационную информацию так, как это сделал я:
 



Ida.key



00000054 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ............................


00000070 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ............................


0000008C FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ............................


000000A8 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ............................


000000C4 FFFF FFFF FFFF FFFF FFFF                                            .........

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


 



000000F0 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ............................


0000010C FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ............................


00000128 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ............................


00000144 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF ............................

Можно удалить и другие байты, попытайтесь сделать это в качестве упражнения.

В результате, несмотря на удаление всей шифрованной регистрационной информации, IDA 4.01 тем не менее продолжает нормально работать и не показывает ее больше нигде, в том числе *.ASM и *.LST, а встроенная в IBD базы лицензия больше не воспроизводится.

ОДНАКО, осталась еще небольшая проблема. Начните декомпилировать большую программу.  Сначала все идет хорошо, но в конце работа прерывается сообщением, что "программа превысила допустимые пределы" (execution flows beyond limits) или ему подобным.  Но если вы возвратите исходный неисправленный ida.key, то все заканчивается нормально.  Что же случилось?

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

001B:10077848  E83B020000        CALL    10077A88


001B:1007784D  85C0              TEST    EAX,EAX  <-- остановимся здесь


001B:1007784F  7C09              JL      1007785A <-- исправить на 'nop'


001B:10077851  0FBE4610          MOVSX   EAX,BYTE PTR [ESI+10]

Если установить в этом фрагменте прерывание 'bpmb 1b:10077848 x' и загрузить idag.exe, то до момента окончания процедуры декомпиляции это прерывание произойдет 5 раз.  По окончании выполните команду 'd esi' и увидите в окне данных расшифрованную регистрационную информацию в виде "= имя, дата, ...мусор...".  Если теперь в памяти изменить лицензионные данные на что-либо еще, то в конце второй попытки декомпиляции возникнет та самая ошибка.

Проверка происходит именно здесь - в расшифрованном ключе.  Да, мы исправили код IDA, однако, регистрационная информация хранится в памяти и используется повторно.  Если Вы хотите все сделать самостоятельно, то запаситесь временем и терпением, эта информация копируется в памяти из области в область (около 300 раз!), прежде чем будет проверена.  Вам придется ставить контрольные точки 'bpmb' в памяти на регистрационную запись и удалять их, как только эти данные будут скопированы в новое место.  Я использовал другие хитрости, здесь не описанные, однако, если Вы терпеливы, то и этот метод прекрасно срабатывает.  В конце концов мы оказываемся в участке кода IDA.WLL, где регистрационная информация уже больше никуда не копируется и где происходит ее окончательная проверка.

0008:10013318 53                 PUSH    EBX





0008:10013319 56                 PUSH    ESI

0008:1001331A 57                 PUSH    EDI

0008:1001331B 55                 PUSH    EBP

0008:1001331C 51                 PUSH    ECX

0008:1001331D E876FFFFFF         CALL    10013298

0008:10013322 84C0               TEST    AL,AL                 <- Вы оказались здесь

0008:10013324 0F858E000000       JNZ     100133B8

0008:1001332A A1CF930910         MOV     EAX,[100993CF]

0008:1001332F E8AC080000         CALL    10013BE0

0008:10013334 33D2               XOR     EDX,EDX

0008:10013336 8AD0               MOV     DL,AL

0008:10013338 B888AA0810         MOV     EAX,1008AA88

0008:1001333D 891424             MOV     [ESP],EDX

0008:10013340 E857E1FFFF         CALL    1001149C

0008:10013345 50                 PUSH    EAX



Что можно предположить?  Если AL содержит 0, то происходит ошибка, и это случается всякий раз, когда вы удаляете из ключа регистрационную информацию.  Подпрограмма по адресу 10013298 используется и в дальнейшем, следовательно нам надо так исправить ее, чтобы она никогда не помещала 0 в регистр AL.

Чрезвычайно важно: та же самая методика будет использована для зашифрованных модулей IDA (найдите их сами).  Нам придется сделать это во всех точках, так как шифрование использует водяные знаки - я имею в виду, что везде для шифрования используется Ваша персональная информация.  Я должен поблагодарить Nolan Blender, который помог, снабдив меня CRC-кодами всех файлов его копии IDA 4.01.  Это понадобилось мне, чтобы обнаружить различающиеся файлы.  Вот их общий список:

IDAG.EXE
IDA.WLL
IDA.KEY  - куда же без него :)
все *.LDW и *.W32

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

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


Ida.wll (исходный)



0004A6A2 0090 C1A8 0A00 D2A8 0A00 E5A8 0A00 0000 0000 6B65 726E 656C 3332 2E64 ..................kernel32.d


0004A6BE 6C6C 0000 0047 6574 5072 6F63 4164 6472 6573 7300 0000 4765 744D 6F64 ll...GetProcAddress...GetMod


0004A6DA 756C 6548 616E 646C 6541 0000 004C 6F61 644C 6962 7261 7279 4100 0000 uleHandleA...LoadLibraryA...


0004A6F6 0000 0000 0000 0000 0000 B4A8 0A00 A4A8 0A00 0000 0000 0000 0000 0000 ............................


0004A712 0000 30A9 0A00 3BA9 0A00 0000 0000 0000 0000 0000 0000 0000 0000 0000 ..0...;.....................


0004A72E 0000 7573 6572 3332 2E64 6C6C 0043 A90A 0000 0000 0000 0045 6E75 6D54 ..user32.dll.C.........EnumT


0004A74A 6872 6561 6457 696E 646F 7773                                         hreadWindows

Эти значения нужно вставить в сброшенный Вами образ IDA.WLL (IDA.DMP) по следующему адресу:



Pe.ldw (исходный)



0000889C 6172 7920 2573 0090 C178 0100 D278 0100 E578 0100 0000 0000 6B65 726E ary %s...x...x...x......kern


000088B8 656C 3332 2E64 6C6C 0000 0047 6574 5072 6F63 4164 6472 6573 7300 0000 el32.dll...GetProcAddress...


000088D4 4765 744D 6F64 756C 6548 616E 646C 6541 0000 004C 6F61 644C 6962 7261 GetModuleHandleA...LoadLibra


000088F0 7279 4100 0000 0000 0000 0000 0000 0000 B478 0100 A478 0100 0000 0000 ryA..............x...x......


0000890C 0000 0000 0000 0000 4479 0100 5779 0100 0000 0000 0000 0000 0000 0000 ........Dy..Wy..............


00008928 4C79 0100 5F79 0100 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 Ly.._y......................


00008944 6964 612E 776C 6C00 7573 6572 3332 2E64 6C6C 0001 0000 8000 0000 0067 ida.wll.user32.dll.........g


00008960 7901 0000 0000 0000 0045 6E75 6D54 6872 6561 6457 696E 646F 7773 0000 y........EnumThreadWindows..

Сравните этот фрагмент со сброшенным Вами из памяти и скопируйте все байты с 889ch по 8962h из исходного файла в полученный Вами.

Теперь секция импорта восстановлена и содержит правильные адреса API-функций.

Не забудьте еще восстановить PE-заголовок, изменить точку входа и восстановить секции импорта во всех .LDW и .W32 модулях, которые Вам понадобятся.  В результате они окажутся расшифрованными, и Вы сможете ими воспользоваться для дальнейшей работы.

Затем я сравнил свой собственный файл PE.LDW с файлом, полученным от Nolan'а.  Оказалось, что в трех местах все еще остались различия: первое - это Ваша регистрационная информация, записанная в заголовке простым ASCII текстом, ее легко удалить.  Также есть еще два места.  Однако, я на этом заканчиваю и не буду объяснять, как удалить эти последние водяные знаки.  Поищите их сами, и, если Вы внимательно прочитали всю статью, это не составит для Вас труда.
 
 

Последние замечания

Если Вам все-таки удастся удалить последние водяные знаки, то не распространяйте эту "взломанную" программу.  Защита программ становится все более и более сложной, поэтому, если Вы так поступите, то рискуете не суметь в дальнейшем обновить последующие версии IDA.  Ниже приведен отрывок из полученного мною письма Pierre Vandevenne, администратора этой программы:


**/**

Re: Re: IDA 4.01 changing thoughts...

Wednesday, 09-Feb-2000 16:18:29

195.0.122.9 writes:

Здравствуйте!

По всей видимости, у нас различные взгляды на кражу, однако, я думаю, что мне все-таки стоит сказать по этому несколько слов:

Имя пользователя, создающего базу данных, в самом деле сохраняется в ней.  Для этого не требуется ни reverse engineering, ни слухов, ни чего бы то ни было еще - это имя демонстрируется в самом начале дизассемблированных кодов!

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

Что касается жадности, то мы действительно могли бы быть жадными, однако, на самом деле с IDA это не невозможно.  Судите сами:

1) Рынок сложных инструментов для исследования на сегодняшний день чрезвычайно мал.

2) Сама IDA создана на условиях полной легальности и лицензионности.  Мы платим за компиляторы, спецификации, книги, за все то, что нам нужно, и что мы можем купить.  Мы покупаем у компаний и компании покупают у нас, в результате работа выгодна обоим сторонам.  Справедливо?

3) Ильфак в настоящее время живет и работает в Бельгии, при этом мы не провозили его в заколоченном ящике, как иностранного шпиона, и не заточали его в пещере с 486 компьютером и черно-белым монитором.  Что-нибудь тоже не так?  Разве он не заслуживает достойных условий работы?

4) Мы оказываем постоянную и незамедлительную помощь нашим пользователям.

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

Pierre Vandevenne

Reversing IDA 4.01 Watermarked protection scheme


Written by Tsehp

Введение

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

Nolan Blender обнаружил, что IDA 4.01 встраивает Ваши регистрационные данные в базы .IDB точно так же, как они вставлялись в .ASM и .LST; этого можно избежать, если Вы измените IDA.KEY и IDA.WLL.  Я научился удалить все водяные знаки в IDA 4.01 и после их полного удаления описанным в данной статье методом выполнил побайтное сравнение созданных баз .IDB с аналогичными же базами, созданными моей лицензионной копией IDA, где все водяные знаки сохранены.  В результате не было обнаружено НИКАКИХ РАЗЛИЧИЙ, так что, если Вы захотите воспользоваться моими советами, Ваша частная информация может оказаться в полной безопасности.

Для выполнения этой работы Вам понадобится обычная копия IDA 4.01, которая содержит внутри себя многочисленные водяные знаки.  В данной статье я не раскрою Вам всех секретов, поэтому кое-что из них в программе все же останется.  Этот инструмент является обязательным орудием любого серьезного исследователя, и он должен развиваться авторами, а они заслуживают тех денег, которых эта программа стоит.

С чем же мы будем иметь дело?  Ваше регистрационное имя в зашифрованном виде помещается в IDA.KEY, и IDA постоянно использует его для проверки легальности выполнения тех или иных функций.  Часть секций данных всех ее *.W32 модулей зашифрованы уникальным ключом, сгенерированным специально для Вашей копии программы, это же справедливо для основной библиотеки IDA.WLL и всех загрузчиков *.LDW.  Остальная часть программы не изменяется.
 
 

Необходимые инструменты

Softice 4.01
Nt_Icedump 1.6
Procdump 1.6.2
Шестнадцатеричный редактор с возможностью побитного сравнения файлов (hex workshop)
Одна лицензионная копия IDA 4.01 (для выполнения этого исследования) или 2 лицензионные копии для проверки наличия водяных знаков.
 
 

URL/FTP исследуемой программы

<

Библиотека для ассемблера x86 IDA Pro


Разве можно жить в стране, в которой так много военкоматов ?

(C) моё

Требования

Как IDA дизассемблирует программы

Для чего именно предназначена моя библиотека

Конвертор

Обнаруженные баги

Жалобы и предложения



Для чего именно предназначена моя библиотека


Как Вы уже могли заметить по прочтении предыдущей главы, IDA Pro предоставляет множество информации по дизассемблируемой инструкции, но далеко не всю. Скажем, Вы не можете из IDA узнать, что, для примера, инструкция CPUID изменяет регистры EAX,EBX,ECX & EDX. Нам нужна ещё одна таблица с характеристиками инструкций, индексируемая по itype - именно она и есть основа моей библиотеки (файл x86data.c). Причём, в отличие от массива instruc структур processor_t (который недоступен нам для изменений в силу своей закрытости), моя таблица распространяется в исходных кодах, поэтому любой желающий может её модифицировать и добавить свойства, которые он посчитает нужным (скажем, время исполнения инструкции - и тогда из IDA Pro можно будет сделать весьма неплохой статический profiler). Прошу обратить внимание, что в настоящее время такая таблица составлена мною только для процессора x86. Чтобы сваять аналогичную для другого процессора, Вам нужно будет:

С помощью reverse engeneering выпотрошить itypes инструкций и их мнемоники из соответствующего процессорного модуля (это значительно легче, чем Вы думаете, особенно если Вы умеете писать на IDC)

Возможно, поправить конвертор inst.pl (см. его описание и предназначение ниже)

Собственно заполнить файл данных для Вашего процессора

В настоящее время для каждой инструкции определены следующие характеристики (описываемые структурой RP_opcode) :

unsigned char type

Тип инструкции. Может быть 0,FPU, MMX, AMD_3D, SSE или UNKNOWN_IT (для недокументированных инструкций).

unsigned char from_proc

Указывает на тип процессора, с которого данная инструкция опознаётся. Может быть 0 (386 или ниже), FROM_486, FROM_P, FROM_PPRO, FROM_PII - соответственно если инструкция опознаётся с 486, Pentium, Pentium Pro или Pentium II.

unsigned long regs

Битовая маска из регистров, изменяемых данной инструкции. Вычисляется как 1, сдвинутая влево на значение регистра (значения регистров см. в файле заголовков x86.h - макросы r_XX).

unsigned short cflags



Битовая маска флагов, изменяемых данной


Битовая маска флагов, изменяемых данной инструкцией. Вычисляется как 1, сдвинутая влево на значение флага (значения флагов см. в файле заголовков x86.h - макросы f_XX).

unsigned short rflags

Битовая маска флагов, от которых зависит выполнение данной инструкции (аналогично cflags).

unsigned short uflags

Битовая маска флагов, состояние которых не определено после выполнения данной инструкции (аналогично cflags).

char ops

Битовая маска операндов, изменяемых данной инструкцией. Это поле дублирует флаги CF_CHG поля feature структур instruc_t - но себе я доверяю значительно больше, чем Ильфаку :-)

Также для манипуляций с этими структурами предоставлены несколько функций (реализованы в файле x86.cpp) :

const struct RP_opcode *get_opcode(const struct insn_t *)

Функция, возвращающая структуру RP_opcode по заполненной структуре insn_t. Прошу отметить, что недостаточно простого индексирования по полю itype. В качестве примера можно рассмотреть инструкцию mul. Обычно она изменяет значение пары регистров EAX & EDX, но если операнды имеют размер 8 бит, инструкция изменяет только регистр EAX.

Также эта функция проверяет аналогичные особые случаи для инструкций div, idiv и imul.

bool is_change_reg(const struct insn_t *, struct RP_opcode *, int reg)

Проверяет, изменяет ли инструкция, описывающаяся IDA структурой insn_t, и моей структурой RP_opcode, регистр reg.

bool exists_XXX

Inline-функции, возвращающие булевское значение, если некое поле содержит значение в данном операнде.

get_SIB_XX

Inline-функции для манипуляций с SIB байтом.


Как IDA дизассемблирует программы


Чтобы понять, для чего именно предназначена моя библиотека, Вы должны очень хорошо представлять себе, как же IDA работает. Так что запаситесь терпением, пивом, поставьте что-нть приятное слуху (от себя могу порекомендовать Marylin Manson, Nine Inch Nails, Pearl Jam или Alice in Chains) - глава будет долгой...

Я встречал много людей, которые на полном серьёзе утверждали, что создание дизассемблера - тривиальное занятие. Хм, однако почему в таком случае так мало хороших дизассемблеров ? Дело в том, что под понятием "хороший дизассемблер" мы подразумеваем не только программу, генерирующую на выходе текстовый файл с ассемблерными инструкциями. Хороший ассемблер должен заниматься так же и анализом кода - чтобы отличить код от данных, распознать использование локальных переменных, начало и конец функций и ещё множество вещей, за которые мы любим IDA Pro. А как же IDA Pro может делать всё вышеперечисленное ? Весь секрет заключается в том, что в ней используется не просто дизассемблер - а ещё и эмулирующий анализатор.

Чтобы заставить IDA Pro понимать ещё один процессор (скажем, HP-PA), Вы должны написать dissassembler module - для краткости в дальнейшем будем называть его просто module. В IDA SDK есть пример такого модуля (для процессора 8051). Рассмотрим, из каких функций состоит module. Module представляет собой .DLL (для Win32), экспортирующую под именем LPH всего одну структуру processor_t. Структура эта достаточно велика - ведь она должна полностью описывать ассемблер некоторого процессора - но нас в этой структуре нас интересует всего несколько членов:

int (*u_ana) (void)

Указатель на функцию, анализирующую одну инструкцию, в результате анализа заполняется глобальная переменная cmd - структура insn_t. Адрес инструкции задаётся в поле cmd.ea. Функция возвращает длину декодированной инструкции, или 0, если инструкция не распознана.

На самом деле мы не можем вызвать эту функцию непосредственно - мы можем вызвать для анализа только следующие функции:

ida_export int ua_code(ea_t ea)


Высокоуровневая функция, анализирует байты по адресу ea, и преобразует их в код.

ida_export int ua_ana(ea_t ea)

Анализирует байты байты по адресу ea, преобразует их в код, а также производит некоторые сопутствующие действия (например, применение fixups, увеличение сегментов и т.д.)

ida_export int ua_ana0(ea_t ea)

Наша рабочая лошадка - просто анализирует байты по адресу ea, заполняя структуру cmd, при этом загруженная база данных не изменяется.

Все эти три функции возвращают длину декодированной инструкции, или 0, если инструкция не опознана. Аргумент ea - адрес (ea_t - просто ulong).

int (*u_emu) (void)

Указатель на функцию, эмулирующую выполнение инструкции. Несмотря на отсутствие аргументов, эта функция имеет доступ к ранее заполненной в результате анализа структуре cmd для эмулируемой инструкции. Именно наличием эмулятора (а также наличием встроенной в IDA виртуальной регистровой машины) и объясняются её выдающиеся способности - инструкции не просто дизассемблируются, но и частично эмулируются, что позволяет производить более глубокий анализ кода. Эта функция отвечает за создание кросс-ссылок, за включение в зону анализа ветвей исполнения (для инструкций переходов и вызова функций) и множество других вещей...

Функции генерации текстового представления (то, что мы видим на экране):

void (*u_out) (void)

Генерирует текстовое представление инструкции по ранее заполненной структуре cmd.

int (*u_outop) (op_t &op)

Генерирует текстовое представление операнда op_t инструкции. Возвращает 1 в случае успеха, и 0, если операнд скрыт.

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

instruc_t *instruc

Массив описаний инструкций (см. подробности ниже).

Структура instruc_t используется для внутреннего представления характеристик инструкции, и имеет всего два члена:

const char near *name

Строка - имя инструкции

ushort feature

Характеристики инструкции. Битовая маска, могущая состоять из следующих значений:



CF_STOP

Инструкция не передаёт исполнение следующей инструкции (например, hlt)

CF_CALL

Вызов процедуры.

CF_CHG1

Инструкция модифицирует свой первый операнд.

CF_CHG2

Инструкция модифицирует свой второй операнд.

CF_CHG3

Инструкция модифицирует свой третий операнд.

CF_USE1

Инструкция использует значение своего первого операнда.

CF_USE2

Инструкция использует значение своего второго операнда.

CF_USE3

Инструкция использует значение своего третьего операнда.

CF_JUMP

Инструкция передаёт управление.

CF_SHFT

Инструкция производит побитовый сдвиг.

CF_HLL

Инструкция может быть описана на языке высокого уровня (я не знаю, что конкретно имелось в виду за столь витиеватой формулировкой)

Структура insn_t используется для внутреннего представления инструкции, нас интересуют следующие члены:

ushort itype

Внутренний код инструкции. Значения кодов определены в каждом процессорном модуле по-разному для каждого процессора (я также сильно подозреваю, что их значения изменяются от версии к версии). Также является индексом в ранее описанном массиве инструкций instruc_t *instruc.

ea_t ea

Линейный адрес инструкции.

ushort size

Размер инструкции в байтах.

union { ushort auxpref; struct { uchar low; uchar high; } auxpref_chars; };

Процессорно-зависимое поле. Используется для x86 процессора (см. детальное описание ниже).

op_t Operands[3]

Операнды инструкции. Почему операндов именно три ? См., например, x86 инструкцию shld или shrd

Структура op_t заслуживает более пристального рассмотрения. Она состоит из следующих членов:

char n

Номер операнда - 0,1 или 2.

optype_t type

Тип операнда. Этот член определяет, какие прочие члены структуры имеют значение, и как оно интерпретируется. Насколько я понял, процессорозависим. Более детальное описание см. ниже.

char offb

Смещение значения операнда от начала инструкции. Имеет смысл не для всех типов операндов.

char offo

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



uchar flags

Некоторые характеристики операндов. Объяснение см. ниже.

char dtyp

Тип значения операнда. Наиболее распространённые типы значений:

dt_byte 0 // 8 бит dt_word 1 // 16 бит dt_dword 2 // 32 бит dt_float 3 // 4 байта dt_double 4 // 8 байт dt_qword 7 // 64 бит

Все нижеописанные члены структуры op_t хранят информацию о значении операнда (и их использование зависит от значений type & flags):

union { uchar reg; uchar phrase; };

Номер регистра. Для ассемблера x86 номера регистров определены в файле заголовков x86.h моей библиотеки - см. макросы r_XX.

union { ulong value; struct { ushort low; ushort high; } value_shorts; };

Значение непосредственного операнда.

union { ulong addr; struct { ushort low; ushort high; } addr_shorts; };

Значение виртуального адреса, используемого операндом.

union { ulong specval; struct { ushort low; ushort high; } specval_shorts; };

Содержит значение операнда, не могущее быть представленным остальными членами структуры op_t. Специфично для каждого процессорного модуля, для ассемблера x86 не используется (IMHO ?).

char specflag1; char specflag2;

Содержат дополнительную информацию об операнде.

Как же именно вышеописанные структуры могут быть использованы для анализа кода ? Я выяснил этот вопрос, не дождавшись ответа от Гильфанова. Хочу ещё раз предупредить, что всё нижеописанное касается только IDA Pro версии 3.85b (и может измениться без предупреждения в любой из следующих версий) и только процессора x86.

Итак, инструкция может иметь один из префиксов. Наличие или отсутствие префиксов определяет поле auxpref_chars.low структуры insn_t:

lock auxpref_chars.low & 0x1 == 0x1

rep/repe auxpref_chars.low & 0xE == 0xA

repne auxpref_chars.low & 0xE == 0xC

Количество операндов можно определить так: последний из них должен иметь type

o_void (но не больше трёх).

Значение операнда определяется его полем type:

o_void

Операнд не имеет значение. Признак отсутствия операнда и всех последующих операндов.



o_reg

Операнд является регистром, поле reg содержит номер регистра. Значения регистров см. в моём файле заголовков x86.h.

o_mem

Операнд является прямой ссылкой на данные в памяти. Сегментный регистр содержится в поле specval_shorts.high, поле addr содержит адрес.

o_phrase

Операнд представляет собой ссылку типа [базовый регистр + индексный регистр]. Сегментный регистр содержится в поле specval_shorts.high. Все значения операнда хранятся в SIB байте - поле specflag2.

Значение базового регистра определяется как specflag2 & 0x7

Значение индексного регистра определяется как (specflag2 >> 3) & 0x7

Масштабный индекс определяется как (specflag2 & 0xC0) >> 6:

0 eq 0

1 eq 2

2 eq 4

3 eq 8

По этой схеме specflag2, равный, скажем, 64, представляет операнд [eax+eax*2]

o_displ

Операнд представляет собой ссылку типа [базовый регистр + индексный регистр + смещение]. Сегментный регистр содержится в поле specval_shorts.high. Поле phrase содержит значение базового регистра. Также используется SIB байт (см. описание выше). Поле value содержит значение, если flags & OF_OUTER_DISP.

Поле addr содержит адрес, если !(flags & OF_NO_BASE_DISP).

o_imm

Операнд содержит непосредственное значение в поле value.

o_far & o_near

Операнд содержит дальнюю и ближнюю ссылку на адрес в поле addr. Сегментный регистр содержится в поле specval_shorts.high.

11

Для инструкций с плавающей точкой - поле reg содержит номер регистра FPU (0 - ST(0), 1 - ST(1) и т.д.)

12

Для инструкций с использованием MMX - поле reg содержит номер регистра MMX (0 - MM0, 1 - MM1 и т.д.)

13

Для инструкций с использованием SSE - поле reg содержит номер регистра SSE (0 - XMM0, 1 - XMM1 и т.д.)


Конвертор inst.pl


Как Вы уже могли догадаться, я не руками формирую файл x86data.c. Эту идею я позаимствовал из Nasma - создаётся файл с данными, в удобном для обращения с ним формате, а уже из него генерируется файл на C. Для подобных манипуляций предназначен script на любимом мною Perlе inst.pl.

Он запускается примерно так:

perl inst.pl [параметры командной строки]

где параметры могут быть следующими:

-c file

Проверить файл заголовков на наличие ошибок. В настоящее время реализованы только две проверки - на наличие дублирующихся itype, а также поиск пропущенных itype. Отчёт помещается в file.

-d file

Задаёт имя файла данных. Имя по умолчанию - data

-i file

Задаёт имя файла заголовков. Имя по умолчанию - x86.h

-n file

Генерирует файл-шаблон file для дальнейшего заполнения его данными.

-o file

Устанавливает имя выходного файла. Имя по умолчанию - x86data.c. Если выходной файл уже существует - программа сообщает об этом и завершает исполнение, существующий файл не модифицируется.

-s

Игнорировать инструкции из файла заголовков, помеченные комментариями с тремя вопросительными знаками.

-?

Показывает краткую инструкцию по использованию программы...

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

Формат входного файла для inst.pl:

# комментарии [имя инструкции] keyword: data ...

[имя инструкции] - это название инструкции, взятое из файла заголовков. Я не использую численных значений (хотя это было бы быстрее в обработке) по той причине, что Вам всё равно нужно будет для каждого численного значения находить мнемоническое имя из файла заголовков. Когда inst.pl запускается с ключом -n, она генерирует файл, в котором будут прописаны в таком виде мнемоники всех инструкций из файла заголовков.


keyword: data - характеристики инструкции. В настоящее время программа понимает следующие keyword:

cflags

Изменяемые инструкцией флаги. Можно указывать как большими, так и маленькими буквами.

rflags

Флаги, от которых зависит результат выполнения инструкции. Можно указывать как большими, так и маленькими буквами.

uflags

Флаги, состояние которых не определено после выполнения инструкции. Можно указывать как большими, так и маленькими буквами.

regs

Самое главное (собственно, ради чего и была написана библиотека) - регистры, изменяемые инструкцией. Можно указывать как большими, так и маленькими буквами.

op

Битовая маска операндов, изменяемых инструкцией. Для операнда 1 используется первый бит, для операнда 2 - второй, и т.д.

type

Тип инструкции (FPU, MMX и т.д.). Можно указывать как большими, так и маленькими буквами.

from

Указывает тип процессора, начиная с которого инструкция распознаётся. Можно указывать как большими, так и маленькими буквами.

fcflags

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

fuflags

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

Для cflags,rflags,uflags & regs производится проверка на наличие дублирующих данных (в случае их обнаружения они просто игнорируются). Каждый keyword должен присутствовать для одной инструкции не более одного раза.


Обнаруженные баги


Вы удивлены, что даже в такой программе как IDA Pro есть баги ? Но ведь это всего лишь программа, почему бы в ней не быть багам ? Кроме того, до сих пор нет единого мнения, какие же именно и сколько инструкций составляют так называемый "x86 ассемблер", и с каждой новой моделью от Intelа и производителей клонов положение только ухудшается... Но обо всём по порядку.

Я нашёл некоторые неопределённые itype (внутренние instruction codes). Это, видимо, не следует считать багом, но всё равно неприятно. Такими являются: 100, 143, 144, 145

Очень большое количество багов описывается в великолепной статье Криса Касперски "ТОНКОСТИ ДИЗАССЕМБЛИРОВАНИЯ" (http://dore.on.ru/articles/disass.pdf). Я не буду пересказывать всю статью, но меня особенно поразило, что IDA не умеет дизассемблировать инструкции, манипулирующие управляющими и отладочными регистрами, несмотря на то, что прекрасно их ассемблирует !

IDA не умеет ассемблировать все 3DNow!, MMX & SSE инструкции, что не мешает ей правильно их дизассемблировать, и даже заполнять для них структуру insn_t.

Ещё более плохие новости: IDA Pro не понимает некоторых слабо документированных (или вообще недокументированных) инструкций. Даже бесплатный Netwide Assembler умеет ассемблировать/дизассемблировать следующие не понимаемые IDA Pro инструкции:

IBTS XBTS SMI UD1 (часто называют также как UD) UD2

Между прочим, UD2 описана в 24319102.pdf - "Intel Architecture Software Developer's Manual. Volume 2: Instruction Set Reference".

Ещё больше недокументированных (и не опознаваемых IDA Pro) инструкций можно найти в этом документе от Potemkin's Hackers Group: http://d1.ifmo.ru/library/dosint/OPCODES/OPCODES.HTM

Краткий перечень не опознаваемых IDA Pro инструкций, но опознаваемых Biew (взять можно на http://biew.sourceforge.net) :

ПроцессорИнструкцияOpcode

386umov0F (10-13)
AMD K6syscall0F 05
sysret0F 07
AMD K7pf2iw0F 0F/rm/1C
pfnacc0F 07/rm/8A
pfpnacc0F 0F/rm/8E
pi2fw0F 0F/rm/0C
pswapd0F 0F/rm/BB
Cyrix486smintold0F 7E
Cyrix686rdshr0F 36
smint0F 38
wrshr0F 37
i387SL MobilefnstdwDF E1
fnstsgDF E2
Cyrix 487frichopDD FC
frinearDF FC
frint2DB FC
<
Что из всего этого следует ? Вы всегда должны иметь под рукой все вышеперечисленные документы и не доверять слепо всему, что показывает IDA Pro (особенно когда она помечает кусок памяти как data, хотя Вы уверены, что это code).

Почему же IDA Pro, коммерческий продукт, проигрывает бесплатным Nasmу & Biew ? Мы имеем классический случай проявления недостатков закрытой системы - исходные код Nasmа & Biew публично доступны, и любой, нашедший баг, легко может его исправить. Код же IDA Pro являет собой жуткую коммерческую тайну, и все вопросы/жалобы могут задавать исключительно зарегистрированные пользователи, причём без всякой надежды на ответ. Происходит же это не потому, что Ильфак Гильфанов такой жадный (хотя общаться с ним практически невозможно). Дело в том, что DataRescue - западная компания, и в ней действует западный стандарт на поддержку клиентов. А в этих ISO-стандартах жалобы клиента, не купивший продукт, принципиально не рассматриваются, даже если несчастный клиент нашёл баг в программе управления ядерным реактором, ежеутренне порождающий пару Чернобылей. По моему глубокому убеждению, это не есть правильно, ибо именно такая схема и порождает монстров наподобие Winblows NT или UnixWare 7 - заточены только функции, за которые заплачены деньги. Всё остальное в расчёт просто не берётся, хотя множество серьёзных багов лежат на поверхности, ежедневно отравляя жизнь - и поделать с ними ничего нельзя, ведь это закрытые системы, у Вас просто нет доступа к исходным кодам...


Требования


Вы должны знать ассемблер процессоров семейства Intel x86. Также, поскольку на сей раз я представляю библиотеку для pluginов к IDA Pro, Вы должны иметь копию этого замечательного дизассемблера (библиотека была написана для версии 3.85b, и, поскольку я не располагаю другими версиями, поддерживающими plugins (такая возможность появилась в версии 3.84), то я не могу гарантировать её работоспособность на других версиях IDA). Если же Вы намерены пользоваться исходным кодом, Вам нужно знать C++ ,и для сборки потребуются Borland C++ 5.02 или Watcom 10, а также IDA SDK для Вашей версии IDA. Также если Вы намерены изменять или расширять характеристики набора инструкций, Вам потребуется Perl. Perl сгодится любой, даже под Unix, если же Вы хотите иметь его персонально на своём персональном компьютере (это всё дурное влияние Билли), могу порекомендовать ActiveState Perl под Win32, взять можно здесь, бесплатно, по крайней мере, когда я ходил туда последний раз за версией 515, было бесплатно...

PS: Не нужно у меня спрашивать, где найти IDA Pro или SDK к ней. Попробуйте посетить сайт автора по адресу www.datarescue.com.



Жалобы и предложения


можно отправлять автору по адресу redplait@usa.net. На глупые вопросы типа "А где же мне всё-таки достать IDA Pro" или "Где мне взять документацию по x86 ассемблеру" я не отвечаю. Если же Вы нашли bug, имеете конструктивные идеи или уверены в моей неправоте - всегда открыт к общению. Также большая просьба - не присылайте мне десятимегабайтных (притом несжатых) файлов в качестве доказательства чего бы то ни было.

Кроме того, автор не несёт ответственности за последствия работы его программ...

Ну и если Вам нужно написать загрузчик, plugin или процессорный модуль для IDA Pro - можете смело обращаться к автору сего...

#include <std_disclaim.h>