hacktricks/binary-exploitation/heap/large-bin-attack.md

3.9 KiB

Atak na duży kubełek

Zacznij od zera i opanuj hakowanie AWS dzięki htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Podstawowe informacje

Aby uzyskać więcej informacji na temat tego, co oznacza duży kubełek, sprawdź tę stronę:

{% content-ref url="bins-and-memory-allocations.md" %} bins-and-memory-allocations.md {% endcontent-ref %}

Można znaleźć świetny przykład w how2heap - atak na duży kubełek.

W zasadzie można zobaczyć, jak w najnowszej "obecnej" wersji glibc (2.35) nie jest sprawdzane: P->bk_nextsize, co pozwala zmodyfikować dowolny adres wartością dużego kawałka kubełka, jeśli spełnione są pewne warunki.

W tym przykładzie można znaleźć następujące warunki:

  • Zaalokowany jest duży kawałek
  • Zaalokowany jest duży kawałek mniejszy od pierwszego, ale w tym samym indeksie
  • Musi być mniejszy, więc musi iść pierwszy w kubełku
  • (Tworzony jest kawałek, aby zapobiec scaleniu z kawałkiem górnym)
  • Następnie pierwszy duży kawałek jest zwalniany, a zaalokowany jest nowy kawałek większy od niego -> Kawałek1 trafia do dużego kubełka
  • Następnie drugi duży kawałek jest zwalniany
  • Teraz podatność: Atakujący może zmodyfikować chunk1->bk_nextsize na [target-0x20]
  • Następnie zaalokowany jest większy kawałek niż kawałek 2, więc kawałek2 jest wstawiany do dużego kubełka, nadpisując adres chunk1->bk_nextsize->fd_nextsize adresem kawałka2

{% hint style="success" %} Istnieją inne potencjalne scenariusze, chodzi o dodanie do dużego kubełka kawałka, który jest mniejszy niż aktualny kawałek X w kubełku, więc musi zostać wstawiony tuż przed nim w kubełku, i musimy móc zmodyfikować bk_nextsize X, ponieważ właśnie tam zostanie zapisany adres mniejszego kawałka. {% endhint %}

Oto istotny kod z funkcji malloc. Dodano komentarze, aby lepiej zrozumieć, jak został nadpisany adres:

{% code overflow="wrap" %}

/* if smaller than smallest, bypass loop below */
assert (chunk_main_arena (bck->bk));
if ((unsigned long) (size) < (unsigned long) chunksize_nomask (bck->bk))
{
fwd = bck; // fwd = p1
bck = bck->bk; // bck = p1->bk

victim->fd_nextsize = fwd->fd; // p2->fd_nextsize = p1->fd (Note that p1->fd is p1 as it's the only chunk)
victim->bk_nextsize = fwd->fd->bk_nextsize; // p2->bk_nextsize = p1->fd->bk_nextsize
fwd->fd->bk_nextsize = victim->bk_nextsize->fd_nextsize = victim; // p1->fd->bk_nextsize->fd_nextsize = p2
}

{% endcode %}

To może być użyte do nadpisania zmiennej globalnej global_max_fast w libc, aby następnie wykorzystać atak na szybkie kubełki z większymi fragmentami.

Możesz znaleźć inną świetną wyjaśnienie tego ataku na stronie guyinatuxedo.