Кодирование.С трудом верится в целесообразность чрезмерного усложнения своей работы. Большинство известных программ переполнения буфера состоят из блоков нечитаемого машинного кода. Вряд ли это кому-то понравится. Есть гораздо лучший способ кодирования полезной нагрузки: напишите код полезной нагрузки на языке C, C++ или встроенном ассемблере, а затем скопируйте откомпилированный код в программный код полезной нагрузки. Многие компиляторы запросто объединяют код на ассемблере и C в единую программу. Подобный способ написания созданных на разных языках программ называется способом комплексирования программ (fusion technique).
Комплексирование программ – сравнительно простой способ написания и компиляции программ на ассемблере с нетрадиционными ухищрениями. Некоторые из них обеспечивают внедрение в рабочие области памяти других процессов. Подобное Windows NT обеспечивает для аутентифицированных пользователей. Но при переполнении буфера того же может добиться и пользователь, не прошедший аутентификации. В любом случае программный код вставляется в пространство удаленного процесса.
Распыление динамически распределяемой памяти («куча»).(Динамически распределяемая память («куча») – область памяти, выделяемая программе для динамически размещаемых структур данных.) Во время исследования возможности использования уязвимости. IDA (Increment/Decrement Adress) информационного сервера Internet IIS (Internet Information Server) 4/5/6 столкнулись со странной ситуацией. Было обнаружено, что диапазон адресов, на которые мог ссылаться при переполнении буфера регистр EIP, сильно ограничен. Уязвимость. IDA была обусловлена переполнением буфера в результате расширения строки символов. Другими словами, бралась строка «AAAA» (в шестнадцатеричном представлении 0x41414141) и преобразовывалась к шестнадцатеричному значению 0x0041004100410041. Это было очень неприятно, так как в область памяти по адресу, начинающемуся с шестнадцатеричного значения 0x00, никакой код никогда не загружался. Поэтому традиционный способ передачи управления программному коду полезной нагрузки с помощью команд перехода по содержимому регистра (jmp ESP или jmp reg) оказался непригодным. Другим неприятным проявлением расширения строки символов было размещение нулевых байтов между байтами программного кода полезной нагрузки. Для преодоления этой проблемы был придуман новый способ, получивший название «принуждение динамически распределяемой памяти» (forcing the heap). Этот способ относится к классу нарушения «кучи» (heap violation). О наиболее известных атаках на динамически распределяемую память будет рассказано позднее, а способ «принуждения динамически распределяемой памяти» отличается от них тем, что его целью является переполнение стека, а не кучи. В ряде случаев этот способ оказался полезным, в том числе и при переполнении буфера из-за расширения строк.
При исследовании доступных адресов памяти вида 0x00aa00bb, где aa и bb – управляемые символы, было обнаружено, что этот диапазон адресов информационный сервер Internet IIS отводит под динамически распределяемую память. Всякий раз при передаче запроса информационному серверу Internet он сохраняет в динамически распределяемой памяти данные сеанса. Было найдено, что в этом же диапазоне памяти сохранялись пользовательские переменные окружения протокола HTTP, но ими нельзя было воспользоваться. Способ распыления динамически распределяемой памяти заключается в создании в ней последовательности команд NOP и передачи туда управления. Это позволило переполнить стек, получить контроль над регистром EIP и с помощью команды перехода в область динамически распределяемой памяти выполнить размещенный в ней программный код.
Преимущества предложенного способа заключаются в использовании различных ухищрений обхода нулевых байт, вставленных в программный код полезной нагрузки в результате расширения байтов, а также в значительном увеличении размера кода полезной нагрузки, загружаемого в доступную память. Способ удобен еще и тем, что не требует задания смещения в команде передачи управления в область памяти с загруженной динамически подключаемой библиотекой. Достаточно только сослаться на область динамически распределяемой памяти.
Обратная сторона способа заключается в необходимости размещения в области динамически распределяемой памяти длинной последовательности команд NOP, позволяющей загрузить нужный код по желаемым адресам памяти.
Читать дальше
Конец ознакомительного отрывка
Купить книгу