Leaking libc address with ROP
从零开始学习AWS黑客技术,成为专家 htARTE(HackTricks AWS Red Team Expert)!
支持HackTricks的其他方式:
如果您想在HackTricks中看到您的公司广告或下载PDF格式的HackTricks,请查看订阅计划!
探索PEASS Family,我们的独家NFT收藏品
加入 💬 Discord群 或 电报群 或在Twitter上关注我们 🐦 @hacktricks_live。
通过向HackTricks和HackTricks Cloud github仓库提交PR来分享您的黑客技巧。
快速总结
找到溢出的偏移量
找到
POP_RDI机关、PUTS_PLT和MAIN机关使用前述机关泄漏puts或其他libc函数的内存地址并找到libc版本(下载地址)
利用库,计算ROP并利用它
其他教程和二进制文件以供练习
本教程将利用此教程中提出的代码/二进制文件进行利用:https://tasteofsecurity.com/security/ret2libc-unknown-libc/ 其他有用的教程:https://made0x78.com/bseries-ret2libc/,https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
代码
文件名:vuln.c
#include <stdio.h>
int main() {
char buffer[32];
puts("Simple ROP.\n");
gets(buffer);
return 0;
}ROP - 泄露 LIBC 模板
下载 exploit 并将其放置在易受攻击的二进制文件相同的目录中,并向脚本提供所需的数据:
Leaking libc - template1- 查找偏移量
在继续利用之前,模板需要一个偏移量。如果未提供任何偏移量,它将执行必要的代码来查找它(默认为 OFFSET = ""):
执行 python template.py 会打开一个 GDB 控制台,程序会崩溃。在该 GDB 控制台 中执行 x/wx $rsp 以获取将要覆盖 RIP 的 字节。最后在 python 控制台中获取 偏移量:

在找到偏移量(在本例中为40)后,使用该值更改模板中的OFFSET变量。
OFFSET = "A" * 40
另一种方法是使用:pattern create 1000 -- 执行直到ret -- 从 GEF 中执行 pattern seach $rsp。
2- 查找Gadgets
现在我们需要在二进制文件中找到ROP gadgets。这些ROP gadgets将有助于调用puts来查找正在使用的libc,并稍后启动最终的攻击。
PUTS_PLT 用于调用 puts 函数。
MAIN_PLT 用于在一次交互后再次调用 主函数 以便再次 利用 溢出(无限次利用)。它用于在每个 ROP 结尾处再次调用程序。
POP_RDI 用于向被调用函数 传递 参数。
在这一步中,您无需执行任何操作,因为在执行过程中 pwntools 将找到一切。
3- 查找 libc 库
现在是时候找出正在使用的 libc 库的版本。为此,我们将 泄漏 内存中 puts 函数 的 地址,然后我们将 搜索 puts 版本所在的库版本。
为了做到这一点,执行的代码中最重要的一行是:
这将发送一些字节,直到覆盖 RIP 可能为止:OFFSET。
然后,它将设置gadget POP_RDI的地址,以便下一个地址(FUNC_GOT)将被保存在RDI寄存器中。这是因为我们想要调用 puts 并将PUTS_GOT的地址作为参数传递给它,因为内存中 puts 函数的地址保存在PUTS_GOT指向的地址中。
之后,将调用PUTS_PLT(带有PUTS_GOT在RDI中),因此 puts 将读取PUTS_GOT中的内容(内存中 puts 函数的地址)并将其打印出来。
最后,再次调用 main 函数,以便我们可以再次利用溢出。
这样,我们已经欺骗 puts 函数将打印出puts函数的内存中的地址(位于libc库中)。现在我们有了该地址,我们可以查找正在使用的 libc 版本。

由于我们正在利用一些本地二进制文件,不需要弄清楚正在使用的libc版本(只需在/lib/x86_64-linux-gnu/libc.so.6中找到该库)。
但是,在远程利用案例中,我将在这里解释如何找到它:
3.1- 搜索 libc 版本(1)
您可以在网页上搜索正在使用的库:https://libc.blukat.me/ 它还将允许您下载发现的libc版本

3.2- 搜索 libc 版本(2)
您也可以执行以下操作:
$ git clone https://github.com/niklasb/libc-database.git$ cd libc-database$ ./get
这将需要一些时间,请耐心等待。 为了使其工作,我们需要:
Libc 符号名称:
puts泄漏的 libc 地址:
0x7ff629878690
我们可以找出最有可能使用的libc。
我们得到2个匹配项(如果第一个不起作用,您应该尝试第二个)。下载第一个:
3.3- 泄漏的其他函数
将libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so中的libc复制到我们的工作目录。
4- 寻找基于libc的地址并利用
在这一点上,我们应该知道使用的libc库。由于我们正在利用一个本地二进制文件,我将仅使用:/lib/x86_64-linux-gnu/libc.so.6
因此,在template.py的开头将libc变量更改为:libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #Set library path when know it
给出libc库的路径,其余的利用将自动计算。
在get_addr函数内,将计算libc的基地址:
请注意,最终的libc基址必须以00结尾。如果不是这种情况,您可能已经泄漏了一个不正确的库。
然后,函数system的地址和字符串_"/bin/sh"_的地址将从libc的基地址中计算出来,并给出libc库。
最后,将准备发送/bin/sh执行利用程序:
让我们解释这个最终的ROP。
最后一个ROP (rop1) 结束时再次调用了 main 函数,然后我们可以再次利用溢出(这就是为什么 OFFSET 再次出现在这里)。然后,我们想要调用 POP_RDI 指向 "/bin/sh" 的地址(BINSH),并调用 system 函数(SYSTEM),因为 "/bin/sh" 的地址将作为参数传递。
最后,调用 exit 函数的地址,以便进程正常退出,不会生成任何警报。
这样,利用程序将执行一个 _/bin/sh_** shell。**

4(2)- 使用 ONE_GADGET
您还可以使用 ONE_GADGET 来获取一个 shell,而不是使用 system 和 "/bin/sh"。ONE_GADGET 将在 libc 库中找到一种方法,只需一个 ROP 地址即可获取一个 shell。
然而,通常会有一些约束条件,最常见且易于避免的是 [rsp+0x30] == NULL。由于您可以控制 RSP 中的值,因此只需发送一些额外的 NULL 值,就可以避免这个约束条件。

EXPLOIT FILE
您可以在这里找到利用此漏洞的模板:
Leaking libc - template常见问题
MAIN_PLT = elf.symbols['main'] 未找到
如果找不到"main"符号。那么您可以找到主代码所在的位置:
并手动设置地址:
Puts未找到
如果二进制文件没有使用Puts,您应该检查是否使用了
sh: 1: %s%s%s%s%s%s%s%s: not found
sh: 1: %s%s%s%s%s%s%s%s: not found如果在创建所有利用后发现这个错误:sh: 1: %s%s%s%s%s%s%s%s: not found
尝试从"/bin/sh"的地址中减去64个字节:
从零开始学习AWS黑客技术,成为专家 htARTE(HackTricks AWS Red Team Expert)!
其他支持HackTricks的方式:
如果您想在HackTricks中看到您的公司广告或下载PDF格式的HackTricks,请查看订阅计划!
加入 💬 Discord群 或 电报群 或 关注我们的Twitter 🐦 @hacktricks_live。
通过向HackTricks和HackTricks Cloud github仓库提交PR来分享您的黑客技巧。
最后更新于