gpt4 book ai didi

c - 跳进argv?

转载 作者:太空狗 更新时间:2023-10-29 11:11:30 25 4
gpt4 key购买 nike

我正在试验 shellcode 并偶然发现了 nop-slide 技术。我写了一个小工具,它将缓冲区大小作为参数并构造一个像这样的缓冲区:[ NOP | SC | RET ],NOP 占据缓冲区的一半,然后是 shellcode,其余部分填充(猜测的)返回地址。它与他著名论文中描述的工具 aleph1 非常相似。

我的易受攻击的测试应用程序与他的论文中的相同:

int main(int argc, char **argv) {
char little_array[512];
if(argc>1)
strcpy(little_array,argv[1]);
return 0;
}

我测试了它,很好,它有效:

jth@insecure:~/no_nx_no_aslr$ ./victim $(./exploit 604 0)
$ exit

但老实说,我不知道为什么。好的,保存的 eip 按预期被覆盖,但我认为它没有跳入缓冲区的某个地方,而是跳入了 argv。

gdb 在 调用 strcpy() 之前显示了以下地址:

(gdb) i f  
Stack level 0, frame at 0xbffff1f0:
eip = 0x80483ed in main (victim.c:7); saved eip 0x154b56
source language c.
Arglist at 0xbffff1e8, args: argc=2, argv=0xbffff294
Locals at 0xbffff1e8, Previous frame's sp is 0xbffff1f0
Saved registers:
ebp at 0xbffff1e8, eip at 0xbffff1ec

little_array 的地址:

(gdb) print &little_array[0]
$1 = 0xbfffefe8 "\020"

strcpy() 之后:

(gdb) i f
Stack level 0, frame at 0xbffff1f0:
eip = 0x804840d in main (victim.c:10); saved eip 0xbffff458
source language c.
Arglist at 0xbffff1e8, args: argc=-1073744808, argv=0xbffff458
Locals at 0xbffff1e8, Previous frame's sp is 0xbffff1f0
Saved registers:
ebp at 0xbffff1e8, eip at 0xbffff1ec

那么,这里发生了什么?我用了一个604字节的buffer来溢出little_array,所以他当然覆盖了saved ebp,saved eip和argc还有argv,猜测的地址是0xbffff458。

然后返回后,EIP指向0xbffff458。但是little_buffer位于0xbfffefe8处,相差1136字节,所以他肯定不是在执行little_array。我跟随 stepi 命令执行,好吧,在 0xbffff458 及以后,他执行 NOP 并到达 shellcode。

我不太清楚为什么会这样。首先,他在 argv 而不是 little_array 中执行我的 shellcode 是否正确?加载程序(?)在哪里将 argv 放到堆栈上?我以为它紧跟在argc之后,但是在argc和0xbffff458之间,有620字节的差距。他怎么可能成功地“降落”在地址 0xbffff458 的 NOP-Pad 中,这个地址远高于保存在 0xbffff1ec 的 eip?

有人可以澄清一下吗?我实际上不知道为什么会这样。我的测试机器是没有 ASLR 的 Ubuntu 9.10 32 位机器。受害者有一个可执行堆栈,用 execstack -s 设置。

提前致谢。

最佳答案

首先,绘制堆栈图。

0xBFFFF4F9 |          |            ----------          ...   0xBFFFF29E |    NOP   |0xBFFFF29D |    NOP   | argv[1]   * guestimate            ----------0xBFFFF29C |   '\0'   |          ...0xBFFFF295 |    '/'   |0xBFFFF294 |    '.'   | argv[0] "./victim"            ----------          ...             ----------0xBFFFF1F8 |   NULL   |0xBFFFF1F8 | &argv[1] |0xBFFFF1F4 | &argv[0] | argv            ---------- 0xBFFFF1F0 | 0x000002 | argc            ----------           ...0xBFFFEFE9 |          |0xBFFFEFE8 |          | little_array            ----------

(注意:在图中,一些框每行包含 1 个字节,其他框则为 4 或 8 个,具体取决于内部存储的类型)

And where does the loader(?) place argv onto the stack?

argcargv 在调用 strcpy 后被覆盖表明它们可能在 little_array 之上。我将它们放在 0xBFFFF1F0,因为那是前一帧的堆栈结束的地方,而且 main 的帧似乎没有空间,即使 GDB 说 arglist 位于 0xBFFFF1E8。它在我的系统上撒谎——argcargv 在 little_array 之下。尝试使用 p &argvp &argc 来确定它们的放置位置。

由于 0xBFFFF458 在 argv[1] 中,argv[1] 中的 shellcode 确实将被执行,而不是 little_array 中的。由于 shell 代码有两份副本(一份在 little_array 中,另一份在 argv[1] 中),因此可以执行任何一个,具体取决于您猜测的返回地址。

I thought [argv] follows immediately after argc, but between argc and 0xbffff458, there is a gap of 620 bytes.

0xBFFFF458 是 存储在 argv 中的值(注意 argc(signed)0xBFFFF458 相同) == -1073744808)。之前,argv 包含 0xbffff294。在这两种情况下,argv 本身都存储在别处。

关于c - 跳进argv?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2750132/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com