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

Пишем shell-код!

Коваленко Дмитрий aka Ingrem

Спецвыпуск Xakep, номер #045, стр. 045-014-5


; она не больше 255 байт), стараемся, чтобы код не содержал

; нулевых байт, поэтому вместо

; mov ecx, expl_end-expl_start

; делаем так

xor ecx, ecx

mov cl, expl_end-expl_start

; заносим в eax уазатель на тело эксплоита, опять-таки

; стараемся, что бы код не содержал нулевых байт

mov eax, esp; заносим в eax адрес головы shell-кода

; добавляем смещение на тело

add eax, expl_start-exploit_head

; теперь все готово для дешифровки

@@1: mov bl, byte ptr[eax] ; читаем очередной байт зашифрованного тела в bl

add bl, -ADD_KEY; отнимаем от него ADD_KEY

xor bl, XOR_KEY; ксорим его на XOR_KEY

mov byte ptr[eax], bl; записываем расшифрованный байт в тело

inc eax ; перемещаем указатель на следующий байт тела

loop @@1; если ecx не равен 0 - новый виток цикла

expl_start:

; тут находится тело shell-кода

......

expl_end dd 0; нулевой байт, завершает строку с shell-кодом

Как видим, процедура расшифровки почти не отличается от процедуры шифрования. Правда, в ней есть некоторые важные нюансы. Во-первых, если при шифровании мы сперва ксорили, а затем прибавляли, то при расшифровке мы делаем наоборот: сперва отнимаем, а затем ксорим. Во-вторых, сама процедура расшифровки не содержит нулевых байт – в этом можно убедиться, загнав ее под отладку. Само собой, обе процедуры могут использовать только одну из инструкций – AND или XOR. Например, для того чтобы использовать только XOR, достаточно закомментировать в процедуре шифрования строчку: add bl, ADD_KEY , а в процедуре дешифровки – строчку: add bl, -ADD_KEY, и тогда для шифрования понадобится лишь один байт – XOR_KEY. Теперь, как я и обещал, поговорим о байтах ADD_KEY и XOR_KEY. Эти два байта представляют собой ключи, с помощью которых мы зашифровываем и расшифровываем. Их надо подобрать так, чтобы зашифрованное тело shell-кода не содержало нулевых байт. Как это сделать? Большинство хакеров подбирают эти ключи методом научного тыка или пишут программы, которые находят нужную пару байт простым перебором. Этот способ работает в большинстве случаев, хотя он немного глуп. Поэтому я придумал, как шифровать эксплоиты любой длины с помощью последовательного применения нескольких XOR'ов. Я не буду объяснять здесь общую идею – она требует знания дискретной теории групп и немного сложна для вступительной статьи. Расскажу лишь о двух простых правилах, вытекающих из нее (в обоих правилах используется лишь XOR, ADD отдыхает).

Правило 1. Если тело shell-кода меньше 256 байт и оно содержит нулевые байты, в качестве ключа XOR_KEY нужно брать байт, который ни разу не встречается в теле shell-кода. Такой байт обязательно найдется, ведь тело слишком короткое и не может содержать в себе 256 разных байт :-). К тому же, этот байт будет ненулевым.

Правило 2. Если тело shell-кода меньше 510 байт и оно содержит нулевые байты, то следует ксорить четные и нечетные байты тела отдельно. Сначала смотрим на нечетные байты (первый, третий, пятый и т.п.), четные пока не трогаем). Если среди них есть нулевые байты, то в качестве ключа XOR_KEY_EVEN берем байт, который среди них не встречается. Как и в первом случае, такой байт обязательно найдется, так как количество нечетных байт в теле shell-кода меньше чем 256. Шифруем этим ключом только нечетные байты и записываем в голову shell-кода процедуру их дешифровки. Потом смотрим на четные байты и делаем то же самое с ними:

Назад на стр. 045-014-4  Содержание  Вперед на стр. 045-014-6