Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Разработка трассировочного плагина для IDA

Обсудить статью на форуме

Очень удобно, когда все крэкерские инструменты, книги и статьи в одном месте. Используйте сборник от EXELAB - вот тут.

Автор: northdemon <northdemon@mail.ru>

"Опыт - нечто, что вы не получаете
до тех пор, пока это вам не понадобится".
(Оливер)


Об IDA как дизассемблере сказано уже достаточно много, но IDA, к тому же еще и отличный отладчик! А возможности IDA SDK и созданные на его основе плагины позволяют неограниченно расширить функциональность при анализе!

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

В процессе написания плагина нам понадобятся IDA 5.0, SDK IDA и вижуалная среда разработки, например, Visual C++ 6.0. О работе в других средах и их настройке можно найти в “Руководстве по созданию плагинов на С и С++” по адресу: http://www.binarypool.com/idapluginwriting – это наиболее полное на сегодняшний день практическое руководство по созданию плагинов для IDA с огромным количеством примеров.

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

Далее рассмотрим общую теорию, необходимую для написания плагинов в IDA.

Любой плагин в IDA строится на основе следующего “шаблона”:

#include <ida.hpp>
#include <idp.hpp>
#include <loader.hpp>

int IDAP_init(void)
{
// Вызывается IDA для инициализации переменных, 
// используемых в плагине. 
// Именно здесь проверяется анализируемый формат файла, 
// для которого был создан плагин (например, f_PE) 

// Функция возвращает PLUGIN_SKIP, если проверка прошла неудачно, 
// иначе – PLUGIN_KEEP.

 return PLUGIN_KEEP;
}

void IDAP_term(void)
{
// Выполняется при выходе из плагина.
// Необходима, например, для освобождения динамической памяти 
// или файловых дескрипторов, которые были задействованы в 
// процессе работы плагина.
 
 return;
}

// Через файл plugins.cfg в плагин могут быть переданы целые 
// аргументы

void IDAP_run(int arg)
{
// Это “тело” плагина

 msg("Hello world!");
 return;
}

// Строка задает описание плагина, доступное из IDA
char IDAP_comment[] = "This is my test plug-in";
char IDAP_help[] = "My plugin";

// Строка задает имя плагина, отображаемое в меню Edit->Plugins menu.
char IDAP_name[] = "My plugin";

// Комбинация клавиш для быстрого вызова плагина в IDA
char IDAP_hotkey[] = "Alt-X";

// Объект PLUGIN
plugin_t PLUGIN =
{
 IDP_INTERFACE_VERSION, // Версия IDA, для которой 
                        // предназначен плагин 
 0,                     // Флаги
 IDAP_init,             // Функция инициализации
 IDAP_term,             // Функция “очистки”
 IDAP_run,              // Основное “тело” плагина 
 IDAP_comment,          // Комментарии
 IDAP_help,             // Помощь
 IDAP_name,             // Имя плагина
 IDAP_hotkey            // Комбинация “горячих” клавиш
};

Представленный выше “шаблон-плагин” с помощью вызова функции msg() выводит в консоль IDA строку “Hello world!”. Чтобы не отделять теорию и практику, сразу рассмотрим как работает этот плагин. Для этого поместим его исходный текст в уже настроенный проект vcsample, который содержится в /idasdk/plugins/vcsample. Результатом компиляции будет файл vcsample.plw в каталоге /idasdk/bin/w32/plugins. Полученный файл необходимо поместить в каталог с установленной IDA: /IDA/plugins. Теперь для вызова плагина необходимо загрузить в IDA исследуемый файл и перейти в меню Edit -> Plugins -> My plugin.

Полное описание всех функций, предоставляемых IDA SDK, можно найти в файлах, в папке: /idasdk/include. Например, описание работы функции msg() содержится в файле kernwin.hpp.

Теперь расширим функциональность нашего “шаблона-плагина” для работы в режиме отладки и трассировки значений регистра ESP.

Прежде всего, добавим обработчик событий, получаемых от отладчика:


hook_to_notification_point(HT_DBG, trace_handler, NULL),

где первый аргумент – HT_DBG обозначает события, получаемые от текущего отладчика, второй – trace_handler – имя функции-обработчика событий, третий – обычно NULL (без параметров).

Функцию обработки будем вызывать при инициализации плагина:

int IDAP_init(void)
{
// Инициализация обработчика событий, получаемых от отладчика
hook_to_notification_point(HT_DBG, trace_handler, NULL);
	
return PLUGIN_KEEP;
}

Перейдем к написанию функции-обработчику событий с именем trace_handler. Исходя из постановки нашей задачи, данная функция должна перехватывать события трассировки (dbg_trace), генерируемые ядром IDA, и печатать в консоли значения регистра ESP. В SDK регистры описываются с помощью структуры register_info_t (ее определение можно найти в заголовочном файле SDK idd.hpp). Значения, хранящиеся в регистрах, описываются структурой regval_t. Получить значение регистра можно с помощью элемента ival структуры regval_t, воспользовавшись функцией get_reg_val() (определение функции можно найти в файле dbg.hpp).

Ниже представлен код получившейся функции-обработчика событий:

// Обработчик для HT_DBG событий 
int idaapi trace_handler(void *udata, int dbg_event_id, va_list va)
{
 regval_t esp;
 // Получаем значение регистра ESP:
 get_reg_val("esp", &esp);
  
 if (dbg_event_id == dbg_trace) 
 {
	msg("ESP = %an", esp.ival);
 }
 return 0;
}

При выходе из плагина завершим обработку событий, получаемых от отладчика, следующим образом:

void IDAP_term(void)
{
// Завершение обработки событий 
unhook_from_notification_point(HT_DBG, trace_handler, NULL);
return;
}

В заключение осталось задать параметры отладки, “включить” пошаговую отладку и вызвать сам отладчик:

void IDAP_run(int arg)
{
 // Указываем точку входа
 request_run_to(inf.startIP);
 // Включаем пошаговую трассировку
 request_enable_step_trace();
 // Запускаем отладчик
 run_requests();
}

Что такое inf.startIP?

В базе данных IDA (IDB) хранится структура idainfo. Она содержит, так называемую, “мета” информацию об изначальном файле, который был загружен в IDA для дизассемблирования. Рассмотрим основные поля этой структуры, определенные в заголовочном файле ida.hpp:

struct idainfo
{
 ... 
 ushort filetype;   // Тип входного файла 
                    // filetype_t enum – может быть 
                    // f_ELF, f_PE, и т.д.
 ea_t	 startSP;   // Значение регистра [E]SP на 
 		    // начальном этапе выполнения программы
 ea_t	 startIP;   // Значение регистра [E]IP на начальном 
                    // этапе выполнения программы
 ea_t	 beginEA;   // Линейный адрес точки входа программы, 
                    // обычно startIP
 ...
};

В SDK IDA inf определяется, как глобальный общедоступный экземпляр структуры idainfo.

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

#include <ida.hpp>
#include <idp.hpp>
#include <loader.hpp>
#include <dbg.hpp>

// Обработчик для HT_DBG событий 
int idaapi trace_handler(void *udata, int dbg_event_id, va_list va)
{
 regval_t esp;
 // Получаем значение регистра ESP:
 get_reg_val("esp", &esp);
  
 if (dbg_event_id == dbg_trace) 
 {
  msg("ESP = %an", esp.ival);
 }
 return 0;
}

int IDAP_init(void)
{
 // Вызывается IDA для инициализации переменных, 
 // используемых в плагине. 
 // Именно здесь проверяется анализируемый формат файла, 
 // для которого был создан плагин (например, f_PE) 

 // Функция возвращает PLUGIN_SKIP, если проверка прошла неудачно, 
 // иначе - PLUGIN_KEEP.

 // Обработчик событий, получаемых от отладчика
 hook_to_notification_point(HT_DBG, trace_handler, NULL);
 return PLUGIN_KEEP;
}

void IDAP_term(void)
{
// Выполняется при выходе из плагина.
// Необходима, например, для освобождения динамической памяти 
// или файловых дескрипторов, которые были задействованы в 
// процессе работы плагина.
 
// Завершаем обработку событий от отладчика
unhook_from_notification_point(HT_DBG, trace_handler, NULL);
	
return;
}
// Через файл plugins.cfg в плагин могут быть переданы целые 
// аргументы

void IDAP_run(int arg)
{
 // Указываем точку входа
 request_run_to(inf.startIP);
 // Включаем пошаговую трассировку
 request_enable_step_trace();
 // Запускаем отладчик
 run_requests();
}

// Строка задает описание плагина, доступное из IDA
char IDAP_comment[] = "This is trace plug-in";
char IDAP_help[] = "My trace plugin";

// Строка задает имя плагина, отображаемое в меню Edit->Plugins menu.
char IDAP_name[] = "My trace plugin";

// Комбинация клавиш для быстрого вызова плагина в IDA
char IDAP_hotkey[] = "Alt-X";

// Объект PLUGIN
plugin_t PLUGIN =
{
 IDP_INTERFACE_VERSION, // Версия IDA, для которой 
               // предназначен плагин 
 0,            // Флаги
 IDAP_init,    // Функция инициализации
 IDAP_term,    // Функция "очистки"
 IDAP_run,     // Основное "тело" плагина 
 IDAP_comment, // Комментарии
 IDAP_help,    // Помощь
 IDAP_name,    // Имя плагина
 IDAP_hotkey   // Комбинация "горячих" клавиш
};

Добро пожаловать в ряды разработчиков плагинов для IDA! :-)

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




Обсуждение статьи: Разработка трассировочного плагина для IDA >>>


Комментарии к статье: Разработка трассировочного плагина для IDA

northdemon 07.09.2007 10:46:46
В статье в нескольких местах пропал перевод строки: необходимо "n" вместо "n".
---

Материалы находятся на сайте https://exelab.ru



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS