13 KiB
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 8‑bit 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
auvictim->fd == av (arena)
, ambayo inamaanisha kwamba anwani tunayotaka kuandika lazima iwe na anwani ya fake chunk katika nafasi yake yafd
na kwambafd
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 kuitafree(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
navictim->fd == unsorted_chunks(av)
kabla ya unlinking. Kwa sababu uingizaji tayari uliandikavictim
ndani yabck->fd
(TARGET yetu), ukaguzi huu unaweza kutimizwa ikiwa uandishi ulifanikiwa.
Modern constraints (glibc ≥ 2.33)
Ili kutumia unsorted‑bin 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 64‑bit 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
navictim->fd == unsorted_chunks(av)
; vinginevyo inakata namalloc(): 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 anarudishabck->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 write‑what‑where baadaye).
- Epuka
__malloc_hook
/__free_hook
kwenye glibc mpya: zilitolewa kwenye 2.34. Epukaglobal_max_fast
kwenye ≥ 2.39 (angalia nota ifuatayo).
- About
global_max_fast
on recent glibc- On glibc 2.39+,
global_max_fast
is an 8‑bit 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.
- On glibc 2.39+,
Minimal exploitation recipe (modern glibc)
Goal: achieve a single arbitrary write of a heap pointer to an arbitrary address using the unsorted‑bin 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 B’s chunk header to set
B->bk = (mchunkptr)(TARGET - 0x10)
.
- Overflow from A into B’s chunk header to set
- Trigger
free(B)
. At insertion time the allocator executesbck->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".
- If you plan to continue allocating and the program uses the unsorted bin, expect the allocator to later set
Pseudocode skeleton:
// 64-bit glibc 2.35–2.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 B’s 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 kwambaTARGET
yako inashikilia pointer kamili yavictim
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 kuchapishaglobal_max_fast
. - Kisha, inawezekana kuita function ya edit kwa index 2 (pointer ya use after free) na kubadilisha
bk
pointer ili iendelee kuonyesha kwap64(global_max_fast-0x10)
. Kisha, kuunda chunk mpya kutatumia address ya free iliyoharibiwa (0x20) na kusababisha unsorted bin attack ikichapishaglobal_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 size0xfc*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 size0x1f8
inaundwa kupata fast bin chunk katika__free_hook
ambayo inachapishwa na anwani ya function yasystem
. - 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
- Glibc malloc unsorted-bin integrity checks (example in 2.33 source): https://elixir.bootlin.com/glibc/glibc-2.33/source/malloc/malloc.c
global_max_fast
and related definitions in modern glibc (2.39): https://elixir.bootlin.com/glibc/glibc-2.39/source/malloc/malloc.c {{#include ../../banners/hacktricks-training.md}}