hacktricks/src/binary-exploitation/libc-heap/unsorted-bin-attack.md

13 KiB
Raw Blame History

Unsorted Bin Attack

{{#include ../../banners/hacktricks-training.md}}

Taarifa za Msingi

For more information about what is an unsorted bin check this page:

{{#ref}} bins-and-memory-allocations.md {{#endref}}

Unsorted lists zinaweza kuandika anwani ya unsorted_chunks (av) katika anwani ya bk ya chunk. Kwa hiyo, ikiwa mshambuliaji anaweza kubadilisha anwani ya pointer bk katika chunk ndani ya unsorted bin, angeweza kuwa na uwezo wa kuandika anwani hiyo mahali popote ambayo inaweza kusaidia ku-leak anwani za Glibc au kuruka utetezi fulani.

Kwa msingi, shambulio hili huruhusu kuweka namba kubwa kwenye anwani yoyote. Namba kubwa hii ni anwani, ambayo inaweza kuwa anwani ya heap au anwani ya Glibc. Lengo la jadi lilikuwa global_max_fast kuruhusu kuunda fast bin bins zenye ukubwa mkubwa (na kutoka unsorted bin attack kwenda fast bin attack).

  • Modern note (glibc ≥ 2.39): global_max_fast became an 8bit global. Blindly writing a pointer there via an unsorted-bin write will clobber adjacent libc data and will not reliably raise the fastbin limit anymore. Prefer other targets or other primitives when running against glibc 2.39+. See "Modern constraints" below and consider combining with other techniques like a large bin attack or a fast bin attack once you have a stable primitive.

Tip

T> Kuangalia mfano uliotolewa katika https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#principle na kutumia 0x4000 na 0x5000 badala ya 0x400 na 0x500 kama chunk sizes (ili kuepuka Tcache) inawezekana kuona kwamba siku za hivi karibuni hitilafu malloc(): unsorted double linked list corrupted inachochewa.

Hivyo, shambulio hili la unsorted bin sasa (miongoni mwa ukaguzi mwingine) pia linahitaji kuwa na uwezo wa kurekebisha double linked list ili kupitisha ukaguzi victim->bk->fd == victim au victim->fd == av (arena), ambayo inamaanisha kwamba anwani tunayotaka kuandika lazima iwe na anwani ya fake chunk katika nafasi yake ya fd na kwamba fd ya fake chunk inarejea kwa arena.

Caution

Kumbuka kwamba shambulio hili linaharibu unsorted bin (na hivyo small na large pia). Kwa hivyo sasa tunaweza tu kutumia allocations kutoka fast bin (programu ngumu zaidi inaweza kufanya allocations nyingine na ku-crash), na ili kuchochea hili lazima tufanye allocation ya ukubwa uleule au programu ita-crash.

Kumbuka kwamba kuandika juu ya global_max_fast kunaweza kusaidia katika kesi hii kwa kuamini kuwa fast bin itashughulikia allocations zote nyingine hadi exploit itakapokamilika.

Msimbo kutoka kwa guyinatuxedo unaelezea vizuri sana, ingawa ukibadilisha mallocs kuomba memory kubwa vya kutosha ili zisimalizike kwenye Tcache utaona kuwa hitilafu iliyotajwa hapo juu inaonekana ikizuia mbinu hii: malloc(): unsorted double linked list corrupted

Jinsi uandishi unavyotokea kwa kweli

  • Uandishi wa unsorted-bin huchochewa wakati wa free wakati chunk iliyofunguliwa inaingizwa kwenye kichwa cha unsorted list.
  • Wakati wa kuingiza, allocator hufanya bck = unsorted_chunks(av); fwd = bck->fd; victim->bk = bck; victim->fd = fwd; fwd->bk = victim; bck->fd = victim;
  • Ikiwa unaweza kuweka victim->bk kuwa (mchunkptr)(TARGET - 0x10) kabla ya kuita free(victim), taarifa ya mwisho itafanya uandishi: *(TARGET) = victim.
  • Baadaye, wakati allocator inashughulikia unsorted bin, ukaguzi wa uadilifu utathibitisha (miongoni mwa mambo mengine) kwamba bck->fd == victim na victim->fd == unsorted_chunks(av) kabla ya unlinking. Kwa sababu uingizaji tayari uliandika victim ndani ya bck->fd (TARGET yetu), ukaguzi huu unaweza kutimizwa ikiwa uandishi ulifanikiwa.

Modern constraints (glibc ≥ 2.33)

Ili kutumia unsortedbin writes kwa kuaminika kwenye glibc ya sasa:

  • Tcache interference: kwa sizes zinazopungua katika tcache, frees zinaelekezwa huko na hazitoghushi unsorted bin. Aidha:
    • fanya maombi yenye sizes > MAX_TCACHE_SIZE (≥ 0x410 kwenye 64bit kwa default), au
    • jaza tcache bin inayolingana (entries 7) ili frees nyingine zifikie global bins, au
    • ikiwa mazingira yanaweza kudhibitiwa, zima tcache (mfano, GLIBC_TUNABLES glibc.malloc.tcache_count=0).
  • Integrity checks on the unsorted list: kwenye njia inayofanya allocation inayotazama unsorted bin, glibc hukagua (imepunguzwa):
    • bck->fd == victim na victim->fd == unsorted_chunks(av); vinginevyo inakata na malloc(): unsorted double linked list corrupted.
  • Hii inamaanisha anwani unayolenga lazima kustahimili maandishi mawili: kwanza *(TARGET) = victim wakati wa free; baadaye, wakati chunk inapoondolewa, *(TARGET) = unsorted_chunks(av) (allocator anarudisha bck->fd kwa kichwa cha bin). Chagua malengo ambapo kulazimisha tu thamani kubwa isiyo-nya ni muhimu.
  • Typical stable targets in modern exploits
    • Hali ya programu au global inayotenda "large" values kama flags/limits.
    • Indirect primitives (mfano, kuandaa kwa ajili ya fast bin attack inayofuata au ku-pivot kwa writewhatwhere baadaye).
    • Epuka __malloc_hook/__free_hook kwenye glibc mpya: zilitolewa kwenye 2.34. Epuka global_max_fast kwenye ≥ 2.39 (angalia nota ifuatayo).
  • About global_max_fast on recent glibc
    • On glibc 2.39+, global_max_fast is an 8bit global. The classic trick of writing a heap pointer into it (to enlarge fastbins) no longer works cleanly and is likely to corrupt adjacent allocator state. Prefer other strategies.

Minimal exploitation recipe (modern glibc)

Goal: achieve a single arbitrary write of a heap pointer to an arbitrary address using the unsortedbin insertion primitive, without crashing.

  • Layout/grooming
    • Allocate A, B, C with sizes large enough to bypass tcache (e.g., 0x5000). C prevents consolidation with the top chunk.
  • Corruption
    • Overflow from A into Bs chunk header to set B->bk = (mchunkptr)(TARGET - 0x10).
  • Trigger
    • free(B). At insertion time the allocator executes bck->fd = B, therefore *(TARGET) = B.
  • Continuation
    • If you plan to continue allocating and the program uses the unsorted bin, expect the allocator to later set *(TARGET) = unsorted_chunks(av). Both values are typically large and may be enough to change size/limit semantics in targets that only check for "big".

Pseudocode skeleton:

// 64-bit glibc 2.352.38 style layout (tcache bypass via large sizes)
void *A = malloc(0x5000);
void *B = malloc(0x5000);
void *C = malloc(0x5000); // guard

// overflow from A into Bs metadata (prev_size/size/.../bk). You must control B->bk.
*(size_t *)((char*)B - 0x8) = (size_t)(TARGET - 0x10); // write fake bk

free(B); // triggers *(TARGET) = B (unsorted-bin insertion write)

Note

• Ikiwa huwezi kupita tcache kwa ukubwa, jaza tcache bin kwa ukubwa uliyoichagua (7 frees) kabla ya kuifree corrupted chunk ili free iende kwenye unsorted. • Ikiwa programu inakatika mara moja kwenye allocation inayofuata kutokana na unsorted-bin checks, angalia tena kwamba victim->fd bado ni sawa na bin head na kwamba TARGET yako inashikilia pointer kamili ya victim baada ya uandishi wa kwanza.

Unsorted Bin Infoleak Attack

Hii kwa kweli ni dhana rahisi. Chunks katika unsorted bin zitakuwa na pointers. Chunk ya kwanza katika unsorted bin itakuwa na viungo vya fd na bk vinavyorejelea sehemu ya main arena (Glibc).
Kwa hiyo, ikiwa unaweza kuweka chunk ndani ya unsorted bin na kuisoma (use after free) au kuiallocate tena bila kuandika juu angalau moja ya pointers kisha kuisoma, unaweza kupata Glibc info leak.

A attack sawa attack used in this writeup, ilikuwa kutumia muundo wa chunks 4 (A, B, C na D - D iko tu kuzuia consolidation na top chunk) hivyo overflow ya null byte kwenye B ilitumika kufanya C kuonyesha kuwa B haikutumika. Pia, kwenye B prev_size ilibadilishwa hivyo ukubwa, badala ya kuwa ukubwa wa B, ulikuwa A+B.
Kisha C ilifutwa, na ikaunganishwa na A+B (lakini B bado ilikuwa inatumika). Chunk mpya ya ukubwa A ilitengenezwa kisha libc leaked addresses ziliandikwa ndani ya B kutoka pale zilipoleak.

References & Other examples

  • https://ctf-wiki.mahaloz.re/pwn/linux/glibc-heap/unsorted_bin_attack/#hitcon-training-lab14-magic-heap
  • Lengo ni kuchapisha (overwrite) global variable na thamani kubwa kuliko 4869 ili iwezekane kupata flag na PIE haijatumiwa.
  • Inawezekana kutengeneza chunks za ukubwa wowote na kuna heap overflow kwa ukubwa unaohitajika.
  • Shambulio linaanza kwa kuunda chunks 3: chunk0 kwa kutumia overflow, chunk1 itakayofanywa overflow na chunk2 ili top chunk isiyoungane na zile zilizotangulia.
  • Kisha, chunk1 inafree-uliwa na chunk0 inaoverflow hadi bk pointer ya chunk1 ionyeshe: bk = magic - 0x10
  • Kisha, chunk3 inaitwa na kuallocate kwa ukubwa sawa na chunk1, ambayo itasababisha unsorted bin attack na kubadilisha thamani ya global variable, kuruhusu kupata flag.
  • https://guyinatuxedo.github.io/31-unsortedbin_attack/0ctf16_zerostorage/index.html
  • Function ya merge ni vulnerabile kwa sababu iwapo index zote mbili zinazopitishwa ni sawa itafanya realloc juu yake na kisha free lakini ikarejesha pointer kwa eneo lililofutwa ambalo linaweza kutumika.
  • Kwa hiyo, chunks 2 ziliundwa: chunk0 ambayo itachanganywa na yenyewe na chunk1 ili kuzuia consolidation na top chunk. Kisha, function ya merge inaitwa na chunk0 mara mbili ambayo itasababisha use after free.
  • Kisha, function ya view inaitwa na index 2 (ambayo ni index ya chunk ya use after free), ambayo italeak anwani ya libc.
  • Kwa kuwa binary ina ulinzi wa kuzuia malloc sizes ndogo kuliko global_max_fast hivyo hakuna fastbin inayotumiwa, unsorted bin attack itatumika kuchapisha global_max_fast.
  • Kisha, inawezekana kuita function ya edit kwa index 2 (pointer ya use after free) na kubadilisha bk pointer ili iendelee kuonyesha kwa p64(global_max_fast-0x10). Kisha, kuunda chunk mpya kutatumia address ya free iliyoharibiwa (0x20) na kusababisha unsorted bin attack ikichapisha global_max_fast kuwa thamani kubwa sana, ikiruhusu sasa kuunda chunks katika fast bins.
  • Sasa shambulio la fast bin linafanywa:
  • Kwanza iligundulika kwamba inawezekana kufanya kazi na fast chunks za size 200 katika eneo la __free_hook:
  • gef➤  p &__free_hook
    

$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook> gef➤ x/60gx 0x7ff1e9e607a8 - 0x59 0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200 0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000 0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000

  • Ikiwa tunafanikiwa kupata fast chunk ya size 0x200 katika eneo hili, itakuwa uwezekano wa kuchapisha function pointer itakayotekelezwa.
  • Kwa hili, chunk mpya ya size 0xfc inaundwa na merged function inaitwa nayo mara mbili, kwa njia hii tunapata pointer kwa freed chunk ya size 0xfc*2 = 0x1f8 katika fast bin.
  • Kisha, function ya edit inaitwa kwenye chunk hii kubadilisha anwani ya fd ya fast bin hii ili iwekelee kwenye __free_hook.
  • Kisha, chunk ya size 0x1f8 inaundwa ili kurejesha kutoka fast bin chunk isiyotumika, kisha chunk nyingine ya size 0x1f8 inaundwa kupata fast bin chunk katika __free_hook ambayo inachapishwa na anwani ya function ya system.
  • Na hatimaye chunk yenye string /bin/sh\x00 inafree-uliwa kwa kutumia function ya delete, kutekeleza __free_hook ambayo sasa inaonyesha system na /bin/sh\x00 kama parameta.
  • CTF https://guyinatuxedo.github.io/33-custom_misc_heap/csaw19_traveller/index.html
  • Mfano mwingine wa kutumia overflow ya 1B kuunganisha chunks katika unsorted bin na kupata libc infoleak na kisha kufanya fast bin attack kubadilisha malloc hook kwa one gadget address
  • Robot Factory. BlackHat MEA CTF 2022
  • Tunaweza tu kuallocate chunks za size kubwa kuliko 0x100.
  • Chapisha global_max_fast kwa kutumia Unsorted Bin attack (inafanya kazi 1/16 mara kutokana na ASLR, kwa sababu tunahitaji kubadilisha bit 12, lakini lazima tubadilishe bit 16).
  • Fast Bin attack kubadilisha array ya global ya chunks. Hii inatoa primitive ya arbitrary read/write, ambayo inaruhusu kubadilisha GOT na kuweka function fulani ili ianze kuonyesha system.

References