Разрыв памяти между статически распределенным массивом и переменной - PullRequest
0 голосов
/ 29 октября 2018

Ниже приводится игрушечная программа, которая предотвращает уязвимость переполнения буфера:

#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 байтов, которые я не могу объяснить их существование. Чем объясняется такой большой разрыв?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...