Альтернатива NOP, которая бесполезна для салазок nop, но полезна для производительности: Какие методы могут быть использованы для эффективного увеличения длины инструкции на современном x86? (например, добавить дополнительные префиксы, чтобы сделать инструкции длиннее).
Обычно полезная нагрузка эксплойта не заботится о значениях регистров (кроме указателя стека), поэтому вы можете свободно уничтожать их с помощью таких вещей, как inc eax
(однобайтовый в 32-битном коде). Есть много однобайтовых инструкций, которые только изменяют регистры и не будут ошибаться. например cld
/ std
, stc
/ clc
/ cmc
, cwde
, cdq
все однобайтовые. Опять в 32-битном код, даже BCD-команды, такие как AAA
или DAA
, пригодны для использования, но они будут торчать, как больной большой палец, потому что компиляторы никогда не используют их. (Компиляторы на практике используют cdq
и, возможно, cwde
, но обычно не cld
или std
.)
С любой многобайтовой инструкцией, такой как mov eax,eax
, , убедитесь, что вы проверите, как она декодируется, если выполнение начинается с чего-то, кроме первого байта . Весь смысл салазок в том, что исполнение должно приземлиться где-то внутри буфера, но вы не знаете где.
Вы можете использовать дополнительные префиксы для создания многобайтовых инструкций, которые по-прежнему декодируются нормально, если выполнение начинается после префикса. cbw
равно 0x66 cwde
(префикс размера операнда).
Префиксы
rep
обычно игнорируются безопасно в инструкциях, к которым они не относятся, но могут работать по-другому на будущих процессорах. (Например, rep nop
раньше был просто NOP, но теперь это pause
. rep bsr
теперь lzcnt
, что дает другой результат.) Это хорошо для шеллкода, вы пытаетесь использовать одну систему сейчас, не быть ориентированным на будущее для будущих процессоров.
Если вы знаете выравнивание целевого буфера, то вы контролируете (через младшие биты указателя инструкции), к каким возможным смещениям вы можете перейти. Если буфер выровнен по 4 байта (или, более конкретно, что ваша полезная нагрузка будет в конечном итоге выровнена с 4 байтами), то только каждый 4-й байт должен быть допустимой начальной точкой для декодирования, поэтому вы можете использовать пары 2-байтовых пар. инструкции, такие как xor eax, ebx
/ add ecx, edx
.
4-байтовые инструкции включают addss xmm0, xmm1
и другие инструкции SSE1 / SSE2. Если код, который вы эксплуатируете, не работает в режиме ядра с отключенным SSE, вы обычно можете предположить, что на любом компьютере, на котором вы работаете, установлен SSE1.
Вы даже можете использовать 5-байтовую инструкцию, например mov eax, 0x90345612
, начиная с 4-байтового выровненного адреса. Обратите внимание, что последний байт непосредственного байтового числа равен 0x90
nop, так что все в порядке, если там начинается декодирование.
Насколько я понимаю, подобные методы широко используются для обхода систем обнаружения вторжений / антивирусных сканеров, которые считают длинные строки с подозрением на 0x90
. (И / или потому что 0x90
не является ASCII для печати и недопустимым UTF-8).