Секреты покорения эльфов Крис Касперски ака мыщъх Хакер, номер #083, стр. 083-106-6 mov ecx, offset begin_msg ; указатель на первый символ выводимого сообщения mov edx, offset end_msg ; указатель на последний символ выводимого сообщения int 80h ; вывод на экран pop esi ; сохраненные команды xor ebx,ebp jmp 80482C3h ; возврат в программу Это не самый оптимальный вариант, и его можно здорово оптимизировать, если переписать так: Оптимизированный вариант xor eax,eax add al, 4 xor ebx,ebx inc ebx mov ecx, offset begin_msg mov edx,ecx add edx, sizeof(msg) int 80h pop esi xor ebp, ebp jmp 80482C3h Теперь прокручивая файл в hex-редакторе, найдем и выпишем стартовые адреса всех цепочек NOP'ов, пригодных для внедрения. А какие цепочки пригодны для внедрения? Если две соседние цепочки расположены в пределах досягаемости короткого перехода (грубо - в пределах сотни байт), 3х NOP'ов будет вполне достаточно (2 байта на команду перехода, один - на любую однобайтовую команду полезного кода, например, inc ebx или pop esi). В противном случае нам необходимо иметь цепочку, по крайней мере, из шести NOP'ов: пять на команду близкого перехода и один на полезную команду. В нашем случае получается: 8048306h 10 байт 80483a2 14 байт 8048464 12 байт Итого - 36 байт. Вполне достойное место для демонстрационной программы! Начинаем заполнять цепочки NOP'ов полезным кодом. С первой попытки у нас получается: 8048306 31 c0 xor eax, eax 8048308 04 04 add al, 4 804830a e9 93 00 00 00 jmp 80483a2h 804830f 90 nop При этом один последний NOP останется потерян, но по-другому не получается. Команда xor ebx,ebx занимает два байта и сюда не помещается. А что если переставить команды местами? Перенести add al,4 в следующую цепочку NOP, а вместо нее вставить xor ebx,ebx/inc ebx: 8048306 31c0 xor eax, eax 8048308 31db xor ebx, ebx 804830a 43 inc ebx 804830b e9 92 00 00 00 jmp 80483a2h Тогда следующая цепочка будет заполнена так: 80483a2 0404 add al, 4 80483a4 b9 ?? ?? ?? ?? mov ecx, offset begin_msg 80483a9 89ca mov edx, ecx 80483ab e9 b4 00 00 00 jmp 8048464h В третью, последнюю, цепочку NOP'ов остаток кода уже не идет, не хватает одного единственного байта! Что ж, попытаемся еще немного ужать наш код. Например, вместо пары инструкций mov edx,ecx/add edx,sizeof(msg), которые занимают 5 байт, можно использовать lea edx,[ecx+sizeof(msg)]. Тогда все влезает! Ну а само сообщение можно разместить в сегменте данных. Поскольку свободного места там не очень много, ограничимся строкой "hello". Завершающий нуль в конце ставить необязательно, поскольку системный вызов write выводит ровно столько символов, сколько ему приказано вывести, и ни на какие знаки «останова» не реагирует. Если все было сделано правильно (что маловероятно, в первый раз ошибки делают все), наш файл победоносно выведет строку "hello", а следом за ней ту строку, которую выводит наша подопытная программа, и экран будет выглядеть так: [заключение] Мы рассмотрели простейший случай, а пропыхтели над ним два часа. А сколько займет троянизация полноценной программы? Всю оставшуюся жизнь? Конечно же, нет. Долго это только с непривычки, потом вырабатывается навык, и все идет на автопилоте. Главное - не бояться трудностей и постоянно тренироваться, оттачивая свое мастерство! |