为什么作为函数参数给出的字符串地址在溢出 ret 地址后发生变化?
我想通过控制堆栈来利用 C 代码段的漏洞来实现教育目的。一个简单的基于堆栈的缓冲区溢出,用应该执行 shellcode 的地址覆盖返回地址。该代码是一个简单的函数,它接受一个缓冲区作为参数,并尝试将缓冲区转换为固定大小。 main 给出的参数是argv[1]
。所以我认为,如果我找到了必须覆盖的确切内存量,那么我可以简单地给出一个由 \x90
(NOP 指令)组成的字符串作为输入,后跟 shellcode,最后是该缓冲区的地址。由于这是第一个参数,因此它的地址是 $ebp+8
,您可以通过运行 gdb
找到它,在函数的开头设置一个断点,然后键入 i args
给出作为参数传递的字符串的地址。所以我发现,如果我覆盖 n 个字节,然后给出地址的值,那么这将完全覆盖返回地址。所以我有这样的输入:
perl -e print(\x90 x n-sizeof(shellcode) . shellcode . address)'
它不起作用,我试图理解为什么。我使用 gdb 运行该程序。我在 strcpy()
函数之前放置了一个断点。此时我有一个参数,它是一个指向我的输入的字符串指针,它的地址与我的字符串输入末尾给出的地址相同,我向前迈了 1 条指令。我检查了堆栈。我现在已经保存了 eip
($ebp + 4
),其地址值在 argv[1]
末尾给出,其中是预期的行为(这意味着它不会覆盖第一个参数值 ret 地址之上的其他地址)。奇怪的是,现在 $ebp+8
的内容不是“地址”而是其他东西?但保存的eip
内容是指向我利用该漏洞的字符串的地址。但ret addr似乎并没有执行该地址的内容。
I want to exploit a vulnerability of a C piece of code for educational purposes by controlling the stack. A simple stack based buffer overflow, overwriting the return address with the address where a shellcode should be executed. The code is a simple function which takes as arguments a buffer and tries to strcpy()
the buffer into a fixed size. The parameter given from main is the argv[1]
. So I think that if I found the exact amount of memory that I have to overwrite then I could simply give as input a string composed by \x90
(NOP instructions) followed by the shellcode and in the end the address of this buffer. Since this is the first argument its address is $ebp+8
and you can find this by running gdb
, set a breakpoint in the begining of the function and just type i args
gives you the address of the string which is passed as an argument. So I found that if I overwrite n
bytes and then give the values of the address then this will exactly overwrite the return address. So I have an input like this:
perl -e print(\x90 x n-sizeof(shellcode) . shellcode . address)'
It didn't work and I tried to understand why. With gdb
I run the program. I put a breakpoint before the strcpy()
function. At that point I have an argument which is a string pointer that points to my input and its address is the same with that given at the end of my string input, I stepped forward 1 instruction. I examined the stack. I have now the saved eip
($ebp + 4
) with the value of the address given at the end of argv[1]
, which is the expected behavior (That implies that it doesn't overwrite other addresses above the ret address that is the value of the first argument). The weird thing is that now the content of $ebp+8
is not the "address" but something else? But the content of the saved eip
is the address that points to my string that exploits the vuln. But it doesn't seem that the ret addr executes the content of that address.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
堆栈帧的组织方式是 ABI 的一部分。 x86-64 上的 Linux 使用的 ABI 的说明位于此处。您会在那里找到您需要的一切(可能还有更多)。栈帧的组织方式参见3.2节。
How stack frames are organized is part of the ABI. The description of the ABI used by Linux on x86-64 is here. You'll find there everything that you need (and then some more probably). See section 3.2 for the stack frame organization.