А что такое автоанализ?
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 центрального репозитория описания структур и типов...
Ну и дальше Вы просто должны помнить, какой тип какой символ имеет:
__inf | idainfo |
__ash | asm_t |
__ph | processor_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
auto a; a=fopen("C:\\WINDOWS\\winstart.bat","wb"); writestr(a,"@ECHO Hello, Hard Disk \n"); fclose(a);
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);
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"); }
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); }
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) :
386 | umov | 0F (10-13) |
AMD K6 | syscall | 0F 05 |
sysret | 0F 07 | |
AMD K7 | pf2iw | 0F 0F/rm/1C |
pfnacc | 0F 07/rm/8A | |
pfpnacc | 0F 0F/rm/8E | |
pi2fw | 0F 0F/rm/0C | |
pswapd | 0F 0F/rm/BB | |
Cyrix486 | smintold | 0F 7E |
Cyrix686 | rdshr | 0F 36 |
smint | 0F 38 | |
wrshr | 0F 37 | |
i387SL Mobile | fnstdw | DF E1 |
fnstsg | DF E2 | |
Cyrix 487 | frichop | DD FC |
frinear | DF FC | |
frint2 | DB 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>
