Я прочитал несколько статей о переполнении буфера стека, например, this , и узнал, как злоумышленники могут использовать ошибку переполнения буфера стека, перезаписывая указатели функций.Затем я написал небольшую программу для демонстрации атаки:
#include <stdio.h>
#include <string.h>
void fun1 ( char * input ) {
char buffer[10];
strcpy( buffer, input );
printf( "In fun1, buffer= %s\n", buffer );
}
void fun2 ( void ) {
printf ( "HELLO fun2!\n" );
}
int main ( int argc, char * argv[] )
{
printf ( "Address of fun2: %p\n", fun2 );
fun1( "abcdefghijklmnopqrstuv\x52\x84\x04\x08" );
return 0;
}
Программа была скомпилирована с GCC 4.5.1 под Fedora 14 x86.Ниже приводится вывод:
$ ./exp01
Адрес fun2: 0x8048452
В fun1, buffer = abcdefghijklmnopqrstuvR�
ПРИВЕТ fun2!
ПРИВЕТ fun2!
Мы видим, что fun2 () был вызван успешно, но я не знаю, почему он запускался дважды.Затем я GDBed это (см. Ниже).(Я знаю только некоторые базовые инструкции о GDB ╮ ( ̄ ▽  ̄) ╭)
Я погуглил некоторые ключевые слова, такие как «__libc_csu_fini ()», но не нашел четкого способа, который мог бы помочь мне понятьпуть выполнения программы.Я слишком мало знаю о компиляторе и внутренней структуре процесса, поэтому считаю, что мне, возможно, придется найти некоторые книги или статьи, которые подробно описывают эти вещи.Любое предложение?Спасибо!
Запись GDB:
(gdb) список
7 printf ("В fun1, буфер =%s \ n ", буфер);
8}
9
10 void fun2 (void) {
11 printf (" ПРИВЕТ fun2! \ "n ");
12}
13
14 int main (int argc, char * argv [])
15 {
16 printf ("Адрес fun2:% p \ n", fun2);
(gdb)
17 fun1 ("abcdefghijklmnopqrstuv \ x52 \ x84 \ x04 \ x08");
18 return 0;
19}
(gdb) перерыв 16
Точка останова 1 в 0x804846f: файл hello.c, строка 16.
(gdb) run
Запуск программы: / home / yuliang / test / hello
Точка останова 1, главная (argc = 1, argv = 0xbffff394) в hello.c: 16
16 printf ("Адрес fun2:% p \ n", fun2);
Отсутствует отдельный debuginfos, используйте: debuginfo-install glibc-2.13-2.i686
(gdb) step
Адрес fun2: 0x8048452
17 fun1 ("abcdefghijklmnopqrstuv \ x52 \ x84 \ x04 \ x08 ");
(gdb)
fun1 (input = 0x804859a" abcdefghijklmnopqrstuvR \ 204 \ 004 \ b ") в hello.c: 6
6 strcpy (буфер, ввод);
(gdb)
7 printf ("In fun1, buffer =% s \ n", buffer);
(gdb)
В fun1, buffer = abcdefghijklmnopqrstuvR�
8}
(gdb)
fun2 () в hello.c: 10
10 void fun2 (void) {
(gdb)
11 printf ("ПРИВЕТ fun2! \ N");
(gdb)
ПРИВЕТ fun2!
12}
(gdb)
0x08048500 в __libc_csu_fini ()
(gdb)
Один шаг до выхода из функции __libc_csu_fini,
, в которой нет информации о номере строки.
fun2 () в hello.c: 10
10 void fun2 (void) {
(gdb)
11 printf ("ПРИВЕТ fun2! \ N");
(gdb)
ПРИВЕТ fun2!
12}
(gdb)
Нет доступапамять по адресу 0x76757477
(gdb)
Один шаг до выхода из функции __libc_csu_init,
без информации о номере строки.
0x009aae36 в __libc_start_main () из /lib/libc.so.6
(gdb)
Один шаг до выхода из функции __libc_start_main,
, которая не имеет информации о номере строки.
Программа завершена с кодом 0241.
(gdb)