Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #66, МАЙ 2006 г.

термоядерный инлайн

GETORIX | INT3

Спецвыпуск: Хакер, номер #066, стр. 066-068-4


Теперь при грамотном пропатчивании существующая защита перестанет мешать нормальной работе с программой.

[остается написать патч] Как уже было сказано, inline-патч должен быть запущен перед переходом на OEP (Original Entry Point), но в нашем случае EP (Entry Point) = OEP. И где размещать его? Можно, конечно, поколдовать с самим файлом: добавить новую секцию (с патчем), изменить параметр AdressOfEntryPoint в PE-заголовке, указав на эту секцию, и потом из тела патча передавать управление непосредственно на начало программы в основной секции кода. В предложенном способе плохо только то, что придется вносить значительные модификации в файл (получив, как следствие, изменение размеров и смешение секций), чего как раз не хотелось бы. У меня же родилась идея заменить первый в программе BL-переход (Branch with Link) на вызов нашего inline-патча и уже из него (после того как основной код будет исправлен) передать управление функции, вызываемой в оригинале. Конечно, звучит немного нелогично и сложновато, зато интересно с точки зрения реализации.

Для начала определимся с местом расположения нашего собственного кода. Видимо, после основного кода, перед секцией импорта. Для того чтобы узнать адрес последней инструкции, в листинге IDA перейдем на начало секции импорта (она находится по адресу 1E000). Смотрим выше и видим, что секция кода заканчивается адресом 1D830. Отступим немного и определим начало патча на адрес 1D840. Теперь запустим любой редактор PE, здесь в конверторе из этого RVA получим File offset. Получается, CC40.

Наконец-то пришла пора разработки тела inline-патча. Здесь советую уделить большое внимание сохранению параметров функции в стеки при входе в подпрограмму (Prolog) и их восстановлению из стека (Epilog) при выходе из подпрограммы. Дело в том, что архитектура ARM поддерживает множество способов укладывания данных в стек, и если не понимать разницу между ними, быстро запутаешься и приведешь свой КПК к HardReset.

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

Листинг 4. ARM-код inline-патча

0001D840 STMFD SP!, {LR} [сохраним адрес возврата в стеке]

0001D844 STMFD SP!, {R0-R3} [сохраним параметры затертой функции]

0001D848 MOV R0, #0xEA [опкод безусловного перехода]

0001D84C LDR R1, =0x18DEF [адрес перехода таймера]

0001D850 STRB R0, [R1] [замена байта в памяти]

0001D854 LDR R1, =0x11147 [адрес вызова диалога]

0001D858 STRB R0, [R1] [замена байта в памяти]

0001D85C LDMFD SP!, {R0-R3} [восстанавливаем параметры функции]

0001D860 BL _cinit [вызов затертой функции]

0001D864 LDMFD SP!, {PC} [возвращаемся обратно]

Если выбросить команду «BL _cinit» или заменить ее на какой-либо другой вызов, можно скомпилировать эту программу и таким образом получить опкод. Затем вырезать его в HEX-редакторе и поместить в жертву по уже оговоренному адресу CC40. Разумеется, профессионалы обойдутся и без таких действий и запишут опкод сразу, по памяти.

Назад на стр. 066-068-3  Содержание  Вперед на стр. 066-068-5