JIT SPRAY ÃÂÃÂÃÂÛØ× TDSS - Xakep Online
JIT SPRAY ÃÂÃÂÃÂÛØ× TDSS - Xakep Online
JIT SPRAY ÃÂÃÂÃÂÛØ× TDSS - Xakep Online
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
ВЗЛОМ<br />
0xXXYY0104 — начала <strong>JIT</strong>-шеллкода<br />
Память «RWX» c <strong>JIT</strong>-кодом<br />
до начала кода с XOR всегда постоянное. Дабы избежать нулевых<br />
байт в адресе ищем первый аргумент, в младших разрядах адреса<br />
не будет нулевых байтов, и первый такой адрес оказался 0x0104<br />
со значением десятого аргумента для XOR. В итоге окончательный<br />
указатель будет 0xXXYY0104, где XXYY могут быть любым значением<br />
из центральной части карты памяти, например 0x0607 или 0x0808 и<br />
т.д. Таким образом, ASLR побежден.<br />
ÈÍÚÅÊÖÈß ÊÎÄÀ<br />
Допустим, мы передали управление по адресу 0x07070104, там<br />
у нас значение 10-го аргумента из XOR-строки. Предположим,<br />
десятый параметр для XOR равен 0x01020304, а одиннадцатый —<br />
0x1a1b1c1d, тогда по адресу 0x07070104 будет следующий код:<br />
. . .<br />
07070104 0403 ADD AL, 3 ; 10-å çíà÷åíèå<br />
07070106 0201 ADD AL, [ECX] ; âòîðàÿ ÷àñòü<br />
-- âûðåçàíî 12 áàéò –<br />
0707011A 81F01D1C1B1A XOR EAX, 1A1B1C1D ; 11 çíà÷åíèå<br />
ñ XOR<br />
. . .<br />
Так как у нас LITTLE-ENDIAN система, то процессор берет значения<br />
«задом наперед», и вместо 0x0304 мы можем написать любые<br />
команды в оп-кодах. А вот 0x0201 мы должны заменить строго на<br />
14EB (EB14 = JMP +0x14), чтобы передать управление на одиннадцатый<br />
параметр. Когда мы говорили про Flash, было легче,<br />
так как там параметры шли один за другим, тут же у нас разрыв<br />
в 20 (0x14) байт, поэтому последние два байта надо «тратить» на<br />
переход между параметрами. К примеру, десятый и одиннадцатый<br />
параметр:<br />
..^0x14EB9090^0x14EBCC90^..<br />
Будут скомпилированы в:<br />
. . .<br />
07070104 90 NOP<br />
07070105 90 NOP<br />
07070106 EB14 JMP 0707011C<br />
-- âûðåçàíî 14 áàéò –<br />
0707011C 90<br />
NOP<br />
0707011D CC<br />
INT3<br />
0707011E EB14<br />
JMP …<br />
. . .<br />
У нас получилась связь между параметрами и выполнение кода,<br />
сначала пустые операторы, а затем прерывание. Итак, DEP мы тоже<br />
обошли...<br />
072<br />
<strong>JIT</strong>-ØÅËËÊÎÄ<br />
Теперь нам надо написать связанный шеллкод, который мы будем<br />
внедрять в память с помощью XOR в JavaScript. Дело кажется<br />
очень трудным, так как у нас есть всего два байта на команду. В<br />
Flash мы могли использовать и трех- и пятибайтные команды,<br />
но тут у нас жесткое ограничение. Кажется, что дело — труба, но<br />
вспомним еще одно важное отличие между <strong>JIT</strong> <strong>SPRAY</strong> в Flash и<br />
Safari — права на память. В Flash они были «R-X» (чтение и исполнение),<br />
а вот в Safari — «RWX», то есть мы можем еще и писать<br />
в память. Никогда не оставляй исполняемую память доступной на<br />
запись, ибо этот, казалось бы, маленький недочет делает возможным<br />
внедрение шеллкода. Поясню: мы заполнили память RWXблоками<br />
и, допустим, передали управление на <strong>JIT</strong>-блок 07070000.<br />
Там у нас будет связанный шеллкод с командами по два байта.<br />
Двух байт вполне достаточно для операции копирования — MOV<br />
[ECX], EAX (0x8901 в оп-кодах). Если ECX будет указывать на следующую<br />
страницу — 0x07080000, а в EAX будут содержаться первые<br />
четыре байта от шеллкода из метасплойта, то произойдет копирование<br />
шеллкода в RWX-память (W позволит нам делать это). Когда<br />
таким образом мы скопируем весь метасплойт-шеллкод кусками по<br />
четыре байта через регистр EAX, по адресу 0x0708000 будет лежать<br />
боевой шеллкод, причем в исполняемой памяти. Далее делаем<br />
JMP ECX (0xFFE1 — также два байта) на эту память, и код оттуда<br />
исполнится без лишних вопросов.<br />
ÄÂÀ ÁÀÉÒÀ ÁÎËÈ<br />
Мы умеем копировать и передавать управление с помощью<br />
регистров. Двух байт для этого достаточно, но прежде всего надо<br />
научиться с помощью этих двух байт заносить произвольные значения<br />
в регистры. MOV REG, VALUE занимает 5 байт. С помощью<br />
двух байт мы можем заносить значения только в младшие разряды<br />
регистра. Для этого будем использовать MOV AL, 01 (0xB001) и MOV<br />
AH, 02 (0xB402), так мы занесли в младшие разряды EAX 0x0201, и<br />
регистр в общем содержит 0xXXYY0201. Как же можно занести значение<br />
в старшие разряды? Первое, что мне пришло в голову — это<br />
побитовый сдвиг влево — SHL EAX, 1 (0xD1E0). Если мы хотим занести<br />
в регистр ECX-адрес блока, куда хотим копировать шеллкод,<br />
то заносим сначала в младшие регистры значение старших, потом<br />
делаем шестнадцать операций сдвига влево... и в итоге значения<br />
младших разрядов сдвигаются на место старших. Потом заносим<br />
еще раз уже значения младших разрядов. План хорош, да оказалось,<br />
что не очень — дело в том, что шеллкод получается очень<br />
большой, и из-за этого долго компилируется <strong>JIT</strong>-компилятором,<br />
но это не главное. Хуже всего то, что размер блока с компилированным<br />
кодом становится больше 0x10000 байт, а это значит, что<br />
блоки идут друг от друга с двойным разрывом: адрес блока N есть<br />
0x06060000, тогда адрес блока N+1 будет 0x06080000 (а должно<br />
быть 0x06070000). Таким образом, работоспособность <strong>JIT</strong> <strong>SPRAY</strong><br />
зависит от четности третьего разряда. Короче говоря, стабильность<br />
работы — 50%. Очевидно, что проблема в шестнадцати операциях<br />
XÀÊÅÐ 09 /140/ 10