AT & T jmp *%esp
/ Intel jmp esp
имеет машинный код ff e4
. Вы должны искать эту последовательность байтов при любом смещении.
(Я собрал файлы .s с этой инструкцией и использовал objdump -d
для получения машинного кода.)
В комментариях много обсуждений от людей, которые думали, что вы говорите
jmp *(%esp)
как ret
без поп. Для будущих читателей см. Почему JMP ESP вместо прямого перехода в стек на security.SE для получения дополнительной информации об этой методике ret2reg , позволяющей победить ASLR стека при попытке вернуться к исполняемой полезной нагрузке. (Но не победить неисполняемые стеки, так что это редко полезно само по себе в современных системах.) Это особый случай гаджета ROP.
Компиляторы никогда не собираются использовать эту инструкцию намеренно, поэтому вы всегда найдете ее как часть байтов для другой инструкции или в разделе без кода. Или нет, если нет данных для включения.
Кроме того, ваш метод поиска может пропустить его, если он произойдет.
objdump | grep 'jmp.*esp'
здесь нехорошо. Это будет пропустить ff e4
как часть mov eax, 0x1234e4ff
например. И разборка разделов данных аналогичным образом будет «проверять» байты только тогда, когда objdump решит, что инструкция начинается. (Он не выполняет перекрывающуюся разборку, начиная с каждого возможного байтового адреса; он достигает конца одной инструкции и предполагает, что следующая инструкция начинается там.)
Но даже в этом случае я скомпилировал ваш код с помощью gcc8.2 с отключенной оптимизацией (gcc -m32 foo.c
) и искал e4
байт в выходных данных hexdump -C
. Ни одному из них не предшествовал ff
байт. (Я попытался снова с gcc -m32 -no-pie -fno-pie foo.c
, все еще без ff e4)
Нет никаких оснований для ожидать, что появится в крошечном исполняемом файле .
Вы можете представить один с глобальным const unsigned char jmp_esp[] = { 0xff, 0xe4 };
Но обратите внимание, что современные наборы инструментов (например, в конце 2018/2019) помещают даже раздел .rodata
в неисполняемый сегмент. Поэтому вам нужно скомпилировать с -zexecstack
, чтобы последовательности байтов в не кодовых разделах были полезны в качестве гаджетов.
Но вам, вероятно, понадобится -z execstack
или что-то еще, чтобы сделать сам стек исполняемым, чтобы ваша полезная нагрузка находилась на исполняемой странице, а не просто jmp esp
в const
массиве.
Если вы отключили библиотеку ASLR, вы можете использовать ff e4
по известному адресу где-нибудь в libc. Но при обычной рандомизации адресов отображения библиотек, вероятно, так же просто попытаться угадать адрес стека вашего буфера напрямую + - некоторые байты, которые вы заполняете слайдом NOP. (Если вы не можете заставить программу, которую вы атакуете, утекать адрес библиотеки, побеждая ASLR).