静态分配的数组和变量之间的内存差距

时间:2018-10-29 17:05:22

标签: c gcc

以下是一个玩具程序,可以抑制缓冲区溢出漏洞:

#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: ""

passwddecision之间的内存间隔为0x1c = 28个字节。还有12个字节,我无法解释它们的存在。这么长的差距有什么解释?

0 个答案:

没有答案