在 ret2libc 攻击中,我知道返回地址可以被系统命令的地址覆盖,系统命令的地址以命令字符串作为参数。在这种情况下,命令字符串的地址不应该直接在 system() 的地址之后吗?但是,我见过的大多数教程都遵循以下格式:system() 的地址。exit() 的地址。命令字符串的地址。
为什么必须包含 exit() 的地址?如果exit() 被排除,攻击仍然有效吗?
在 ret2libc 攻击中,我知道返回地址可以被系统命令的地址覆盖,系统命令的地址以命令字符串作为参数。在这种情况下,命令字符串的地址不应该直接在 system() 的地址之后吗?但是,我见过的大多数教程都遵循以下格式:system() 的地址。exit() 的地址。命令字符串的地址。
为什么必须包含 exit() 的地址?如果exit() 被排除,攻击仍然有效吗?
ret2libc(和面向返回的编程 (ROP))技术依赖于覆盖堆栈来创建调用系统函数的新堆栈帧。这篇维基百科文章非常详细地解释了堆栈帧:https : //en.wikipedia.org/wiki/Call_stack#Stack_and_frame_pointers
堆栈帧指示函数调用和参数的写入顺序:
function address
return address
parameters
因此,在你比如你要打电话system()
与cmdstring
和返回exit()
功能,当system()
调用返回。因此,您编写了以下堆栈帧:
system_addr
exit_addr
cmdstring_addr
如果删除退出地址,则会将堆栈帧更改为以下内容:
system_addr
cmdstring_addr
existingdataonstack_aka_junk
因此,现在您使用system()
垃圾地址参数进行调用,并在函数完成后尝试返回您的命令字符串。这就是它失败的原因。您可以将exit()
地址替换为其他数据,例如 调用完成0x41414141
后将导致segfault
的地址。system()
或者你可以用一个位置的地址替换它,pop pop ret
然后在下面写更多的堆栈帧。现在这是一个ROP
有效载荷。这是堆栈上的外观的基本示例:
system_addr
poppopret_addr
cmdstring_addr
printf_addr
exit_addr
addr_of_string_to_printf
这将允许您You got hacked
在退出之前打印类似的内容。
包括在内的原因exit()
是为了优雅地终止程序。如果您exit()
在链的末尾没有,程序将继续奇怪地运行,或者很可能以分段错误终止。包含对 的调用不是强制性的exit()
。理想情况下,您将以这样一种方式构建您的漏洞利用程序,之后程序继续照常运行,因此没有人会因为他们的服务不再运行而产生怀疑。