为什么我的C程序在二进制文件中没有jmp esp指令?

时间:2019-06-05 16:19:31

标签: c assembly gdb exploit objdump

我想利用缓冲区溢出来利用我的C程序,但是我找不到jmp esp

objdump -D ./a.out | grep jmp.*esp

这是源代码:

#include <stdio.h>

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

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

1 个答案:

答案 0 :(得分:1)

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

以为您在谈论的人的评论中有很多讨论
jmp *(%esp)ret,没有弹出。对于以后的读者,请参阅security.SE上的Why JMP ESP instead of directly jumping into the stack,以获取有关在尝试返回可执行有效负载时击败堆栈ASLR的 ret2reg 技术的更多信息。 (但不能击败不可执行的堆栈,因此在现代系统中单独使用它很少有用。)这是ROP小工具的特例。


编译器永远不会故意使用该指令,因此,您只会在其他指令的字节部分或非代码段中找到它。如果没有任何数据包含它,则根本不会。

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

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


但是即使如此,我还是使用gcc8.2禁用了优化功能(gcc -m32 foo.c来编译您的代码,并在e4的输出中搜索了hexdump -C个字节。它们之前都没有ff字节。 (我再次尝试使用gcc -m32 -no-pie -fno-pie foo.c,但仍然不起作用)

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

您可以使用全局const unsigned char jmp_esp[] = { 0xff, 0xe4 };

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

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


如果禁用库ASLR,则可以在libc中某处的已知地址处使用ff e4。但是,通过对库映射地址进行常规随机化,可以很容易地尝试直接猜测缓冲区的堆栈地址,+-用NOP幻灯片填充一些字节。 (除非您可以使要攻击的程序泄漏库地址,从而击败ASLR)。