【问题标题】:Why doesn't my C program have a jmp esp instruction in the binary?为什么我的 C 程序在二进制文件中没有 jmp esp 指令?
【发布时间】:2019-06-05 16:19:31
【问题描述】:

为什么你只能在大型应用程序中找到jmp esp

在这个小程序中你找不到jmp esp。但为什么? 这是源代码:

#include <stdio.h>

int main(int argc, char **argv)
{
    char buffer[64];

    printf("Type in something: ");
    gets(buffer);
    return 0;
}

【问题讨论】:

  • 没有 x86 机器指令的汇编符号字面意思是 jmp esp。有一条指令,其汇编符号在 Intel-ese 中为 jmp dword ptr [esp](编码为 0xFF 0x24 0x24),如果它已生成,您的 grep 会发现,但我想不出 C 编译器会在任何情况下永远生成该指令。您在哪里阅读或听说您应该查找此说明?
  • @bitfriends 这本书叫什么名字,作者是谁,出版日期是什么时候?
  • @bitfriends 这本书:rheinwerk-verlag.de/hacking-security_4382 ?
  • 谢谢。我很遗憾地说我付不起 44,90 欧元只是为了看看这本书是否真的说缓冲区溢出涉及jmp esp 指令。不过,我的猜测是,您对函数返回如何在 x86 上工作的描述有点过于字面化了。您应该寻找的指令拼写为ret
  • 如果你真的想学习如何做这样的漏洞利用,你首先需要学习目标平台的汇编语言。

标签: c assembly gdb exploit objdump


【解决方案1】:

AT&T jmp *%esp / Intel jmp esp 具有机器代码 ff e4。您应该在任何偏移量处寻找该字节序列。
(我用该指令组装了一个 .s 并使用 objdump -d 获取机器码。)

在 cmets 中有很多人认为您在谈论
jmp *(%esp) 作为ret 没有流行音乐。对于未来的读者,请参阅 security.SE 上的Why JMP ESP instead of directly jumping into the stack,了解有关此 ret2reg 技术的更多信息,该技术可在尝试返回可执行负载时击败堆栈 ASLR。 (但不能击败不可执行的堆栈,因此这在现代系统中很少单独使用。)这是 ROP 小工具的一个特例。


编译器永远不会有意使用该指令,因此您只会将它作为另一条指令的字节的一部分,或在非代码部分中找到。如果碰巧没有数据包含它,或者根本不包含它。

此外,如果确实发生,您的搜索方法可能会错过它。

objdump | grep 'jmp.*esp' 在这里不好。例如,这将错过ff e4 作为mov eax, 0x1234e4ff 的一部分。同样,数据部分的反汇编只会“检查” objdump 决定指令开始的字节。 (它不会从每个可能的字节地址开始进行重叠反汇编;它到达一条指令的末尾并假设下一条指令从那里开始。)


但即便如此,我还是使用 gcc8.2 编译了您的代码,并禁用了优化 (gcc -m32 foo.c),并在 hexdump -C 的输出中搜索了 e4 字节。它们前面都没有ff 字节。 (我又试了gcc -m32 -no-pie -fno-pie foo.c,还是没有ff e4)

没有理由期望它会出现在一个很小的可执行文件中

你可以介绍一个全局const unsigned char jmp_esp[] = { 0xff, 0xe4 };

但请注意,现代工具链(如 2018 年末/2019 年末)甚至将 .rodata 部分放在不可执行的部分中。因此,您需要使用 -zexecstack 编译非代码部分中的字节序列才能用作小工具。

但您可能需要-z execstack 或其他东西来使堆栈本身可执行,以便您的有效负载本身位于可执行页面中,而不仅仅是const 数组中的jmp esp


如果您禁用了库 ASLR,那么您可以在 libc 中某个已知地址处使用 ff e4。但是通过库映射地址的正常随机化,尝试直接猜测缓冲区的堆栈地址可能同样容易,+-一些字节你用 NOP 幻灯片填充。 (除非您可以让您正在攻击的程序泄露库地址,从而击败 ASLR)。

【讨论】:

  • @bitfriends:这是一个 gcc 选项。我说的是 compile with,而不是 debug with。另外,我的桌面有 GDB 版本 8.2.1。您在 GDB 3 中使用了哪种古老的系统?但无论如何,如果您的 GCC + ld 不是去年左右的,.section .rodata 已经链接到(可执行)文本段。但是您仍然需要-z execstack 才能使堆栈本身可执行,以便您的实际有效负载运行,而不仅仅是 ret2reg 小工具。
  • @bitfriends:这是一个非常古老的 gcc 版本。 gcc4.x 很长一段时间都是最新的,但 3 很旧。无论如何,如果你的链接器和你的编译器一样老,你不需要-z execstack 来使const 数组可执行,它已经是。 (但你的堆栈通常不会。)
猜你喜欢
  • 2013-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多