我想利用缓冲区溢出来利用我的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;
}
答案 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)。