Я пишу возврат к libc атаке для класса моей системы безопасности. Во-первых, уязвимый код:
//vuln.c
#include <stdio.h>
#include <stdlib.h>
int loadconfig(void){
char buf[1024];
sprintf(buf, "%s/.config", getenv("HOME"));
return 0;
}
int main(int argc, char **argv){
loadconfig();
return 0;
}
Я хочу использовать возврат к libc атаке. Компиляция и отладка программы:
$ gcc -g -fno-stack-protector -o vuln vuln.c
$ gdb vuln
(gdb) break loadconfig
(gdb) run
Reached breakpoint blah blah blah.
(gdb) p $ebp
$1 = (void *) 0xbfffefb0
(gdb) p system
$2 = {<text variable, no debug info>} 0x0016db20 <system>
(gdb) p exit
$3 = {<text variable, no debug info>} 0x001639e0 <exit>
(gdb) x/2000s $esp
...
0xbffff5af: "SHELL=/bin/bash"
Чтобы выполнить атаку, я хочу переполнить буфер в адрес возврата loadconfig
(он же $esp+4
), заменив его адресом возврата для system
, затем адресом возврата для exit
(так как system
ожидает реальный адрес возврата), затем имя команды (адрес SHELL=/bin/bash
плюс 6, чтобы обрезать часть SHELL=
). Это должно быть возможно путем создания переменной среды $HOME
из 1024 символов дерьма, а затем адреса с прямым порядком байтов system
, exit
и /bin/bash
.
Однако на каждом компьютере, который я пробовал, system
загружается по адресу, начинающемуся с 0x00, что приведет к завершению строки, которую sprintf
читает, и остановит атаку мертвой. Есть ли способ заставить libc
загружаться в другое место в памяти, или я неправильно истолковываю атаку?
Для справки, я использую виртуальную машину Ubuntu Server 11.10 в VirtualBox (хост Windows) с gcc
версия 4.6.1 и gdb
версия 7.3-2011.08. редактирование: ASLR отключен, и я скомпилировал с -fno-stack-protector
, чтобы удалить канарейку. Поскольку я ничего не выполняю из стека, мне не нужно execstack
.