<summary><strong>Jifunze kudukua AWS kutoka sifuri hadi shujaa na</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Mtaalam wa Timu Nyekundu ya AWS ya HackTricks)</strong></a><strong>!</strong></summary>
* Ikiwa unataka kuona **kampuni yako ikitangazwa kwenye HackTricks** au **kupakua HackTricks kwa PDF** Angalia [**MIPANGO YA KUJIUNGA**](https://github.com/sponsors/carlospolop)!
* Pata [**swag rasmi ya PEASS & HackTricks**](https://peass.creator-spring.com)
* Gundua [**Familia ya PEASS**](https://opensea.io/collection/the-peass-family), mkusanyiko wetu wa [**NFTs**](https://opensea.io/collection/the-peass-family) ya kipekee
* **Jiunge na** 💬 [**Kikundi cha Discord**](https://discord.gg/hRep4RUj7f) au kikundi cha [**telegram**](https://t.me/peass) au **tufuate** kwenye **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Shiriki mbinu zako za kudukua kwa kuwasilisha PRs kwa** [**HackTricks**](https://github.com/carlospolop/hacktricks) na [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos za github.
Ili kuhakikisha wito wa mfumo unafanywa kwa usahihi, lazima ucompile programu iliyopita na wito wa mfumo unapaswa kuonekana katika **strace ./PROGRAMA\_COMPILADO**
Wakati wa kuunda shellcodes, unaweza kutumia hila. Maagizo ya kwanza ni jump kwenda kwa wito. Wito unaita msimbo wa asili na pia huingiza EIP kwenye stack. Baada ya maagizo ya wito tumeweka string tunayohitaji, kwa hivyo na EIP hiyo tunaweza kuelekeza kwa string na kuendelea kutekeleza msimbo.
Inahusisha nambari ndogo inayopitia kurasa za kumbukumbu zinazohusiana na mchakato kutafuta shellcode iliyohifadhiwa hapo (inatafuta saini fulani iliyojumuishwa kwenye shellcode). Inatumika katika hali ambapo kuna nafasi ndogo tu ya kuingiza nambari.
Hizi ni shellcodes zilizofichwa ambazo zina nambari ndogo za kuzifichua na kuzinduka kwake, zikitumia mbinu ya Kuita-Pop hii itakuwa **mfano wa kificho kilichofichwa cha Caesar**:
Kwa njia hii, EBP inaweza kubadilishwa wakati wa kutoka kwenye kazi (fvuln) ambayo imeitwa na kazi nyingine, wakati kazi iliyomwita fvuln itakapomaliza, EIP yake inaweza kubadilishwa.
Katika fvuln, unaweza kuingiza EBP bandia inayoashiria mahali ambapo anwani ya shellcode iko + 4 (inapaswa kuongezwa 4 kwa pop). Kwa hivyo, wakati wa kutoka kwenye kazi, thamani ya &(\&Shellcode)+4 itawekwa kwenye ESP, na pop itapunguza 4 kutoka ESP na itaashiria kwa anwani ya shellcode wakati ret inatekelezwa.
Inaruhusu kubadilisha tu byte usio na maana zaidi ya EBP. Inaweza kutekelezwa kama shambulio hapo juu lakini kumbukumbu inayoshikilia anwani ya shellcode lazima iwe na byte 3 za kwanza zinazoshirikiana na EBP.
ASLR husababisha kazi kila wakati kubebwa kwenye nafasi tofauti za kumbukumbu kila wakati. Kwa hivyo mbinu hii inaweza kutofaulu katika kesi hiyo. Kwa seva za mbali, kama programu inatekelezwa mara kwa mara kwa anwani ile ile inaweza kuwa na manufaa.
Anwani ya maelekezo ya mfumo wa libc inawekwa na string "bin/sh", kawaida kutoka kwa mazingira ya kivinjari. Zaidi ya hayo, anwani ya kazi ya exit hutumiwa ili mara tu shell itakapokuwa haifai tena, programu itoke bila shida (na kuandika magogo).
"A" \* UMBALI EBP + 4 (EBP: inaweza kuwa "A" 4 ingawa bora ikiwa ni EBP halisi kuepuka makosa ya segfault) + Anwani ya **system** (itapindua EIP) + Anwani ya **exit** (baada ya kutoka kwa system(“/bin/sh”) hii itaita kazi hivyo byte za kwanza 4 za stack zinachukuliwa kama anwani inayofuata ya EIP itakayotekelezwa) + Anwani ya “**/bin/sh**” (itakuwa parameter iliyopitishwa kwa mfumo)
Kwa njia hii, EIP itapinduliwa na anwani ya mfumo ambayo itapokea kama parameter string “/bin/sh” na baada ya kutoka kwa hii itatekeleza kazi ya exit().
Inawezekana kukutana na hali ambapo byte moja ya anwani ya kazi ni tupu au nafasi (\x20). Katika kesi hiyo, unaweza kuchambua anwani zilizotangulia kwa kazi hiyo kwani labda kuna NOPs kadhaa ambazo zinaweza kuturuhusu kuita moja yao badala ya kazi moja kwa moja (kwa mfano na > x/8i system-4).
Mbinu hii inafanya kazi kwa sababu kuita kazi kama mfumo kwa kutumia opcode **ret** badala ya **call**, kazi inaelewa kuwa byte za kwanza 4 zitakuwa anwani ya **EIP** ya kurudi.
Mbinu ya kuvutia na mbinu hii ni kuita **strncpy()** kusonga mzigo kutoka kwenye stack hadi kwenye heap na baadaye kutumia **gets()** kutekeleza mzigo huo.
Mbinu nyingine ya kuvutia ni matumizi ya **mprotect()** ambayo inaruhusu kutoa ruhusa zinazohitajika kwa sehemu yoyote ya kumbukumbu. Inafanya kazi au ilifanya kazi kwa BDS, MacOS na OpenBSD, lakini sio kwa linux (inadhibiti kwamba ruhusa za kuandika na kutekeleza haziwezi kutolewa wakati huo huo). Kwa shambulio hili, unaweza kurejesha stack kama kutekelezeka.
Kwa njia hii, unaweza kuunganisha kazi za kuita. Zaidi, ikiwa unataka kutumia kazi na hoja nyingi, unaweza kuweka hoja zinazohitajika (k.m. 4) na kuweka hoja 4 na kutafuta anwani kwenye tovuti na opcodes: pop, pop, pop, pop, ret —> **objdump -d executable**
Shellcode hii inaweza kurudiwa bila kikomo kwenye sehemu za kumbukumbu ambazo unaweza kupata kwa urahisi shellcode inayoweza kugawanywa kwa vipande vidogo vya kumbukumbu.
Inafaa wakati huwezi kuweka anwani ya stack kwenye EIP (inathibitisha kuwa EIP hauna 0xbf) au wakati huwezi kuhesabu mahali pa shellcode. Lakini, kazi inayoweza kudhurika inakubali parameter (shellcode itakuwa hapa).
Kwa njia hii, kwa kubadilisha EIP na anwani ya **ret**, itapakia anwani inayofuata (ambayo ni anwani ya hoja ya kwanza ya kazi). Yaani, itapakia shellcode.
Exploit itakuwa: SHELLCODE + Kujaza (hadi EIP) + **\&ret** (byte zinazofuata za stack zinaelekeza mwanzo wa shellcode kwa sababu anwani ya parameter iliyopitishwa imewekwa kwenye stack)
Inaonekana kazi kama **strncpy** mara tu zinapokamilika zinaondoa kutoka kwa stack anwani ambapo shellcode ilikuwa imehifadhiwa ikizuia mbinu hii. Yaani, anwani wanayopitisha kama hoja kwa kazi (ile inayohifadhi shellcode) inabadilishwa na 0x00 kwa hivyo wakati wa kuita **ret** ya pili inakutana na 0x00 na programu inakufa.
Kwa kuangalia jinsi mchakato mpya unavyojengwa kwenye Linux, unaweza kuendeleza exploit ili programu ianze katika mazingira ambayo ina variable moja tu, shellcode. Kisha unaweza kuhesabu anwani ya hii kama: addr = 0xbfffffff - 4 - strlen(NOMBRE\_ejecutable\_completo) - strlen(shellcode)
Kwa kuwa ESP inalenga mwanzo wa stack daima, hii technique inahusisha kubadilisha EIP na anwani ya wito wa **jmp esp** au **call esp**. Hivyo, shellcode inahifadhiwa baada ya kuandika upya EIP kwa sababu baada ya kutekeleza **ret** ESP itakuwa inalenga anwani inayofuata, mahali ambapo shellcode imehifadhiwa.
Ikiwa ASLR haipo kwenye Windows au Linux, unaweza kuita **jmp esp** au **call esp** zilizohifadhiwa kwenye kitu kinachoshirikishwa. Ikiwa ASLR iko, unaweza kutafuta ndani ya programu yenye hitilafu.
Zaidi ya hayo, uwezo wa kuweka shellcode baada ya kuharibu EIP badala ya katikati ya stack, inaruhusu maagizo ya push au pop yanayotekelezwa katikati ya kazi kutofikia shellcode (jambo ambalo lingeweza kutokea ikiwa ingewekwa katikati ya stack ya kazi).
Kwa njia sawa na hii, ikiwa tunajua kwamba kuna kazi inarudisha anwani ambapo shellcode imehifadhiwa, unaweza kuita **call eax** au **jmp eax (ret2eax).**
Aina hii ya kujaa hufanyika wakati variable haijajiandaa kushughulikia nambari kubwa kama ile inayopitishwa, labda kutokana na mkanganyiko kati ya variables zenye ishara na zisizo na ishara, kwa mfano:
Ikiwa tunaweka nambari hasi kama kigezo cha kwanza, itasema kuwa len <256natutapitakizuizihicho,napiastrlen(buffer)itakuwandogokulikol,kwanilniunsignedintnaitakuwakubwasana.
Haijulikani thamani ambayo inaweza kuchukua kwa kigezo ambacho hakijaanzishwa na inaweza kuwa ya kuvutia kuichunguza. Inaweza kuchukua thamani ambayo kigezo cha kazi ya awali kilichukua na hii inaweza kudhibitiwa na mshambuliaji.
Katika C **`printf`** ni kazi inayoweza kutumika kwa **kuchapisha** string fulani. **Kigezo cha kwanza** kinachotarajiwa na kazi hii ni **maandishi safi na formatters**. **Vigezo vinavyofuata** vinavyotarajiwa ni **thamani** za **kuchukua nafasi** ya **formatters** kutoka kwa maandishi safi.
Udhaifu unaonekana wakati **maandishi ya mshambuliaji yanawekwa kama hoja ya kwanza** kwa kazi hii. Mshambuliaji ataweza kutengeneza **kuingiza maalum kwa kudanganya** uwezo wa **formati ya printf** ya **kuandika data yoyote kwenye anwani yoyote**. Kwa njia hii, wakati huo huo kuweza **kutekeleza kanuni za aina yoyote**.
**`%n`** **huiandika****idadi ya****baiti zilizoandikwa** kwenye **anwani iliyotajwa. Kuandika** idadi **ya** baiti **kama vile namba ya hex** tunayohitaji **kuandika ndivyo unaweza** kuandika data yoyote**.
Katika binary, GOT ina **anwani za kazi au** kwa sehemu ya **PLT** ambayo itapakia anwani ya kazi. Lengo la shambulio hili ni **kubadilisha kuingia kwa GOT** ya kazi ambayo itatekelezwa baadaye **na** anwani ya PLT ya **kazi ya `system`**. Kimsingi, uta **badilisha** GOT ya **kazi** ambayo **itaitwa na parameta zinazodhibitiwa na wewe** (hivyo utaweza kudhibiti parameta zinazotumwa kwa kazi ya mfumo).
Ikiwa **`system`** **haitumiwi** na script, kazi ya mfumo **haitakuwa na kuingia** katika GOT. Katika hali hii, utahitaji **kuvuja kwanza anwani** ya kazi ya `system`.
**Procedure Linkage Table** ni meza **isiyoweza kuhaririwa** katika faili ya ELF inayohifadhi alama zote muhimu **zinazohitaji ufumbuzi**. Wakati moja ya kazi hizi inaitwa, **GOT** ita **elekeza****mzunguko** kwa **PLT** ili iweze **kufumbua****anwani** ya kazi na kuandika kwenye GOT.\
Kisha, **wakati ujao** wito unafanywa kwa anwani hiyo **kazi** inaitwa moja kwa moja **bila** kuhitaji kufumbua.
Kama ilivyoelezwa awali lengo litakuwa **kubadilisha****anwani** ya **kazi** katika meza ya **GOT** ambayo itaitwa baadaye. Kimsingi tunaweza kuweka **anwani kwa shellcode** iliyoko katika sehemu ya kutekelezeka, lakini ni uwezekano mdogo utaweza kuandika shellcode katika sehemu ya kutekelezeka.\
Kwa hivyo chaguo lingine ni **kubadilisha****kazi** ambayo **inapokea****vigezo vyake** kutoka kwa **mtumiaji** na **kuielekeza** kwa **kazi ya `system`**.
Kimsingi hii ni muundo na **kazi ambazo zitaitwa** kabla ya programu kukamilika. Hii ni ya kuvutia ikiwa unaweza kuita **shellcode yako kwa kuruka kwa anwani**, au katika hali ambapo unahitaji kurudi kwa main tena **kushambulia format string mara ya pili**.
Tafadhali kumbuka kwamba hii **haitasababisha****mwanya wa milele** kwa sababu unaporudi kwenye kipengele kuu, canary atagundua, mwisho wa steki unaweza kuharibiwa na kazi haitaitwa tena. Kwa hivyo, utaweza **kuwa na utekelezaji mwingine 1** wa mwanya.
Fomati ya string inaweza kutumika pia kudumpisha yaliyomo kutoka kwenye kumbukumbu ya programu.\
Kwa mfano, katika hali ifuatayo kuna **variable ya ndani kwenye steki inayoelekeza kwenye bendera.** Ikiwa **utapata** mahali **kwenye kumbukumbu** ambapo **ishara** ya **bendera** iko, unaweza kufanya **printf kufikia** anwani hiyo na **kuchapisha** bendera:
Tafadhali kumbuka baada ya **kutumia mwanya wa awali** na kugundua unaweza **kuvuja yaliyomo** unaweza **kuweka ishara** kwa **`printf`** kwenye sehemu ambapo **kutekelezeka** ime **pakia** na **kudump** kabisa!
Kawaida utapata sehemu ya **DTOR****kati ya** thamani `ffffffff` na `00000000`. Kwa hivyo ikiwa unaona thamani hizo tu, inamaanisha kwamba **hakuna kazi iliyosajiliwa**. Kwa hivyo **badilisha****`00000000`** na **anwani** ya **shellcode** ili kuitekeleza.
**sprintf inahamisha** string iliyopangwa **kwa****variable.** Kwa hivyo, unaweza kutumia **upangaji** wa string kusababisha **buffer overflow kwenye variable** ambapo maudhui yanakopwa.\
Kwa mfano, payload `%.44xAAAA` itaandika **44B+"AAAA" kwenye variable**, ambayo inaweza kusababisha buffer overflow.
**`atexit()`** ni kazi ambayo **kazi zingine hupitishwa kama parameta.** Hizi **kazi** zitatekelezwa wakati wa kutekeleza **`exit()`** au **kurudi** kwa **msingi**.\
Ikiwa unaweza **kubadilisha****anwani** ya mojawapo ya hizi **kazi** ili ielekee shellcode kwa mfano, utapata **udhibiti** wa **mchakato**, lakini hii ni ngumu zaidi kwa sasa.\
Kwa sasa **anwani za kazi** zitakazotekelezwa zimefichwa nyuma ya miundo kadhaa na mwishowe anwani ambayo inaelekezwa sio anwani za kazi, bali zime **fichwa kwa XOR** na kuhama na **ufunguo wa nasibu**. Kwa hivyo kwa sasa njia hii ya shambulio **si ya kufaa sana angalau kwenye x86** na **x64\_86**.\
Kazi ya **ufichaji** ni **`PTR_MANGLE`**. **Miundo mingine** kama m68k, mips32, mips64, aarch64, arm, hppa... **hawatekelezi kazi ya ufichaji** kwa sababu **inarejesha sawa** na ilivyopokea kama kuingia. Kwa hivyo miundo hii inaweza kushambuliwa kupitia njia hii.
Registri zilizohifadhiwa ni: `EBX, ESI, EDI, ESP, EIP, EBP`\
Kile kinachotokea ni kwamba EIP na ESP hupitishwa na **kazi ya `PTR_MANGLE`**, kwa hivyo **usalama wa miundo hii ni sawa na hapo juu**.\
Ni muhimu kwa kupona kosa au kuingilia kati.\
Walakini, kutokana na nilichosoma, registri zingine hazilindwi, **kwa hivyo ikiwa kuna `call ebx`, `call esi` au `call edi`** ndani ya kazi inayoitwa, udhibiti unaweza kuchukuliwa. Au unaweza pia kubadilisha EBP kubadilisha ESP.
Kila kitu cha **darasa** kina **VPtr** ambayo ni **pointa** kwa safu ya darasa yake. VPtr ni sehemu ya kichwa cha kila kitu, kwa hivyo ikiwa **ubadilishaji** wa **VPtr** unafanikiwa inaweza **kubadilishwa** ili **ielekee** kwa njia bandia ili kutekeleza kazi iende kwenye shellcode.
Ni mbinu ya kugeuza buffer overflow kuwa kosa la string ya formati. Inahusisha kubadilisha EIP ili ielekee printf ya kazi na kumpa kama hoja string ya formati iliyodhibitiwa ili kupata thamani kuhusu hali ya mchakato.
Maktaba ziko kwenye nafasi na bits 16 za nasibu = anwani 65636 za uwezekano. Ikiwa seva inayoweza kushambuliwa inaita fork() nafasi ya anwani ya kumbukumbu inaiga katika mchakato wa mtoto na inabaki bila kuguswa. Kwa hivyo unaweza kujaribu kufanya nguvu ya brute kwa kazi ya usleep() ya libc ukimpa "16" kama hoja ili wakati itachukua muda mrefu kuliko kawaida kujibu, kazi hiyo itakuwa imepatikana. Ukiwa unajua wapi kazi hiyo iko unaweza kupata delta\_mmap na kuhesabu zingine.
**Relro (Usogezaji wa Kusoma tu)** inaathiri ruhusa ya kumbukumbu sawa na NX. Tofauti ni wakati NX inafanya stack iweze kutekelezwa, RELRO inafanya **vitu fulani viwe vya kusoma tu** hivyo hatuwezi kuandika kwao. Njia ya kawaida niliyoona hii kuwa kizuizi ni kuzuia kutufanya **`got` table overwrite**, ambayo itajadiliwa baadaye. Jedwali la `got` linashikilia anwani za kazi za libc ili programu ijue anwani ni zipi na iweze kuzipiga. Hebu tuone ruhusa ya kumbukumbu inaonekanaje kwa kuingia la jedwali la `got` kwa programu na bila relro.
Kwa binary **bila relro**, tunaweza kuona kuwa anwani ya kuingia ya `got` kwa `fgets` ni `0x404018`. Tukiangalia ramani za kumbukumbu tunagundua kuwa iko kati ya `0x404000` na `0x405000`, ambayo ina **ruhusa `rw`**, maana yake tunaweza kusoma na kuandika kwake. Kwa binary **yenye relro**, tunaona kuwa anwani ya jedwali la `got` kwa kukimbia kwa binary (pie imewezeshwa hivyo anwani hii itabadilika) ni `0x555555557fd0`. Katika ramani ya kumbukumbu ya binary hiyo inaangukia kati ya `0x0000555555557000` na `0x0000555555558000`, ambayo ina ruhusa ya kumbukumbu **`r`**, maana yake tunaweza tu kusoma kutoka kwake.
Kwa hivyo ni **vipi kuvuka**? Kuvuka kawaida ninayotumia ni kutofautisha kuandika kwenye maeneo ya kumbukumbu ambayo relro husababisha kuwa ya kusoma tu, na **kupata njia tofauti ya kupata utekelezaji wa nambari**.
* Kufunga kwa uvivu: Anwani ya kazi inatafutwa mara ya kwanza kazi inaitwa. Kwa hivyo, GOT inahitaji kuwa na ruhusa ya kuandika wakati wa utekelezaji.
* Funga sasa: Anwani za kazi zinafumbuliwa mwanzoni mwa utekelezaji, kisha ruhusa za kusoma tu zinapewa sehemu nyeti kama .got, .dtors, .ctors, .dynamic, .jcr. `` `** ``-z relro`**`y`**`-z now\`\*\*
Wakati binary inapakiwa kumbukani na kazi inaitwa kwa mara ya kwanza, inaruka kwenye PLT (Procedure Linkage Table), kutoka hapo inafanya kuruka (jmp) kwenye GOT na kugundua kuwa ingizo hilo halijaresishwa (linamiliki anwani inayofuata ya PLT). Kwa hivyo inaita Runtime Linker au rtfd ili kuresisha anwani na kuifadhi kwenye GOT.
Kuwaita kazi kunaita PLT, ambayo ina anwani ya GOT ambapo anwani ya kazi imehifadhiwa, kwa hivyo inaelekeza mtiririko huko na hivyo kuita kazi. Walakini, ikiwa ni mara ya kwanza kuita kazi, kile kilicho kwenye GOT ni maagizo inayofuata ya PLT, kwa hivyo mtiririko unaendelea kwenye nambari ya PLT (rtfd) na kugundua anwani ya kazi, kuifadhi kwenye GOT na kuuita.
Lazy binding —> Anwani ya kazi inatafutwa mara ya kwanza kazi hiyo inaitwa, kwa hivyo GOT ina ruhusa ya kuandika ili wakati inatafutwa, iwekwe hapo na isitafutwe tena.
Bind now —> Anwani za kazi zinatafutwa wakati programu inapakia na ruhusa za sehemu .got, .dtors, .ctors, .dynamic, .jcr zinabadilishwa kuwa za kusoma tu. **-z relro** na **-z now**
Ya pili haikubali **%n** kutoka sehemu na ruhusa ya kuandika. Pia, parameter ya ufikiaji wa moja kwa moja wa hoja inaweza kutumika tu ikiwa zimetumiwa hapo awali, yaani, inaweza kutumika tu **%3$d** ikiwa **%2$d** na **%1$d** zimetumiwa hapo awali.
Kutumia argv\[0] kuonyesha ujumbe wa kosa, kwa hivyo ikiwekwa kwenye anwani nyingine (kama kwenye kibadala cha kawaida) ujumbe wa kosa utaonyesha maudhui ya kibadala hicho. Uk. 191
Inazuia wito wa kazi fulani zisizo salama kwa kazi zingine salama. Haijathibitishwa (kwa x86 pekee, sio kwa uundaji wa -fomit-frame-pointer, sio uundaji wa static, sio kila kazi inayoweza kudhuriwa inageuzwa kuwa salama na LD\_PRELOAD haifanyi kazi kwa binary zenye suid).
Inahusisha kupakia maktaba zilizoshirikiwa kutoka 0x00000000 hadi 0x00ffffff ili daima iwe na byte 0x00. Walakini, hii kimsingi haizuili mashambulizi mengi, haswa katika mfumo wa little endian.
Inahusisha kufanya ROP ili kuita kazi strcpy@plt (kutoka plt) na kuelekeza kuingia kwenye GOT na kunakili byte ya kwanza ya kazi unayotaka kuita (system()). Kisha unafanya hivyo hilo hilo ukiashiria GOT+1 na kunakili byte ya pili ya system()… Mwishowe unaita anwani iliyohifadhiwa kwenye GOT ambayo itakuwa system()
Kwa kazi zinazotumia EBP kama usajili wa kuashiria hoja wakati wa kubadilisha EIP na kuashiria kwa system(), EBP pia lazima ibadilishwe ili kuashiria eneo la kumbukumbu lenye byte 2 yoyote kwanza na kisha anwani ya &”/bin/sh”.
Kwenye "size" kuna bits za kuonyesha: Ikiwa kipande kilichotangulia kina matumizi, ikiwa kipande kimepewa kwa kutumia mmap() na ikiwa kipande kinamilikiwa na uwanja wa msingi.
Ikiwa kipande kimoja huru, vipande vingine vinavyopakuliwa vinapounganishwa kupitia macro unlink() na kipande kipya kikubwa zaidi kinapitishwa kwa frontlink() ili kiingize bin sahihi.
Na hivyo shellcode inatekelezwa wakati programu inamalizika.
Zaidi, sentensi ya 4 ya unlink() inaandika kitu na shellcode lazima ibadilishwe kwa hili:
BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor\_end\_\_ - 12) —> Hii husababisha kuandika byte 4 kutoka kwa byte ya 8 ya shellcode, kwa hivyo maagizo ya kwanza ya shellcode lazima iwe jmp ili kusonga hili na kufikia nops ambayo inaendelea na shellcode.
Kwa hivyo, shambulio linajengwa:
Kwenye buffer1 tunaweka shellcode ikiwaanza na jmp ili iangukie kwenye nops au sehemu iliyobaki ya shellcode.
Baada ya shell code tunaweka kujaza hadi kufikia uwanja wa prev\_size na size wa kipande kinachofuata. Maeneo haya tunaweka 0xfffffff0 (ili kubadilisha prev\_size ili iwe na bit inayosema ni huru) na “-4“(0xfffffffc) kwenye size (ili wakati wa kuchunguza kipande cha 3 ikiwa kipande cha 2 kilikuwa huru kweli iende kwa prev\_size iliyobadilishwa ambayo itasema kwamba ni huru) -> Hivyo wakati free() inachunguza itaenda kwa size ya 3 lakini kwa kweli itaenda kwa 2 - 4 na kufikiria kipande cha 2 ni huru. Na kisha itaita **unlink()**.
Kuita unlink() kutatumia kama P->fd data za kwanza za kipande cha 2 kwa hivyo anwani inayotaka kubadilishwa - 12(kwa sababu katika FD->bk itaongeza 12 kwa anwani iliyohifadhiwa kwenye FD) itaingizwa hapo. Na kwenye anwani hiyo itaingiza anwani ya pili inayopatikana kwenye kipande cha 2, ambayo itakuwa anwani ya shellcode(P->bk bandia).
**fake\_size = pack("\<I”, 0xfffffffc) #-4, ili iweze kufikiria kuwa "size" ya kipande cha 3 iko nyuma kwa bytes 4 (inatazama prev\_size) kwani ndipo inapotazama ikiwa kipande cha 2 kiko huru**
**got\_free = pack("\<I", 0x08048300 - 12) #Anwani ya free() kwenye plt-12 (itakuwa anwani itakayobadilishwa ili shellcode iitwe mara ya pili free inaitwa)**
Kwa hiyo, programu itafikiria "a" iko huru na kwenye bin, kwa hivyo itaita unlink() kuiondoa. Hata hivyo, kwa kuwa kichwa cha PREV\_SIZE ni -4. Itafikiria kipande cha "a" kwa kweli kinaanza kwenye b+4. Yaani, itafanya unlink() kwa kipande kinachoanza kwenye b+4, kwa hivyo b+12 kutakuwa na pointer "fd" na b+16 kutakuwa na pointer "bk".
Kwa njia hii, kwa kusajili upya kwa njia isiyo na kudhibitiwa katika mallocs mbili na moja kwa njia inayodhibitiwa lakini inayofutwa tu, tunaweza kufanya shambulio.
Ikiwa unataka kutumia moja tena, unaweza kuipata bila shida. Ikiwa unataka kutumia nyingine, utapewa nafasi ile ile kwa hivyo tutakuwa na pointers "fd" na "bk" zilizodanganywa na data itakayoandikwa na akiba ya awali.
Wito mmoja tu wa free() unahitajika kusababisha utekelezaji wa nambari ya aina ya kiholela. Ni muhimu kutafuta kipande cha pili ambacho kinaweza kufurika na kimoja cha awali na kufutwa.
Katika \[1] inathibitisha uga wa ukubwa wa NON\_MAIN\_ARENA, ambao unaweza kubadilishwa ili uhakiki irudishe kweli na kutekeleza heap\_for\_ptr() ambayo inafanya and kwa "mem" ikiiacha 0 bytes 2.5 zisizo na maana (katika kesi yetu ya 0x0804a000 inaacha 0x08000000) na kufikia 0x08000000->ar\_ptr (kama vile ni muundo wa struct heap\_info)
Kwa njia hii, ikiwa tunaweza kudhibiti kipande kwa mfano kwenye 0x0804a000 na kipande kitafutwa kwenye **0x081002a0** tunaweza kufikia anwani ya 0x08100000 na kuandika chochote tunachotaka, kwa mfano **0x0804a000**. Wakati kipande cha pili kitakapofutwa, itagundua kwamba heap\_for\_ptr(ptr)->ar\_ptr inarudisha kile tulichoandika kwenye 0x08100000 (kwa sababu inatumia and kama ilivyoonekana hapo awali na kutoka hapo inachukua thamani ya bytes 4 za kwanza, ar\_ptr)
Kama tulivyoona hapo awali tunaweza kudhibiti thamani ya av, kwa hivyo ndio tunachoandika kwenye kipande kitakachofutwa.
Kama ilivyoainishwa unsorted\_chunks, tunajua kwamba:\
bck = \&av->bins\[2]-8;\
fwd = bck->fd = \*(av->bins\[2]);\
fwd->bk = \*(av->bins\[2] + 12) = p;
Kwa hivyo ikiwa tunaweza kuandika thamani ya \_\_DTOR\_END\_\_-12 kwenye av->bins\[2] kwenye hatua ya mwisho itaandikwa kwenye \_\_DTOR\_END\_\_ anwani ya kipande cha pili.
Yaani, kwenye kipande cha kwanza tunahitaji kuweka mwanzoni mara nyingi anwani ya \_\_DTOR\_END\_\_-12 kwa sababu ndio itakayotolewa na av->bins\[2]
Kwenye anwani ambayo itaanguka anwani ya kipande cha pili na sifuri tano za mwisho tunahitaji kuandika anwani ya kipande cha kwanza ili heap\_for\_ptr() iweze kufikiria ar\_ptr iko mwanzoni mwa kipande cha kwanza na kutoa av->bins\[2] kutoka hapo
Kwenye kipande cha pili na kwa msaada wa kipande cha kwanza tunasajili upya prev\_size na jump 0x0c na ukubwa na kitu cha kuamsha -> NON\_MAIN\_ARENA
Kisha kwenye kipande cha pili tunaweka nyingi za nops na mwishowe shellcode
Kwa njia hii wito wa \_int\_free(TROZO1, TROZO2) utaitwa na kufuata maagizo ya kuandika kwenye \_\_DTOR\_END\_\_ anwani ya prev\_size ya TROZO2 ambayo itaruka kwenye shellcode.
Kuomba mbinu hii kuna mahitaji kadhaa zaidi ambayo yanafanya payload kuwa ngumu kidogo zaidi.
Hii mbinu sio tena tena kwa sababu karibu na kufanyiwa marekebisho sawa na unlink. Wanalinganisha ikiwa tovuti mpya inayolengwa pia inamlenga.
Kwa njia hii, ikiwa inawekwa kwenye "fb" inatoa anwani ya kazi kwenye GOT, kwenye anwani hii anwani ya kipande iliyobadilishwa itawekwa. Kwa hili, itakuwa muhimu kwamba uwanja uko karibu na anwani za dtors. Hasa, av->max\_fast iko kwenye anwani ambayo tunataka kubadilisha.
Kwa hivyo ikiwa tunaweka ukubwa wa 8 + NON\_MAIN\_ARENA + PREV\_INUSE kwenye uga wa ukubwa —> fastbin\_index() itarudisha fastbins\[-1], ambayo italenga av->max\_fast
Pia lazima iwe kwamba kipande kilicho karibu na kilichofutwa kiwe kikubwa kuliko 8 -> Kwa kuwa tumesema ukubwa wa kipande kilichofutwa ni 8, kwenye kipande hiki bandia tunahitaji tu kuweka ukubwa mkubwa kuliko 8 (kwa kuongezea, shellcode itakuwa kwenye kipande kilichofutwa, itabidi tuweke mwanzoni mwa jmp inayoelekea kwenye nops).
Kwa sababu ya nulls za \_DTOR\_END\_ na anwani chache kwenye GOT, hakuna anwani kutoka sehemu hizi zinazofaa kubadilishwa, kwa hivyo tuone jinsi ya kutumia fastbin kushambulia safu.
Pia lazima iwe kwamba kipande kilicho karibu na kilichofutwa kiwe kikubwa kuliko 8 -> Kwa kuwa tumesema ukubwa wa kipande kilichofutwa ni 16, kwenye kipande hiki bandia tunahitaji tu kuweka ukubwa mkubwa kuliko 8 (kwa kuongezea, shellcode itakuwa kwenye kipande kilichofutwa, itabidi tuweke mwanzoni mwa jmp inayoelekea kwenye nops zilizo baada ya uga wa ukubwa wa kipande kipya bandia).
Katika kesi hii tunatafuta kuwa na pointer kwa malloc ambayo inaweza kubadilishwa na mshambuliaji (kwa mfano, pointer iko kwenye safu chini ya overflow inayowezekana kwa kipengele).
Hivyo, tunaweza kufanya pointer huu uelekee popote. Walakini, sio kila eneo ni sahihi, ukubwa wa kipande kilichobadilishwa lazima uwe mdogo kuliko av->max\_fast na hasa sawa na ukubwa ulioombwa katika wito wa baadaye wa malloc()+8. Kwa hivyo, ikiwa tunajua kwamba baada ya pointer huu wa kuharibika kuna wito wa malloc(40), ukubwa wa kipande bandia lazima uwe sawa na 48.
Kwa mfano, ikiwa programu itauliza mtumiaji nambari tunaweza kuingiza 48 na kuuelekeza pointer wa malloc uliobadilishwa kwa 4bytes zifuatazo (ambazo zinaweza kuwa sehemu ya EBP kwa bahati nzuri, hivyo 48 iko nyuma, kana kwamba ni kichwa cha ukubwa). Kwa kuongezea, anwani ptr-4+48 lazima itimize masharti kadhaa (ikiwa katika kesi hii ptr=EBP), yaani, 8 <ptr-4+48<av->system\_mem.
Ikiwa hii itatimizwa, wakati wito ufuatao wa malloc ambao tulisema ni malloc(40) utaitwa, anwani yake itakuwa anwani ya EBP. Ikiwa mshambuliaji pia anaweza kudhibiti kile kinachoandikwa kwenye malloc hii anaweza kubadilisha EBP na EIP na anwani anayotaka.
Nadhani hii ni kwa sababu wakati free() inafuta itahifadhi kwamba kuna kipande cha ukubwa kamili kwa malloc() mpya inayotaka kuweka akiba, hivyo inampa anwani hiyo.
Jambo la kwanza linalofanywa ni kubadilisha ukubwa wa kipande cha wilderness na thamani kubwa sana (0xffffffff), hivyo ombi lolote la kumbukumbu kubwa kutosha litashughulikiwa katika \_int\_malloc() bila haja ya kupanua heap
Victim inachukua thamani ya anwani ya kipande cha wilderness cha sasa (av->top ya sasa) na remainder ni haswa jumla ya anwani hiyo plus idadi ya bytes iliyotakiwa na malloc(). Kwa hivyo ikiwa \&EIP-8 iko kwenye 0xbffff224 na av->top ina 0x080c2788, basi kiasi tunachohitaji kuweka akiba kwenye malloc iliyodhibitiwa ili av->top ielekee $EIP-8 kwa malloc() ijayo itakuwa:
0xbffff224 - 0x080c2788 = 3086207644.
Hivyo thamani iliyobadilishwa itahifadhiwa kwenye av->top na malloc ijayo itaelekeza kwa EIP na itaweza kubadilishwa.
Ni muhimu kujua kwamba ukubwa wa kipande kipya cha wilderness uwe mkubwa kuliko ombi lililofanywa na malloc() ya mwisho. Yaani, ikiwa wilderness inaelekeza kwa \&EIP-8, ukubwa utabaki kwenye uga wa EBP wa safu.
**The House of Lore**
**Corruption SmallBin**
Vipande vilivyofutwa vinawekwa kwenye bin kulingana na ukubwa wao. Lakini kabla ya kuwekwa, vinahifadhiwa kwenye unsorted bins. Kipande kilichofutwa hakijawekwa moja kwa moja kwenye bin yake bali kinabaki kwenye unsorted bins. Kisha, ikiwa kipande kipya kinaweza kutumika kwa kipande kilichofutwa, kinarejeshwa, lakini ikiwa kipande kikubwa zaidi kinahitajika, kipande kilichofutwa kwenye unsorted bins kinawekwa kwenye bin yake sahihi.
Ili kufikia kanuni inayoweza kudhuriwa, ombi la kumbukumbu lazima liwe kubwa kuliko av->max\_fast (kawaida 72) na chini ya MIN\_LARGE\_SIZE (512).
Ikiwa kuna kipande kwenye bin lenye ukubwa unaofaa kwa ombi, kipande hicho kitarejeshwa baada ya kufunguliwa:
bck = victim->bk; Inaelekeza kwenye kipande kilichotangulia, hii ndio habari pekee tunayoweza kubadilisha.
bin->bk = bck; Kipande cha pili kutoka mwisho kinakuwa cha mwisho, ikiwa bck inaelekeza kwenye safu, kipande kifuatacho kitapewa anwani hii
bck->fd = bin; Kufunga orodha kwa kufanya hii ielekee kwa bin
Inahitajika:
Reserve malloc mbili, ili ya kwanza iweze kufanya overflow baada ya ya pili kuwa imeachiliwa na kuingizwa kwenye bin yake (yaani, malloc kubwa zaidi kuliko ya pili kabla ya kufanya overflow)
Lengo ni, ikiwa tunaweza kufanya overflow kwa heap ambayo ina sehemu iliyofunguliwa chini yake na kwenye bin yake, tunaweza kubadilisha pointer yake bk. Ikiwa tunabadilisha pointer yake bk na sehemu hii inakuwa ya kwanza kwenye orodha ya bin na kuhifadhiwa, bin itadanganywa na kuelezwa kuwa sehemu ya mwisho ya orodha (inayofuata kutoa) iko kwenye anwani ya uwongo tuliyoweka (kwa mfano, kwenye stack au GOT). Kwa hivyo, ikiwa sehemu nyingine inahitajika kuhifadhiwa na mshambuliaji ana ruhusa ndani yake, atapewa sehemu kwenye nafasi inayotakiwa na ataweza kuandika ndani yake.
Baada ya kufungua sehemu iliyobadilishwa, ni muhimu kuhifadhi sehemu kubwa kuliko ile iliyofunguliwa, ili sehemu iliyobadilishwa itoke kwenye unsorted bins na iingizwe kwenye bin yake.
Marafiki kwenye bin yake wanapaswa kusubiri hadi wito wa malloc() ufanyike mara kutosha ili bin iliyobadilishwa itumike tena na kudanganya bin kwa kufanya iaminike sehemu inayofuata iko kwenye anwani ya uwongo. Na kisha sehemu inayotakiwa itatolewa.
Ili kutekeleza udhaifu haraka iwezekanavyo, ni bora: Hifadhi ya sehemu inayoweza kudhuriwa, hifadhi ya sehemu itakayobadilishwa, acha sehemu hii, hifadhi sehemu kubwa kuliko ile itakayobadilishwa, badilisha sehemu (udhaifu), hifadhi sehemu ya ukubwa sawa na ile iliyovunjwa na hifadhi sehemu ya pili ya ukubwa sawa na hiyo itakayoelekeza kwenye anwani iliyochaguliwa.
Kulinda shambulio hili, uthibitishaji wa kawaida kwamba sehemu "si" ni ya uwongo hutumiwa: inathibitishwa ikiwa bck->fd inaelekeza kwa mwathiriwa. Yaani, katika kesi yetu ikiwa pointer wa fd\* wa sehemu ya uwongo iliyoelekezwa kwenye stack inaelekeza kwa mwathiriwa. Ili kuvunja ulinzi huu, mshambuliaji lazima awe na uwezo wa kuandika kwa njia fulani (labda kwenye stack) kwenye anwani sahihi ya mwathiriwa. Ili ionekane kama sehemu ya kweli.
Shambulio ni kama lile lililopita, yaani, lazima kubadilisha pointer bk na wito wote huo wa malloc(), lakini pia lazima ubadilishe ukubwa wa sehemu iliyobadilishwa ili ukubwa huo - nb uwe <MINSIZE.
Kimsingi inahusisha kuhifadhi kumbukumbu yote inayowezekana kwa heaps na kuzijaza na safu ya nops zilizomalizika na shellcode. Kama safu, 0x0c hutumiwa. Kwa hivyo, jaribio litakuwa kusonga kwa anwani 0x0c0c0c0c, na hivyo ikiwa anwani yoyote itaandikwa na safu hii itaenda kwenye colchón. Kimsingi mkakati ni kuhifadhi kiasi kikubwa iwezekanavyo kuona ikiwa pointer yoyote itaandikwa na kuruka kwa 0x0c0c0c0c kwa matumaini kwamba kuna nops huko.
Inahusisha kusambaza kumbukumbu kwa njia ya akiba na kuachilia kumbukumbu kwa njia ambayo sehemu zilizohifadhiwa zinabaki kati ya sehemu zilizofunguliwa. Buffer ya kufurika itawekwa kwenye moja ya mayai.
<summary><strong>Jifunze kuhusu kudukua AWS kutoka sifuri hadi shujaa na</strong><ahref="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
* Ikiwa unataka kuona **kampuni yako ikitangazwa kwenye HackTricks** au **kupakua HackTricks kwa PDF** Angalia [**MIPANGO YA KUJIUNGA**](https://github.com/sponsors/carlospolop)!
* Pata [**bidhaa rasmi za PEASS & HackTricks**](https://peass.creator-spring.com)
* Gundua [**Familia ya PEASS**](https://opensea.io/collection/the-peass-family), mkusanyiko wetu wa [**NFTs**](https://opensea.io/collection/the-peass-family) ya kipekee
* **Jiunge na** 💬 [**Kikundi cha Discord**](https://discord.gg/hRep4RUj7f) au **kikundi cha** [**telegram**](https://t.me/peass) au **tufuate** kwenye **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Shiriki mbinu zako za kudukua kwa kuwasilisha PRs kwa** [**HackTricks**](https://github.com/carlospolop/hacktricks) na [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.