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

Ultimate adventure

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

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


Нажимаем <Enter>, переходя к началу функции, а затем входим в меню View\Open Subview\Cross Reference, открывая окно с перекрестными ссылками, каждая из которых ведет к точке вызова нашей функции. В зависимости от особенностей компилятора и сексуальных наклонностей программиста, проектировавшего исследуемое приложение, вызов может быть как непосредственным (типа CALL our_func), так и косвенным (типа mov ecx, pClass/mov ebx,[ecx + 4]/call ebx/…/pClass DD xxx/DD offset our_func). В последнем случае перекрестные ссылки на out_func будут вести к DD offset our_func и определить место ее реального вызова будет не так-то просто! Обычно хакеры в таких случаях нанимают отладчик, устанавливая на our_func точку останова, а затем записывают EIP всех мест, откуда она вызывается (кстати, наличие интегрированного отладчика в последних версиях IDA существенно ускоряет этот процесс).

И вот мы находимся в окрестностях вызывающего кода! Если аргумент, определяющий размер принимаемого буфера, представляет собой непосредственное значение (что-то типа push 400h, см. листинг 2) – это хороший знак, и дыра, скорее всего, ждет нас где-то поблизости. Если же это не так, не стоит отчаиваться: лучше, прокручивая курсор вверх, посмотреть, где этот размер инициализируется. Может быть, он все-таки представляет собой константу, передаваемую через более-менее длинную цепочку переменных или даже аргументов материнских функций!

(Листинг 2. Непосредственное значение максимальной длины буфера, передаваемое функции, хороший признак возможного переполнения)

.text:00401017 push 400h

.text:0040101C mov ecx, [ebp+var_8]

.text:0040101F push ecx

.text:00401020 call _fgets

Теперь найдем код, осуществляющий выделение памяти под буфер (обычно за это отвечают функции malloc и new). Если аргумент, определяющий размер выделяемой памяти, также представляет собой константу, причем эта константа меньше предельно допустимой длины возвращаемых данных, дыра найдена и можно смело переходить к фазе анализа возможных способов воздействий на переполняющийся буфер через поля входных данных.

Законы безопасного проектирования гласят: прежде чем выделять буфер, определи точный размер данных, которые ты собираешься положить туда. Другими словами, в правильной программе вызову malloc или new всегда предшествует strlen, GetWindowTextLength или что-то типа того. В противном случае программа потенциально уязвима. Разумеется, наличие превентивной проверки размера само по себе еще не гарант стабильности, поскольку далеко не во всех случаях затребованный размер определяется правильно, особенно если в буфер сливаются данные с нескольких источников.

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