Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #83, НОЯБРЬ 2005 г.

Секреты покорения эльфов

Крис Касперски ака мыщъх

Хакер, номер #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", а следом за ней ту строку, которую выводит наша подопытная программа, и экран будет выглядеть так:

[заключение]

Мы рассмотрели простейший случай, а пропыхтели над ним два часа. А сколько займет троянизация полноценной программы? Всю оставшуюся жизнь? Конечно же, нет. Долго это только с непривычки, потом вырабатывается навык, и все идет на автопилоте. Главное - не бояться трудностей и постоянно тренироваться, оттачивая свое мастерство!

Назад на стр. 083-106-5  Содержание  Вперед на стр. 083-106-7