Ниже приводится игрушечная программа, которая предотвращает уязвимость переполнения буфера:
#include < stdio.h >
#include < string.h >
/* Returns 1 if pass is
* the correct password, otherwise 0 */
int check_correct_passwd(char * pass) {
/* Omitted */
/* Very complex logic */
return 0;
}
void print_secret_key() {
int c;
FILE * file;
file = fopen("/home/alice/master-secret.txt", "r");
if (file) {
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
} else {
printf("Failed to open master-secret.txt");
}
}
int main(int argc, char ** argv) {
int decision;
char passwd[16];
if (argc < 2) {
printf("usage: %s password\n", argv[0]);
return 0;
}
decision = check_correct_passwd(argv[1]);
strcpy(passwd, argv[1]);
printf("%d\n", decision);
printf("%s\n", argv[1]);
if (decision) {
printf("Access granted to the document with passwd %s!\n", passwd);
print_secret_key();
} else
printf("Access denied.\n");
return 0;
}
ОС - Linux 4.14.76
. Версия компилятора gcc 8.2.1
.
Я компилирую эту программу с gcc getkey.c -ggdb -fno-stack-protector -o getkey
, в основном размещает символы отладки и отключает стек канарейки.
Я ожидаю, что эта программа распечатает мастер-ключ после получения ввода, длина которого превышает 16, так как это перезапишет решение и вынудит ветвь оценить значение true. Однако требуемая длина намного больше 16. GDB показывает адреса этих переменных и их содержимое после выполнения strcpy(passwd, argv[1])
следующим образом:
(gdb) print &passwd
$17 = (char (*)[16]) 0x7fffffffe0b0
(gdb) print &decision
$18 = (int *) 0x7fffffffe0cc
(gdb) x/16b &passwd
0x7fffffffe0b0: "01234567890123456"
0x7fffffffe0c2: "\377\377\377\177"
0x7fffffffe0c7: ""
0x7fffffffe0c8: ""
0x7fffffffe0c9: ""
0x7fffffffe0ca: ""
0x7fffffffe0cb: ""
0x7fffffffe0cc: ""
0x7fffffffe0cd: ""
0x7fffffffe0ce: ""
0x7fffffffe0cf: ""
0x7fffffffe0d0: "\360RUUUU"
0x7fffffffe0d7: ""
0x7fffffffe0d8: "#\322\337\367\377\177"
0x7fffffffe0df: ""
0x7fffffffe0e0: ""
Разрыв памяти между passwd
и decision
составляет 0x1c
= 28 байт. Есть дополнительные 12 байтов, которые я не могу объяснить их существование. Чем объясняется такой большой разрыв?