На пути к пониманию двоичных файлов (разметка виртуальной памяти, выполнение... и т. д.) я написал код C
, который объявляет глобальную строку, содержащую байты исполняемого кода, затем я перезаписал адрес возврата из функции main()
на этот исполняемый код, используя простой трюк, объявляя указатель (PTR
) в main()
, который представляет собой локальную область памяти, зарезервированную в стеке 2 СЛОВА далеко от адреса возврата из main()
, поэтому все, что я делаю, это присваиваю адрес адреса возврата к этому указателю (PTR=(int*)&PTR+2)
, а затем перезаписать содержимое этого адреса адресом исполняемого кода (статической строкой).
Теперь дилемма заключается в том, что всякий раз, когда я компилирую и выполняю, я получаю ошибка сегментации. Исполняемый код не использует память input/output
(это просто набор NOPs
).
Используя GDB, я убедился, что процесс работает идеально: адрес возврата меняется на адрес строки, но возврата никогда не происходит.
Все, что я знаю, это то, что исполняемый код сопоставляется с страницы в виртуальной памяти помечены RW
(сегменты .data
и .bss
), поэтому, возможно, нет способа выполнить такое выполнение кода, если только код не вводится в область executable
памяти (страницы, помеченные RE
). Это моя теория по этому вопросу, я приглашаю вас дать более подробную информацию.
char code[]="\x90\x90\x90\x90\x90\x90\x90\x90"; //a static string contains executable code
int main()
{
int *return_address; //Pointer to the return address - uninitialized
return_address = (int *)&return_address + 2; //Initializing the return address - according to stack layout
(*return_address) = (int)code; //Overwriting the return address with the code's address
}
execstack
tool (linux.die. net/man/8/execstack; стек можно переключить на rwx; см. статью 2004 г.). ядра ›2.3 могут поддерживать PAE, но в то же время PAE может быть не включен в конфигурации ядра (во время сборки; был вариант ядра linux-generic-pae). - person osgx   schedule 30.06.2016