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

МАССИВное переполнение

Мысла Владислав

Спецвыпуск Xakep, номер #045, стр. 045-030-3


Листинг

Пример 5. Использование переполнения массивов № 3

char szPassword [0xFF];

...

void CreateData( long lDefaultIndex, long lValue ) {

long lpNewData[0xFF];

ZeroMemory( lpNewData, 0xFF );

lpNewData[lDefaultIndex] = lValue;

...................................

}

void ShowPassword() {

ShowMessage( "Password: %s", szPassword ); }

...

Массив lpNewData является временным, и поэтому память для него выделяется в стеке. Учитывая архитектуру стека и местоположение буфера, можно говорить о том, что, если в качестве индекса указать число, превосходящее размеры массива, оно перезапишет собой данные, находящиеся в верхних адресах. А среди них есть и адрес возврата для выхода из функции, поэтому если передать функции параметры 0х101 и любое другое число "A", то при выходе из функции управление передастся на адрес, указанный в переменной "A". Так, например, если знать адрес функции ShowPassword и указать его в качестве второго параметра, то программа покажет пароль админа. Но это уже – переполнение стека, рассмотрение которого в рамки данной статьи не входит. Если память под массив выделяется в куче, то получить управление можно, перезаписав глобальную таблицу смещений функций. Способов есть множество, их работоспособность определяется конкретной архитектурой уязвимого приложения.

Обход ограничений на размерность массива

Однако не все так просто. Во избежание переполнений в обработке массивов программеры используют проверки на указанный индекс элемента. Если он больше размера массива, то операция отменяется (пример 6).

Листинг

Пример 6. Использование переполнений массивов с проверкой индекса

char szPassword [0xFF];

...

void CreateData(int intDefaultIndex, int intValue ) {

long lpNewData[0xFF];

if( intDefaultIndex < 0xFF ) return;

ZeroMemory( lpNewData, 0xFF );

lpNewData[intDefaultIndex] = intValue;

...................................

}

Но и здесь есть выход! Переменная intDefaultIndex является числом, но числом со знаком. Поэтому, хотя проверка на размер производится, значение не проверяется на отрицательность. Это значит, что, если в прошлом примере ты указал номер элемента 0x101, то теперь необходимо просто вычислить его: индекс = старый_индекс + 0x80000000. Таким образом, появляется возможность обхода проверки на указанный индекс элемента.

Теперь ты знаком с уязвимостями класса Array Overflow. Нужно иметь в виду возможность такого взлома и думать о своей защите.

Массив – это последовательность элементов одинаковой структуры. Например, массив из чисел – это последовательность чисел и ничего другого.

По сути, переполнение массивов – это обычное переполнение буфера, происходящее при обработке массивов.

Более детальную информацию о целочисленных переполнениях ты можешь найти в статье "Integer Overflow".

Атака на переполнение массива может быть использована как способ получения контроля над исполнением программы.

Назад на стр. 045-030-2  Содержание