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

Integer Overflow

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

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


aka DigitalScream (digitalscream@real.xakep.ru)

Числа как одна из первопричин возникновения ошибок

Он мог с легкостью написать эксплоит к 0day-уязвимости, он быстро стал известным в узких кругах и одним из первых узнавал о новых изъянах… Однажды ему принесли исходник, украденный у крупной фирмы. Это была реализация клиентской части для банковского персонала. Работенка предстояла не из легких…

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

Приступим…

Давай для начала вспомним кое-что из теории представления чисел в IA32. Для работы с числами на уровне машинных кодов используются 8-, 16-битные и т.д. регистры. Количество используемых бит зависит от того, с какими типами программа имеет дело. А поскольку для хранения значений численных переменных отводится ограниченное количество разрядов (битов), то появляются такие понятия, как максимальное и минимальное значения для каждого из типов.

Можно заметить, что максимальное значение типа определяется не только количеством его разрядов. Если идет речь о числах со знаком, то диапазон принимаемых значений уменьшается ровно в два раза. То есть, если для беззнакового типа byte диапазон значений от 0 до 255, то для знакового варианта он будет от –127 до +127. На машинном уровне число считается положительным, если его самый старший разряд равен нулю, и отрицательным в противоположном случае. Таким образом, старший разряд используется для служебных целей, а для представления числа остаются свободными 7 бит, которыми можно описать только 0x7F значений. В тоже время для беззнаковых чисел такого ограничения нет, и поэтому они используют все 8 разрядов. Это утверждение справедливо для всех остальных целочисленных типов, разница заключается только в разрядности типа.

Поехали дальше. Следующее, что нужно помнить, – числа носят циклический характер. Это значит, что если взять беззнаковую переменную типа long, которая равна единице, и увеличивать ее до тех пор, пока переменная не достигнет максимального значения 0xFFFFFFFF (4294967295), то после следующего инкремента ее значение будет равно нулю, потом единице и т.д. Если же мы используем знаковый тип, то при достижении максимального положительного значения 0x7FFFFFFFF(2147483647) следующий шаг увеличит значение до 0x80000000. А это уже отрицательное число, потому как оно больше половины из 0xFFFFFFFF на 1, и новым значением переменной будет 2147483648. При каждой итерации значение переменной будет расти. Но оно будет стремиться к нулю (ведь -2147483648 > 0), а когда значение станет равным 0xFFFFFFFF (-1), то следующий шаг установит значение переменной в нуль. После чего повторяется заново. Как ты мог убедиться, числам не стоит особо доверять. Они имеют способность радикально изменять свои значения в самых непредсказуемых блоках программы. Причем результаты могут быть фатальны для сохранения целостности реализованной системы безопасности, приводя к возникновению других более опасных уязвимостей. А причин может быть множество, каждая из которых – проявление специфических особенностей представления целочисленных типов.

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