Я работаю над переполнением стекового буфера на Protostar, и моя конечная цель - лучше понять, что происходит. Я нахожусь на упражнении 4 (https://exploit.education/protostar/stack-four/). Я получил переполнение буфера для выполнения желаемой функции, но я могу сделать это только в GDB. Причина, по которой я могу сделать это только в gdb, заключается в том, что второе слово после конца буфера, который я использую, содержит адрес памяти arg c. Если это второе слово будет перезаписано, то вызов функции не будет работать. Я скомпилировал с опцией -fno-stack-protector.
В gdb я запустил:
run <<< (echo -e "$(python -c "print('h'*64)")aaaa\xa0\xf0\xff\xbfaaaaaaaaaaaaaaaaaaaa\x3b\x84\x04\x08\x37\x16\xe2\xb7")
64 часа заполнили буфер, первые четыре a просто переполнили слово, следующий четыре байта являются адресом аргумента c, следующие 5 слов (20 а) просто переполняются. Затем я помещаю адрес win (функция, которую я хочу вызвать), а затем старый адрес возврата, чтобы выйти без segfault.
Когда я запускаю это в gdb, я вызываю функцию win, и процесс завершается. Когда я запускаю это за пределами GDB, я получаю segfault. Я подумал, что, возможно, переменные окружения были разными, но это не тот случай, когда я изменил переменные окружения в gdb так, чтобы они точно совпадали с тем, что есть у меня вне gdb, и он все еще не работает.
7 слов после Конец буфера и до адреса возврата: 1: 0xb7fbb300 - Неизвестно 2: 0xbffff0a0 - адрес argc 3: 0x00000000 - пусто 4: 0xb7e21637 - Адрес возврата, но не фактический, который имеет значение. (не знаю, почему их два) 5: 0xb7fbb000 - Неизвестно 6: 0xb7fbb000 - Неизвестно 7: 0x00000000 - Неизвестно
Итак, мои вопросы: почему это работает только в gdb? и каково значение адреса arg c для предотвращения segfault? И почему я вижу обратный адрес дважды? Один раз на 4-м слове после буфера и снова на 8-м слове после буфера.