Unicode-Buffer Overflows

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

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

aka DigitalScream (digitalscream@real.xakep.ru)

Проблемы эксплуатации формата Unicode и написание Unicode shell-кодов

Некоего хакера интересовал один сервер, и тут прошел слух, что есть переполнение в одном из демонов. Он написал программу, посылавшую вместо пароля строку из 300 букв «А». Уязвимость имела место, но адрес возврата был не 0x41414141, а 0x00410041. Хакер и не предполагал, что столкнется с Unicode-переполнениями…

Что такое Unicode

Эра компьютеров началась задолго до появления интернета. Но уже тогда было много людей, которые имели отношение к информационным технологиям. Однако, так как ОС использовали только 8-битные ASCII символы, то для локализации системы под нужный язык пришлось вводить понятие кодировки символов. Вскоре каждая страна имела свою кодировку, а некоторые, например Россия, даже не одну, а несколько :). Но очень быстро (в связи с глобальным ростом интернета) количество используемых кодировок сильно увеличилось и люди часто просто не могли получить нужную информацию. Назревала необходимость создания единой системы, которая бы систематизировала этот процесс. И тут появился Unicode. Формат Unicode очень простой. Он отводит на одну кодировку ровно 128 символов, сам символ представляется двумя байтами. Первый байт – это номер кодировки, а второй – номер символа. Так, английская кодировка имеет индекс 0, а символ «А» – 0x41 в этой кодировке, то есть в Unicode буква «А» будет 0x0041. Именно поэтому хакер получил адрес возврата 0x00410041 – система перевела его ввод в Unicode.

Проблемы эксплуатации

Очевидно, что эксплуатировать уязвимости такого рода в чистом виде нельзя. Ведь если передать в shell-коде команду 83 C4 2D add esp, 2Dh, то он после конвертирования превратится в 00 83 00 C4 00 2D add byte ptr [ebx+2D00C400h], al. А это не совсем то, чего мы ожидаем. Поэтому такие уязвимости требуют иного подхода – такого, который позволил бы добиться исполнения shell-кода, а не бессмысленных команд. Как быть? Один из вариантов решения данной проблемы очень прост. Дело в том, что если мы каким-то образом можем указать приложению, что передаваемые данные имеют формат Unicode, то оно уже не будет пытаться повторно их конвертировать. Но этот метод не всегда подходит в силу особенностей эксплуатируемых программ. Он может подойти к программам, которые обрабатывают большие текстовые информационные блоки, например к редакторам, браузерам и т.д. Естественно, может случиться и так, что любое другое приложение адекватно отреагирует на полученные данные, хотя такие случаи довольно редки.

Unicode shell-код

Поскольку программа преобразовывает полученные данные в Unicode, то нужно написать такой shell-код, который будет работать после обработки. Если ты считаешь, что это невозможно, то глубоко ошибаешься! Конечно, придется отказаться от многих инструкций, некоторых регистров, но shell-код может существовать! Надо всего лишь подойти к процессу творчески. Помнишь прошлый пример? Его можно написать следующим образом:

Листинг

00 А5 add ch,dh

54 push esp

00 45 00 add byte ptr [ebp],al

Содержание  Вперед на стр. 045-056-2
ttfb: 22.279024124146 ms