mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
135 lines
13 KiB
Markdown
135 lines
13 KiB
Markdown
# 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](large-bin-attack.md) or a [fast bin attack](fast-bin-attack.md) 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](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**](https://guyinatuxedo.github.io/31-unsortedbin_attack/unsorted_explanation/index.html) 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 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` 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]({{#ref}}fast-bin-attack.md{{#endref}}) inayofuata au ku-pivot kwa write‑what‑where 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 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.
|
||
|
||
## 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)`.
|
||
- 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:
|
||
```c
|
||
// 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 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**](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw18_alienVSsamurai/index.html), 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**](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**](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 ita**leak** 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`**:
|
||
- <pre class="language-c"><code class="lang-c">gef➤ p &__free_hook
|
||
$1 = (void (**)(void *, const void *)) 0x7ff1e9e607a8 <__free_hook>
|
||
gef➤ x/60gx 0x7ff1e9e607a8 - 0x59
|
||
<strong>0x7ff1e9e6074f: 0x0000000000000000 0x0000000000000200
|
||
</strong>0x7ff1e9e6075f: 0x0000000000000000 0x0000000000000000
|
||
0x7ff1e9e6076f <list_all_lock+15>: 0x0000000000000000 0x0000000000000000
|
||
0x7ff1e9e6077f <_IO_stdfile_2_lock+15>: 0x0000000000000000 0x0000000000000000
|
||
</code></pre>
|
||
- 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**](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**](https://7rocky.github.io/en/ctf/other/blackhat-ctf/robot-factory/)
|
||
- 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}}
|