У меня есть простая программа, которая инициализирует строку стиля ac, а затем инициализирует символ.Затем я использую функцию strcpy
, чтобы вызвать ситуацию переполнения буфера, которая, казалось бы, перезаписывает содержимое памяти символьной переменной x
(при условии, что она хранится в смежной памяти).
char str[] = "Testt";
char x = 'X';
// print address and value of str
printf("%p: ", &str);
printf("%s\n", str);
// print value of x
printf("%c\n", x);
// cause buffer overflow
strcpy(str, "Hello world");
// print address and value of str
printf("%p: ", &str);
printf("%s\n", str);
// print address and value of x
// printf("%p: ", &x);
printf("%c\n", x);
return 0;
При запуске,этот код производит вывод, который выглядит как
0061FF29: Testt
X
0061FF29: Hello world
w
Эта ситуация показывает, что переполнение буфера действительно произошло, и это привело к изменению значения переменной x
с 'X'
на 'w'
.
Однако, если я удаляю прокомментированный // printf("%p: ", &x);
в строке с третьей по последнюю, переполнение буфера не приводит к перезаписи переменной x
.
Для ясности вот этот код (обратите вниманиеизменение с третьей на последнюю строку)
char str[] = "Testt";
char x = 'X';
// print address and value of str
printf("%p: ", &str);
printf("%s\n", str);
// print value of x
printf("%c\n", x);
// cause buffer overflow
strcpy(str, "Hello world");
// print address and value of str
printf("%p: ", &str);
printf("%s\n", str);
// print address and value of x
printf("%p: ", &x);
printf("%c\n", x);
return 0;
Это приводит к выводу:
0061FF2A: Testt
X
0061FF2A: Hello world
0061FF29: X
Так что в этой ситуации переполнение буфера не перезаписывало переменную x
,
Почему простая печать адреса памяти переменной x
влияет на ситуацию переполнения буфера?
edit: добавлено в сборку для двух ситуаций.сгенерированная сборка для первого случая (без printf):
.file "hello.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "%p: \0"
LC1:
.ascii "%c\12\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB17:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
movl $1953719636, 25(%esp)
movw $116, 29(%esp)
movb $88, 31(%esp)
leal 25(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
leal 25(%esp), %eax
movl %eax, (%esp)
call _puts
movsbl 31(%esp), %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
leal 25(%esp), %eax
movl $1819043144, (%eax)
movl $1870078063, 4(%eax)
movl $6581362, 8(%eax)
leal 25(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
leal 25(%esp), %eax
movl %eax, (%esp)
call _puts
movsbl 31(%esp), %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE17:
.ident "GCC: (MinGW.org GCC-6.3.0-1) 6.3.0"
.def _printf; .scl 2; .type 32; .endef
.def _puts; .scl 2; .type 32; .endef
и для второго случая
.file "hello.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "%p: \0"
LC1:
.ascii "%c\12\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB17:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
movl $1953719636, 26(%esp)
movw $116, 30(%esp)
movb $88, 25(%esp)
leal 26(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
leal 26(%esp), %eax
movl %eax, (%esp)
call _puts
movzbl 25(%esp), %eax
movsbl %al, %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
leal 26(%esp), %eax
movl $1819043144, (%eax)
movl $1870078063, 4(%eax)
movl $6581362, 8(%eax)
leal 26(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
leal 26(%esp), %eax
movl %eax, (%esp)
call _puts
leal 25(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _printf
movzbl 25(%esp), %eax
movsbl %al, %eax
movl %eax, 4(%esp)
movl $LC1, (%esp)
call _printf
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE17:
.ident "GCC: (MinGW.org GCC-6.3.0-1) 6.3.0"
.def _printf; .scl 2; .type 32; .endef
.def _puts; .scl 2; .type 32; .endef