Аудит и дизассемблирование exploit'ов

в начале shell-кода расположен расшифровщик, расшифровывающий весь остальной код


Первые 8 команд более или менее понятны, а вот дальше начинается явный мусор, типа инструкций IN и OUT, которые при попытке выполнения на прикладном режиме возбуждают исключение. Тут что-то не так! Либо точка входа в shell-код начинается не с первого байта (но это противоречит результатам наших исследований), либо shell-код зашифрован. Присмотревшись к первым восьми командам повнимательнее, мы с удовлетворением обнаруживаем тривиальный расшифровщик в лице инструкции XOR, следовательно, точка входа в shell-код определена нами правильно и все, что нужно — это расшифровать его, а для этого мы должны определить значение регистров EBX и ECX, используемых расшифровщиком.

С регистром ECX разобраться несложно — он инициализируется явно, путем нехитрых математических преобразований: sub ecx,ecxàecx:=0; sub ebx,-50hàadd ecx,50hàecx := 50h, то есть на входе в расшифровщик ECX будет иметь значение 50h – именно столько двойных слов нам предстоит расшифровать.

С регистром EBX все обстоит намного сложнее и чтобы вычислить его значение, необходимо углубиться во внутренние структуры данных сопроцессора. Команда FLDZ помещает на стек сопроцессора константу +0.0, а команда FSTENV сохраняет текущую среду сопроцессора по адресу [esp-0Ch]. Открыв "Intel Architecture Software Developer's Manual Volume 2: Instruction Set Reference", среди прочей полезной информации мы найдем и сам формат среды FPU:

FPUControlWord                    ß SRC(FPUControlWord);

FPUStatusWord               ß SRC(FPUStatusWord);

FPUTagWord                 ß SRC(FPUTagWord);

FPUDataPointer                    ß SRC(FPUDataPointer);

FPUInstructionPointer             ß SRC(FPUInstructionPointer);

FPULastInstructionOpcode   ß SRC(FPULastInstructionOpcode);



Содержание раздела