Пишем 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-кода процедуру их дешифровки. Потом смотрим на четные байты и делаем то же самое с ними: |