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

Ultimate adventure

Крис Касперски aka мыщъх

Спецвыпуск: Хакер, номер #058, стр. 058-028-6


С локальными переменным в этом плане намного сложнее, поскольку их размер приходится явным образом задавать на этапе компиляции программы, когда длина возвращаемых данных еще не известна. Неудивительно, что переполняющиеся буфера чаще всего обнаруживаются именно среди локальных переменных.

Локальные переменные хранятся в стековых фреймах (англ. frames), также называемых кадрами или автоматической памятью. Каждой функции выделяется "персональный" кадр, в который помещаются все принадлежащие ей локальные переменные. Формирование кадра чаще всего осуществляется машинной командой "SUB ESP, xxx", реже – "ADD ESP, –xxx", где xxx - размер кадра в байтах. Текущие версии IDA PRO по умолчанию трактуют все непосредственные значения как беззнаковые числа, и преобразование "xxx" в " xxx" приходится осуществлять вручную путем нажатия на клавишу < – >.

К сожалению, "разобрать" монолитный кадр на отдельные локальные переменные в общем случае невозможно, поскольку компилятор полностью уничтожает исходную информацию и анализ становится неоднозначным. Однако для наших целей возможностей автоматического анализатора IDA PRO более чем достаточно. Мы будем исходить из того, что локальные буфера чаще всего (но не всегда!) имеют тип byte *, а их размер составляет по меньшей мере 5 байт (правда, как показывает статистика, ошибки переполнения чаще всего встречаются именно в четырехбайтовых буферах, которые при беглом анализе легко спутать с DWORD).

Рассмотрим в качестве примера кадр стека, "разобранный" автоматическим анализатором IDA PRO, и попытаемся обнаружить в нем локальные буфера (см. листинг 3):

(Листинг 3. Локальные переменные, автоматически восстановленные IDA)

.text:00401012 sub_401012 proc near ; CODE XREF: start+AF?p

.text:00401012

.text:00401012 var_38 = dword ptr -38h

.text:00401012 var_34 = byte ptr -34h

.text:00401012 var_24 = byte ptr -24h

.text:00401012 var_20 = byte ptr -20h

.text:00401012 var_10 = dword ptr -10h

.text:00401012 var_C = dword ptr -0Ch

.text:00401012 var_8 = dword ptr -8

.text:00401012 var_4 = dword ptr -4

.text:00401012

Переменная var_38 имеет тип DWORD и занимает 4 байта (размер переменной определяется путем вычитания адреса текущей переменной из адреса следующей: –34h – (– 38h) == 4h). На буфер она похожа мало.

Переменная var_34 имеет тип BYTE и занимает 10h байт, что типично для локального буфера. Тоже самое можно сказать и о переменной var_20. Переменная var_24 хотя и имеет тип BYTE, занимает всего 4 байта, поэтому может быть как компактным локальным буфером, так и простой скалярной переменной (причем последние встречаются намного чаще). До тех пор пока на предмет переполнения не будут исследованы все явные буфера, возиться с подобными "кандидатами в буфера" нет никакого смысла.

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

Назад на стр. 058-028-5  Содержание  Вперед на стр. 058-028-7