Переполнение буфера в heap. 1 серия

kas1e

Xakep, номер #057, стр. 057-074-2


5. Initialized data - сегмент инициализированных данных. Если мы объявим переменную как глобальную и присвоим ей значение в исходном тексте программы, например, так: char hahah = "im was here";, то строка hahah разместится в этом сегменте инициализированных данных.

6. Text segment (сегмент текста). Это read-only сегмент, включающий в себя все инструкции программы.

7. Разделяемые библиотеки. Функции общего и не очень общего ;) назначения.

0xBFFFFFFF |-------------------|

| |

| . |

| . |

| . |

| . |

| и т.д. |

1 |env/argv указатели |

| argc |

|-------------------|

| |

2 | стек |

| |

| | |

| | |

| V |

/ /

\ \

| |

| ^ |

3 | | |

| | |

| |

| heap |

|-------------------|

4 | bss (data segment)|

|-------------------|

5 | initialized data |

|-------------------|

6 | text |

|-------------------|

7 | shared libraries |

| etc. |

0x8000000 |-------------------|

Примерно так выглядит образ запущенной ELF программы в памяти. Непосредственно из самой программы я буду брать некоторые данные, например, значение Global Offset Table. Об этом позже, а пока рассмотрим более подробно heap область.

Подробно о heap

Существуют разные способы выделения памяти (всего 4). Нас будет интересовать способ, когда выделяется дополнительная память, т.к. она берется именно из heap области. Heap - это некая виртуальная память, расположенная рядом с сегментом данных. Ее размер меняется в зависимости от самих запросов на выделение памяти. Например, при использовании библиотечной функции malloc(), происходит запрос на выделение дополнительной памяти, которая в дальнейшем и будет использоваться для динамического размещения данных. Или, скажем, функция ctime() - она тоже требует выделения дополнительной памяти. Вообще, чуть ниже мы поговорим более подробно об этих функциях, работающих с heap, а пока рассмотрим интересную зависимость между heap и bss. Дело в том, что heap сливается с bss не просто так: данные, данные и вдруг бац - пошел heap. Нет. Между ними есть 4 байта некого адреса, который называется "break address". Изменение размера сегмента данных по существу заключается в изменении break адреса. Для изменения его значения есть 2 системных вызова: brk и sbrk. Первый вызов (brk) позволяет непосредственно установить значение break адреса, второй вызов (sbrk) позволяет увеличить значение break адреса на определенную величину (тут есть несколько нюансов, например, размеры порций выделяемой памяти; это оставим самым пытливым). Сразу резонный вопрос: зачем же нам нужно вообще изменять этот break адрес? Затем, что именно это и есть граница между heap и bss, и, используя именно эти вызовы, мы выделяем память из heap. Так что функции malloc и другие - это не что иное, как простые "обертки" для brk и sbrk. Рассмотрим рисунок:

Назад на стр. 057-074-1  Содержание  Вперед на стр. 057-074-3