| |
[Aug. 31st, 2009|09:14 pm] |
В который раз убеждаюсь, что всё новое - это хорошо забытое старое. Пока был в отпуске нашёл статью SMT "Использование Microsoft Visual C++ 6.0 для создания перемещаемого программного кода", TD 2000.03. Про более древние находки и не говорю, как-нибудь в другой раз. Ж-) Это не единственный пример того, как успешно проёбываются хорошие затеи. А что остаётся делать? Только изобретать заново велосипед и писать статьи от первого лица. Ж:-) Всё-таки напишу о двух топиках, с которыми столкнулся лично - о парсерах машинного кода и о позиционно-независимом коде с точки зрения gcc, давно ведь собираюсь. Завтра и начну. :-) |
|
|
| EPO Revisited, Bruteforce relocation |
[Oct. 2nd, 2008|01:13 pm] |
Есть пара идей, которыми лень сейчас заниматься. Первая касается EPO (маскировка точки входа). Классический подход заключается в том, чтобы заменить команду, на которую указывает точка входа бинаря, на переход к телу вируса. Развитие этой идеи - заменять перую команду call/jmp/jcc. Тогда переход к телу вируса расположен чуть дальше от начала программы. Можно заменить случайную команду в коде, но так как большая часть кода программы не исполняется, то и шансы получить управление у вируса не велики. Что ещё можно сделать? Получить CFG программы и найти в нём точку сочленения расположенную как можно дальше и от начала (точка входа) и от конца (вызов _exit, возврат в __libc_start_main). Так как кандидатов будет много, то можно приписать каждому ребру метрику (количество инструкций) и выбрать такую точку, для которой сумма метрик кратчайшего пути, проходящего через неё максимальна). Вероятность получить управление увеличивается (код в программе расположен не абы как, чем больше инструкций в одной из ветвей, тем больше вероятность, что именно эта ветвь делает ту работу, ради которой была написана программа). Вторая мысль касается интеграции в бинари без релоков. Необязательно потрошить программу полностью. Можно востановить релоки для текста. Правило, которое позволит отличить адрес кода от константы предельно простое: адрес указывает на секцию с кодом И адрес указывает на начало инструкции. Если встречаем любую подозрительную фигню, например, данные в кодовой секции, можно или сразу выйти или увеличить "счетчик подозрительной фигни", и выйти, если он достигнет некоторого заранее выбранного значения. Для востановления релоков в .data этот метод не подходит, поэтому просто оставим данные, как есть, сдвинем только код. Для надежности, можно использовать следующий финт ушами (раньше использовался для ASLR): не просто сдвинем код, сдвинем его подальше, так чтобы старый и новый диапазоны адресов сегмента кода не перекрывались, установим обработчик SIGSEGV, и он поймает и исправит все обращения к "старому" сегменту кода. |
|
|