【问题标题】:A buffer overflow attack on Windows results in access violationWindows 上的缓冲区溢出攻击导致访问冲突
【发布时间】:2011-04-10 19:41:07
【问题描述】:

我刚开始研究buffer overflow 攻击的工作原理,并尝试使用 Visual C 2010 在 Windows 7 上模拟攻击。缓冲区溢出攻击非常人为,它只是将返回地址覆盖为“缓冲区”局部变量的地址。缓冲区保存 shellcode 字符串。

无论我是否在 Visual Studio 2010 Debug 中运行程序,程序都会跳转到 shellcode 并几乎开始执行它,但我得到一个访问冲突错误,程序不会继续执行shellcode。

为什么会出现此错误?这是对 Windows 中缓冲区溢出的某种保护吗?

如何让程序执行缓冲区中的shellcode?​​p>

编辑:

汉斯(答案)是正确的。这在 Windows Internals 5th 的安全章节中进行了讨论,错误的原因是微软对Executable Space Protection 的实现。

如果这个问题对任何人有帮助,我们将不胜感激。

void execute_my_shellcode()
{
    char buffer[24];
    memcpy(buffer, "\x6A\x21\xFF\x15\x40\x62\x40\x00\x83\xC4\x04\x6A\x0A\xFF\x15\x40\x62\x40\x00\x83\xC4\x04\xC3", 24); 
    printf("current return address: %p\n", *(int*)((char*)&buffer + 24 + 4));   
    *(int*)((char*)&buffer + 24 + 4) = (int)&buffer; 
    printf("return address is now : %p\n\n", (int*)*(int*)((char*)&buffer + 24 + 4) );
}

【问题讨论】:

  • 一旦您解决了 NX 问题,您能否帮我一个忙,并发布在可执行文件本身启用 ASLR 的情况下运行可执行文件时会发生什么?

标签: c security shellcode


【解决方案1】:

这在 10 年前可能有效。这些明显的安全漏洞已经被修补,现在处理器支持的no-execute bit就是对策之一。

【讨论】:

  • 不,还没有打补丁,他们已经解决了。
  • 呃,是的,C 数组将永远被破坏。
  • Hans,那么当我收到此访问冲突异常(在 Visual Studio 调试模式下)时,使用了哪种形式的保护?是不执行位还是其他?这是特定于 Windows 的吗?
  • 您要求的详细信息只有坐在您机器前 3 英尺的人才能真正回答。我什至不知道你使用的是什么 Windows 版本。不知道为什么重要,NX 位还不够吗?
  • NX 位肯定对我有帮助,但我不知道这是否是这种情况的答案,我只是在寻找可能用于这种情况的保护形式,因为理解的目的,而不是测试 SO 社区的知识。我使用的是Windows 7,程序编译到Win32平台。
【解决方案2】:

还有其他针对缓冲区溢出攻击的保护措施可能无法实现,例如在堆栈帧的每个开始和结束处设置保护页面。有地址空间布局随机化等。 Here 是关于此的文章。

事实上,您的 shellcode 可能包含 nullbytes 或其他类型的无效字符,这些字符在转换后不会变成指令或有效地址...这是您自己弄清楚的。

注意我不会给后一个建议被滥用。您有责任合法地正确使用此建议。

【讨论】:

    【解决方案3】:

    首先,你的 shellcode 中有空值。回到你的 shellcode 并找到不产生空操作码 (0x00) 的指令,这样你的 shellcode 就不会被视为字符串。

    其次,访问冲突并不一定意味着它是某种保护方案的原因。可能(一时兴起)您的返回地址或 shellcode 试图使 EIP 寄存器跳转到内存中无法执行的位置。

    您将不得不过期更多。每个编译器和计算机都会有所不同。几乎所有事情都有办法。一般来说,您可能想对该主题进行更多研究,但我建议的第一件事是创建一个重复的返回地址,该地址指向 shellcode 之前缓冲区中的 NOP sled,以便您的 shellcode 更有效地执行并且可能更多准确。

    正如您所说,可执行空间保护是正确的,但我上面的回答在大多数情况下都是非正式的和必要的。快乐的黑客:)

    【讨论】:

      【解决方案4】:

      程序究竟在哪里中断?您是否尝试过使用OllyDbg 逐步执行汇编指令以查看您是否至少开始执行缓冲区或在此之前失败?如果您甚至没有执行缓冲区中的第一条指令,那么很可能堆栈页面(或本例中的数据部分,因为您将其作为字符串文字提供)已被标记为不可执行,您将不得不使用另一种技术.可能有一种方法可以告诉 Windows 使堆栈页面可执行(或在这种情况下为数据部分)以用于测试/学习目的(我知道 ELF 二进制文件具有可执行堆栈标志,Linux 提供了 execstack 实用程序来编辑标志) .

      如果它在您的缓冲区中的几条指令后中断,那么很可能是因为您的缓冲区中的指令试图(间接)调用绝对地址(0xff 0x15 0x40 0x62 0x40 x00 => call dword ptr ds:[406240])并且在 W7 中,address space layout randomization( ASLR) 可能已启用(我不确定 VS2010 链接器是否默认设置了 PE 标头中的 IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 位)。

      编辑

      根据您添加到问题中的其他信息,我在第一段中提到的不可执行堆栈的问题似乎是罪魁祸首。但是,即使您解决了第二个问题,也可能仍然是个问题,因为您不知道如果启用了 ASLR,0x00406240 会发生什么。

      【讨论】:

      • 我在问题中添加了一个“澄清编辑”,这可能会有所帮助。
      • @T. Webster 最后一个澄清:第一条指令(0x6a 0x21 => push 21)失败了?此外,假设 0x00406240 是 puts 的导入地址表中的正确地址,此代码也不会正确调用 putsputs 采用单个 char* 参数,您首先将其提供为 0x21,第二次提供为 0x0a。这意味着puts 将尝试输出位于内存地址 0x00000021 的字符串。您可能想要的是 putchar,它采用单个 32 位字符而不是 char*
      • 啊对,我的意思是putchar。 0x21 是字符“!”。你的回复很有帮助,所以我投了赞成票。
      • 地址空间布局随机化 (ASLR) 似乎不是这里的问题。我是直接将buffer[]的地址值存入栈的返回地址位置。
      • -1 他正在获取&buffer 的实际地址,因此ASLR 在这种情况下无效。
      猜你喜欢
      • 2011-11-12
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 2021-02-25
      • 1970-01-01
      • 2019-10-23
      • 2021-06-15
      • 1970-01-01
      相关资源
      最近更新 更多