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

Unicode-Buffer Overflows

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

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


4C dec esp

00 45 00 add byte ptr [ebp],al

58 pop eax

05 00 44 00 01 add eax,1004400h

00 45 00 add byte ptr [ebp],al

05 00 01 00 FF add eax,0FF000100h

00 45 00 add byte ptr [ebp],al

50 push eax

00 45 00 add byte ptr [ebp],al

44 inc esp

00 45 00 add byte ptr [ebp],al

5C pop esp

Разница в объеме ощутима, но зато какой результат! Все инструкции, согласно стандарту, формируют последовательность в формате 0х00ХХ, где ХХ – это какой-либо отличный от нуля байт. Думаю, теперь стало очевидным, что уязвимости такого типа могут успешно эксплуатироваться. Но возникает другой вопрос: как узнать, подойдет ли тебе та или иная инструкция? Можно, конечно, перебирать опкоды и в конце концов найти все подходящие. Но лучше поступить иначе. Я предполагаю, что тебя в основном интересует платформа IA32 (Intel Architecture 32). Тогда смело грузишь с intel.com доки о командах процессора и смотришь, какие из инструкций доступны для использования.

Использование регистров

В первую очередь определись с регистрами. Тут все зависит от операций, в которых они принимают участие, а, точнее, от их размера. Например, push занимает 5 бит. Если использовать его с 32-битными регистрами, то эта операция будет занимать всего лишь один байт.

Также тебе доступны регистры r8 (ah, al, bh, bl…). Вопрос о пригодности решается в зависимости от команд и регистров. Поэтому достаточно сказать, что в общем случае ты можешь использовать все r32 и r8 регистры. Естественно, некоторые операции не могут подойти из-за своего размера или же операнда/операндов. Но уже сейчас заверю тебя, что r16 (ax, bx, cx…) использовать не получится, однако, изменяя регистры r8 и r32, ты все-таки неявно контролируешь r16. Хотя, я думаю, этого запаса тебе будет вполне достаточно.

Работа с памятью

С регистрами определились, теперь поговорим об их использовании. Команда mov значительно урезана из-за наложения на нее ряда ограничений. Пересылка данных из регистра в регистр в читаемом виде невозможна. То есть mov eax,ebx ты не воспользуешься (правда, это можно обойти, например, используя команду xchg или стек). Зато стали доступны кое-какие другие ее возможности:

Возможности команды mov

89 00 mov dword ptr [eax],eax

8B 00 mov eax,dword ptr [eax]

88 00 mov byte ptr [eax],al

8A 00 mov al,byte ptr [eax]

8C 00 mov word ptr [eax],es

8E 00 mov es,word ptr [eax]

Также можешь использовать ее для работы с памятью, указав адрес в качестве приемника или источника. Но помни: так как shell-код находится в Unicode, то используемые адреса должны быть оформлены соответственно, то есть для работы с памятью тебе необходимо использовать адреса вида 0хХХ00ХХ00.

Листинг

A0 00 ХХ 00 ХХ mov al,byte ptr ds:[ХХ00ХХ00h]

A1 00 ХХ 00 ХХ mov eax,dword ptr ds:[ХХ00ХХ00h]

A2 00 ХХ 00 ХХ mov byte ptr ds:[ХХ00ХХ00h],al

A3 00 ХХ 00 ХХ mov dword ptr ds:[ХХ00ХХ00h],eax

Кроме всего этого, есть еще команда копирования строк: A4 movs byte ptr [edi],byte ptr [esi]. Вот и весь джентльменский набор для команды mov. Как видишь, эта команда подходит для работы с памятью, а значит, может быть использована для изменения определенных областей программы или стека. Также помни о возможностях добавления r8 регистров к любой области памяти:

Назад на стр. 045-056-1  Содержание  Вперед на стр. 045-056-3