Почему моя программа на C не имеет инструкции jmp esp в двоичном файле? - PullRequest
0 голосов
/ 05 июня 2019

Я хочу использовать мою программу на C с переполнением буфера, но я не могу найти jmp esp.

objdump -D ./a.out | grep jmp.*esp

Это исходный код:

#include <stdio.h>

int main(int argc, char **argv)
{
    char buffer[64];

    printf("Type in something: ");
    gets(buffer);
    return 0;
}

1 Ответ

1 голос
/ 06 июня 2019

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).

...