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 регистров к любой области памяти: |