Читаем Защита от хакеров корпоративных сетей полностью

После завершения работы над фрагментом управляющего кода следует решить вопрос о передачи ему управления из программы переполнения буфера. Для этого нужно подменить сохраненное в стеке значение регистра EIP на адрес управляющего кода. Когда функция bof уязвимой программы попытается вернуться в функцию main по команде ret, она восстановит из стека сохраненное там значение регистра EIP и по команде перехода jmp перейдет по восстановленному адресу. Но где в памяти будет расположен управляющий код? Конкретнее, на какой адрес нужно подменить содержимое регистра EIP, сохраненное в стеке?

При помощи функции fread данные из файла считываются в размещенный в стеке восьмибайтовый буфер buffer. Известно, что программный код полезной нагрузки в конечном счете будет загружен из файла в стек. В UNIX-подобных системах во всех программах стек начинается с одного и того же адреса. Поэтому последнее, что осталось сделать, – это написать программу определения смещения области размещения программного кода полезной нагрузки в стеке относительно его начала.

Перед завершением своей работы функция передает вызвавшей ее программе код возврата в регистре EAX, чтобы та знала об успешном или неуспешном выполнении функции. Чтобы узнать ассемблерную реализацию фрагмента программы, отвечающего за передачу кода завершения, оттранслируем и дизассемблируем следующую программу:

$ cat ret.c

int main

{

return(0);

}

$ gcc ret.c -o ret

$ gdb ./ret

(gdb) disas main

Dump of assembler code for function main:

0x8048430

: push %EBP

0x8048431 : mov %ESP,%EBP

0x8048433 : mov $0x0,%EAX <– here it is :)

0x8048438 : pop %EBP

0x8048439 : ret

0x804843a : mov %ESI,%ESI

0x804843c : nop

0x804843d : nop

0x804843e : nop

0x804843f : nop

End of assembler dump.

(gdb)

Далее, вместо выполнения оператора возврата return (значение) пропустим его и перепишем значение ESP в регистр EAX. Таким способом значение регистра ESP может быть назначено переменной. Вот пример программы, отображающей содержимое регистра ESP:

–get_ESP.c–

unsigned long get_ESP(void)

{

__asm__(“movl %ESP,%EAX”);

}

int main

{

printf(“ESP: 0x%x\n”, get_ESP);

return(0);

}

–get_ESP.c–

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже