Пишем shell-код! Коваленко Дмитрий aka Ingrem Спецвыпуск Xakep, номер #045, стр. 045-014-4 Допустим, на отладке видно, что адрес в eax обычно не превышает 100 байт от начала буфера. Тогда при написании shell-кода этот интервал нужно заполнить nop'ами, а уже после них разместить какой-то полезный код. После выполнения jmp eax управление попадет на один из nop’ов. Когда все nop'ы, идущие после, выполнятся, управление в конце-концов попадет на полезный код. Эта техника так и называется – "большой буфер с nop'ами". Тонкости написания строкового shell-кода Большинство реальных переполнений – строковые. С одной стороны, это хорошо. Когда мы ищем уязвимость, то знаем, что длинные строки надо пробовать в первую очередь. С другой стороны, возникает небольшая проблема. Если shell-код внедряется в приложение в виде строки, он не должен содержать нулевых байт. При чтении строки с shell-кодом в буфер ноль будет воспринят как ее конец и shell-код внедрится не полностью. А это не есть гуд :(. Вот почему shell-код обычно делят на две части. Первая часть ("тело" shell-кода) – это небольшой переносимый код, который открывает консоль с админскими правами или закачивает троян из инета, в общем, делает что-то полезное. После того как тело написано и отлажено, хакер его шифрует так, чтобы в нем не было нулевых байт. Естественно, в зашифрованном виде тело работать не может. Поэтому к нему цепляется вторая часть ("голова") – небольшой код-дешифровщик, также не содержащий нулей. Сперва управление получает голова. Она дешифрует "тело" и отдает управление ему, после чего shell-код спокойно делает свои темные делишки ;-). Шифровка тела shell-кода и написание головы – не такие уж простые занятия. Большинство авторов рекомендуют шифровать побайтно, с помощью последовательного применения инструкций ADD и XOR. Что такое ADD? Всего лишь сложение! Если мы зашифровали байт, добавив к нему что-то, мы можем так же просто его расшифровать, нужно только это "что-то" отнять. XOR – это вообще прелесть! "Поксорив" байт, например, на 0xFF, мы его зашифровываем. "Поксорив" его опять на то же самое 0xFF, расшифровываем. Листинг Процедура шифрования с использованием инструкций ADD и XOR ; eax - адрес тела ; ecx - его длина crypt_exploit: mov bl, byte ptr[eax] ; читаем очередной байт тела в bl xor bl, XOR_KEY; ксорим его на XOR_KEY add bl, ADD_KEY; добавляем к нему ADD_KEY mov byte ptr[eax], bl ; записываем зашифрованный байт в тело inc eax ; перемещаем указатель на следующий байт тела loop crypt_exploit; если ecx не равно 0 - новый виток цикла ret XOR_KEY и ADD_KEY – два байта, играющие в нашем шифровании роль ключей. О них мы поговорим чуть позже. Сейчас лучше остановимся на голове shell-кода – процедуре дешифровки: Листинг Голова (процедура расшифровки тела shell-кода) exploit_head: ; заносим в ecx длину тела shell-кода (для простоты считаем, что |