Привет всем, Спустя довольно-таки продолжительное время с момента написания первой статьи я всё-таки решил, пусть и по чуть-чуть, но писать статьи на тему модификации/улучшения IDA Pro. В этой статье пойдёт речь о том, как правильно исправлять косяки в тех процессорных модулях, исходников которых у вас нет, а косяки прям-таки жить не дают. К сожалению, не все указанные ниже проблемы можно отнести к косякам, поэтому разработчики вряд ли станут их реализовывать. Примечание: здесь и далее будут рассматриваться ошибки в модуле Motorola M68000 (моём самом любимом и очень часто используемом). Итак, первый косяк: адресация относительно регистра PC. Ошибка заключается в том, что дизассемблерный листинг для таких инструкций не всегда корректен. Взглянем на скриншот:

Кажется, что ошибки здесь нет. Более того, её наличие не мешает анализу. Но, опкод дизассемблирован неправильно. Посмотрим на дизазм в каком-нибудь онлайн-дизассемблере:

Видим, что адресация у нас должна быть относительно PC-регистра, т.к. целевой адрес ссылки попадает в диапазон signed short. Косяк два: "зеркала" для оперативной памяти, и некоторых других регионов. Т.к. адресация в m68k 24-битная, то все обращения к старшим (или наоборот, младшим) регионам, должны быть переадресованы на один и тот же диапазон, как и перекрёстные ссылки. Косяк три (скорее, даже не косяк, а отсутствие функционала): так называемые lineA (1010) и lineF (1111) эмуляторы. Это такие опкоды, на которые не хватило основного набора команд, поэтому они должны обрабатываться специальным образом векторами прерываний. Размер опкодов зависит лишь от реализации на уровне обработчика. Я видел лишь двухбайтовую реализацию. Будем добавлять. Косяк четыре: trap #N инструкции не дают cref-ов на сами обработчики "ловушек". Косяк пять: movea.w инструкция должна делать из word-ссылки полный xref на адрес, но мы имеем только word-число. Для того, чтобы понять, как исправлять конкретный процессорный модуль, нужно понять, какие возможности на эту тему у нас есть в принципе и что из себя представляет "фикс". Собственно, "исправлялка" представляет из себя обычный плагин. Его, вроде как, можно написать и на Python, но, я всё делал в "плюсах". Страдает лишь портабельность, но, если кто-то возьмётся переписать плагин на Python — буду очень благодарен. Для начала создадим пустой DLL-проект в Visual Studio: File->New->Project->Windows Desktop Wizard->Dynamic link library (.dll), поставив также галку Empty Project, и сняв все остальные:
 Распакуем IDA SDK, и пропишем его в макросах Visual Studio (я буду использовать 2017), чтобы в будущем можно было легко ссылаться на него. Заодно мы добавим макрос для пути к IDA Pro. Заходим в View->Other Windows->Property Manager:
 Т.к. мы работаем с версией SDK 7.0, компиляция будет происходить x64-компилятором. Поэтому выбираем Debug | x64->Microsoft.Cpp.x64.user->Properties:
 Жмём кнопку Add Macro в разделе User Macros, и прописываем там макрос IDA_SDK с указанием пути, по которому вы распаковали SDK:
 Так же поступаем с IDA_DIR (путь к Вашей IDA Pro):

Замечу, что IDA ставится по умолчанию в %Program Files%, что требует прав администратора. Давайте также удалим Win32 конфигурацию (в данной статье я не буду затрагивать компиляцию под x86 системы), оставив только x64-вариант. Создадим пустой файл ida_plugin.cpp. Код пока не добавляем.
Теперь появилась возможность выставить кодировку, и другие настройки для C++:
   Пропишем инклуды:
 И библиотеки из SDK:
  Теперь добавим шаблон кода: Функции print_op() и print_insn() нужны для того, чтобы понять, какие флаги выставлены текущим процессорным модулем для определённых инструкций. Это нужно, если мы хотим найти какие-то флаги для имеющихся опкодов, чтобы потом использовать их при исправлении. Собственно, телом нашей "исправлялки" является функция hook_idp(). В ней для наших нужд потребуется реализовать три колбэка: Функция init_plugin() не даёт загрузиться нашей исправлялке в других процессорных модулях.
Ну и, самое главное — вешаем весь колбэк на события процессорного модуля: Для того, чтобы нормально решить эту проблему пришлось много повозиться с дебажным выводом, который я как раз реализовал для этой задачи. Я знал, что в некоторых случаях IDA успешно выводит ссылки относительно PC (в инструкциях, где происходит прыжок по таблице смещений, которая находится недалеко от текущей инструкции, плюс регистр-индекс), но для инструкции lea правильного отображения адресации не реализовано. В итоге, я нашёл такую инструкцию с прыжком, и выяснил, какие флаги нужно установить, чтобы PC со скобками отображался:  Тут всё просто. Просто маскируем адреса на конкретный диапазон: 0xFF0000-0xFFFFFF (для RAM) и 0xC00000-0xC000FF (для видеопамяти VDP). Тут главное фильтровать по типу операнда o_near и o_mem. Собственно, чтобы добавить нужный опкод, необходимо:  Решается так: находим опкод для инструкции trap, получаем индекс из инструкции, и берём по этому индексу вектор-обработчик. Получится что-то типа того:  Тут тоже всё просто: сначала фильтруем по операции movea.w. Затем, если операнд типа word, и ссылается на RAM, делаем ссылку по-крутому, относительно базы 0xFF0000. Выглядеть это будет так:  На самом деле, исправление существующих модулей является не очень-то и простой задачей, если это касается не просто реализации неизвестных опкодов, а чего-то посложнее.
Требуется многочасовая отладка существующей реализации, понимание происходящего в ней (иногда даже реверс проц-модуля). Но результат стоит того. Ссылка на исходник: https://github.com/lab313ru/m68k_fixer Реверс-инженер