Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #81, СЕНТЯБРЬ 2005 г.

Куча с горкой

Хаштамов Адиль (adi1@ok.kz)

Хакер, номер #081, стр. 081-074-1


Основы heap-переполнений под Windows

Если порыться в Сети, можно найти огромное количество материалов, описывающих различные методы всевозможных переполнений. Переполнения в стеке, buffer overflow, format string - все это в деталях описано на многих сайтах. Однако если присмотреться, почти все примеры и описания популярных методик приведены именно для unix-систем. Лезть в кучу специфических для Windows моментов никто не желает. По этой причине мы решили приготовить для тебя интересный материал о популярном среди хакеров и вирмейкеров приеме, с помощью которого распространяется добрая половина сетевых червей, - о heap overflow.

[что такое heap]

Прежде всего давай разберемся, что такое heap. Любой школьник тебе скажет, что с английского это слово переводится как «куча». В нашем же компьютерном контексте слово «heap» обозначает специальную область зарезервированного адресного пространства, выделение и освобождение памяти в котором реализуется при помощи специальных системных функций. При работе с кучей программистам доступно собственное огромное виртуальное адресное пространство, по емкости значительно превосходящее объем реальной физической памяти, установленной в компьютере. Все основные функции по работе с кучей (выделение, освобождение и создание блоков памяти) расположены в системной библиотеке ntdll.dll. Изначально каждому приложению в Windows выделяется одна мегабайтная куча, а далее уже, по мере необходимости, объем выделяемой памяти автоматически увеличивается. В свою очередь приложение может создавать собственное адресное пространство с помощью специальных функций. Память в куче выделяется областями, причем в каждой области можно создать блоки памяти, которые будут расположены в сегментах. Для управления каждым таким блоком создается свой специальный заголовок, который изображен на рисунке 1.

Здесь Size обозначает размер блока, Previous Size - размер предыдущего блока, Segment Index - индекс сегмента, в котором расположен блок, Unused - количество неиспользуемых байт в блоке, Tag Index - индекс метки, а Flags - флаг блока. Флаги могут быть следующими:

0x01 - HEAP_ENTRY_BUSY

0x02 - HEAP_ENTRY_EXTRA_PRESENT

0x04 - HEAP_ENTRY_FILL_PATTERN

0x08 - HEAP_ENTRY_VIRTUAL_ALLOC

0x10 - HEAP_ENTRY_LAST_ENTRY

0x20 - HEAP_ENTRY_SETTABLE_FLAG1

0x40 - HEAP_ENTRY_SETTABLE_FLAG2

0x80 - HEAP_ENTRY_SETTABLE_FLAG3

При освобождении блока памяти он принимает вид, изображенный на рисунке 2.

Здесь Flink - указатель на следующий освобожденный блок, а Blink - указатель на предыдущий освобожденный блок.

[другая разметка]

Для упрощения управления свободными блоками используется так же разметка по количеству единиц выделения. Единицы можно высчитать таким образом. Объем каждого выделяемого блока памяти равен 8. К примеру, если приложение выделяет блок размером в 64 байта, тогда единиц адресации получится 64/8 = 8. Каждая куча стартует со структуры из 128 массивов LIST_ENTRY, которую можно посмотреть в winnt.h/win.h. В каждый индекс массива записывается

свободный блок, нумерованный по единицам выделения. В нашем примере мы выделили блок равный 64 байтам, единиц выделения получилось 8. Выходит, что при освобождении блока памяти в массив FreeList (массив свободных блоков) под индексом 8 запишется наш освобожденный блок. Учти, что первый индекс FreeList не используется из-за того, что блок размером в 8 байт не может существовать. Нумерация индексов начинается с 2-х, нулевой индекс используется для хранения освобожденных блоков памяти более 1016 байт.

Содержание  Вперед на стр. 081-074-2