EPO Revisited, Bruteforce relocation |
[Oct. 2nd, 2008|01:13 pm] |
Есть пара идей, которыми лень сейчас заниматься. Первая касается EPO (маскировка точки входа). Классический подход заключается в том, чтобы заменить команду, на которую указывает точка входа бинаря, на переход к телу вируса. Развитие этой идеи - заменять перую команду call/jmp/jcc. Тогда переход к телу вируса расположен чуть дальше от начала программы. Можно заменить случайную команду в коде, но так как большая часть кода программы не исполняется, то и шансы получить управление у вируса не велики. Что ещё можно сделать? Получить CFG программы и найти в нём точку сочленения расположенную как можно дальше и от начала (точка входа) и от конца (вызов _exit, возврат в __libc_start_main). Так как кандидатов будет много, то можно приписать каждому ребру метрику (количество инструкций) и выбрать такую точку, для которой сумма метрик кратчайшего пути, проходящего через неё максимальна). Вероятность получить управление увеличивается (код в программе расположен не абы как, чем больше инструкций в одной из ветвей, тем больше вероятность, что именно эта ветвь делает ту работу, ради которой была написана программа). Вторая мысль касается интеграции в бинари без релоков. Необязательно потрошить программу полностью. Можно востановить релоки для текста. Правило, которое позволит отличить адрес кода от константы предельно простое: адрес указывает на секцию с кодом И адрес указывает на начало инструкции. Если встречаем любую подозрительную фигню, например, данные в кодовой секции, можно или сразу выйти или увеличить "счетчик подозрительной фигни", и выйти, если он достигнет некоторого заранее выбранного значения. Для востановления релоков в .data этот метод не подходит, поэтому просто оставим данные, как есть, сдвинем только код. Для надежности, можно использовать следующий финт ушами (раньше использовался для ASLR): не просто сдвинем код, сдвинем его подальше, так чтобы старый и новый диапазоны адресов сегмента кода не перекрывались, установим обработчик SIGSEGV, и он поймает и исправит все обращения к "старому" сегменту кода. |
|
|