c - 缓冲区溢出困境

标签 c security buffer-overflow

因此,我试图对这段代码执行缓冲区溢出,目的是将变量 target 更改为“Y”。问题是,我似乎无法让缓冲区溢出到足以产生运行时错误的程度。谁能帮我理解为什么?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

enum {SIZE = 50};

char target = 'Z';
char name[SIZE];
FILE *f;

void read(char *s) {
   char buffer[SIZE];
   int i = 0; 
   int c;

   for (;;) 
   {
      c = getchar();
      if ((c == EOF) || (c == '\n')) 
         break;
      buffer[i] = c;
      i++;
   }
   buffer[i] = '\0';

   for (i = 0; i < SIZE; i++) 
      s[i] = buffer[i];
}


int main(void) 
{
   read(name);

   if (strcmp(name, "ABCD") == 0) 
      target = 'Y';

   printf("%s\n", name);
   printf("%c\n", target);

   exit(0);
}

最佳答案

如果您尝试使用更改后的返回地址执行此操作,则需要用您想要的特定地址覆盖它。在这种情况下,为了获得所需的结果,您可以使用代码 target = 'Y';

的地址进行覆盖

根据堆栈的组织方式,您可以直接破坏 read() 的返回地址,这将使您返回到 main 的第一行之后> 它被调用的地方。如果做不到这一点,您就有机会破坏 i,这将使您可以任意写入内存。写入这些字节时需要小心,因为它会影响索引。

我假设这是在 ARM 上完成的,因为我更熟悉他们的堆栈布局和调用约定。所以,你的堆栈看起来像这样:

STACKPTR-60: buffer[0]
 |   |   |
STACKPTR-11: buffer[49]
STACKPTR-10: padding
STACKPTR -9: padding
STACKPTR -8: i (bits 7..0)
 |   |   |
STACKPTR -5: i (bits 31..24)
STACKPTR -4: c (bits 7..0)
 |   |   |
STACKPTR -1: c (bits 31..24)
STACKPTR +0: link register (return address) (bits 7..0)
 |   |   |
STACKPTR +3: link register (return address) (bits 31..24)

因此,对于这种堆栈布局,当您溢出 buffer 时,您将首先填充两个填充字节。之后,填充i 的最低有效字节。在这种情况下,您可以跳过巨大的溢出,只需修改您的索引以指向堆栈链接寄存器。你希望 i=60 开始写入返回地址,但是在你写入之后,它会递增,所以你真的想要 i=59,这将是增加到 i=60。此时,您可以从最低位到最高位写入所需的返回地址,然后是 EOF\n

真正重要的是要注意,这完全是特定于体系结构和特定于编译器的。编译器设置将决定 int 的大小,是否填充堆栈以对齐变量,以及变量在堆栈中出现的顺序。该架构将决定您的堆栈框架的外观。

关于c - 缓冲区溢出困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23494685/

相关文章:

用 C 创建 ADT 集

c++ - Arduino中断频率

C 使用 lseek/read/write 删除大型二进制文件的一部分

php - 没有HTTPS登录,如何安全?

mysql - 不检查数据类型的安全问题

firebase - 如何限制每个用户可以上传到 Firebase 存储的存储量?

c - 主机上的本地用户如何使用缓冲区溢出攻击来获得对主机的根访问权限?

c - 这个程序如何创建僵尸进程?

c - 如何修复 GDB 可能的字符集问题 NOP 0x90 转换为内存中的 0x90c2?

c - 缓冲区溢出,调用函数