Thursday, June 23, 2011

3D графика как инструмент реверс-инженера

Интерфейс взаимодействия между человеком и компьютером за прошедшие десятки лет практически не претерпел фундаментальных изменений, и в настоящее время по прежнему представляет собой либо командную строку, либо плоские "окна". Однако, существуют определённые научные дисциплины, обработка данных для которых с помощью компьютера не мыслима без использования 3D графики. К таким дисциплинам относятся различного рода инженерия, клеточная и молекулярная биология, физика высоких частиц и многие другие. Одним словом, все те области, которые требуют работы с большими объёмами данных со сложной структурой, организацией и множественными связями.

При работе в области программирования а в особенности - реверс-инженеринга, технический специалист, вроде бы как, тоже сталкивается с подобными данными, однако, на сегодняшний день 3D графика (или что-либо с ней связанное), как рабочий инструмент, не имеет широкого распространения в области информационной безопасности. В данной записи речь будет идти про интеграцию библиотеки UbiGraph в программный пакет IDA Pro с целью получения средства для визуализации графа связей между процедурами исследуемого кода.

UbiGraph представляет собой универсальную библиотеку, которая предоставляет API для построения динамических трёхмерных графов. Благодаря использованию клиент-серверной архитектуры со взаимодействием через XML-RPC for C он имеет легковесные биндинги для большинства популярных языков программирования. Для того что бы увидеть возможности этой интереснейшей разработки достаточно просмотреть ролики на YouTube по соответствующим ключевым словам.

Ниже продемонстрирован пример кода на Python, использующий UbiGraph API.
 1 import ubigraph
 2 
 3 U = ubigraph.Ubigraph()
 4 U.clear()
 5 
 6 x = U.newVertex(shape="sphere", color="#ffff00")
 7 
 8 smallRed = U.newVertexStyle(shape="sphere", \
 9   color="#ff0000", size="0.2")
10 
11 previous_r = None
12 for i in range(0, 10):
13 
14   r = U.newVertex(style=smallRed, label=str(i))
15   U.newEdge(x, r, arrow=True)
16 
17   if previous_r != None:
18 
19     U.newEdge(r, previous_r, spline=True, stroke="dashed")
20 
21   previous_r = r
22

Однако, UbiGraph обладает рядом недостатков:
  • Закрытый исходный код сервера.
  • Исполняемый файл сервера доступен только для платформ Linux и OS X
  • Проект, судя по всему, заброшен и не развивается с 2008-го года. Связаться с разработчиком что бы разузнать о деталях текущего состояния проекта (или получить на каких-либо условиях его исходный код) мне так и не удалось.
Но даже не смотря на все эти недостатки - не представляется реальным найти альтернативные разработки, которые бы по гибкости и возможностям приближались бы к UbiGraph. В связи с этим было решено провести ряд экспериментов именно с ним, поставив перед собой цель выяснить на практике перспективы применения 3D визуализаций в реверс-инженеринге.

Рассмотрим "обычный" граф процедур в IDA, который был получен при помощи плагина MyNav:



... и вид этого же (относительно простого и наглядного) графа в 3D, который строится модифицированной для работы с сервером UbiGraph версией MyNav 1.1:



На первый взгляд - существенных преимуществ 3D в данном примере не имеет, однако, благодаря тому, что такой граф можно вращать во всех плоскостях и масштабировать без существенных "тормозов" даже при огромном количестве узлов - его становится банально удобнее использовать для навигации по коду исследуемого файла.

Разумеется, удобство является сугубо индивидуальным понятием, и каждый человек принимает относительно него какие-либо выводы опираясь исключительно на собственные ощущения. Я позиционирую результат проделанной мной работы как возможность взглянуть на привычный всем анализ дизасембилрованного кода под новым, интересным углом, а завершенным продуктом, который "совершит революцию", инструмент, о котором идет речь, ни коим образом не является уж точно.

Настройка рабочей среды


Как было упомянуто выше, UbiGraph запускается только на Linux и OS X. Исследователи, которые работают с IDA в среде данных операционных систем, не будут обременены сложными настройками в принципе, поэтому, далее подробно будет рассказано о настройке рабочей среды для UbiGraph на базе Windows.

Для этого потребуется следующий софт:
  • Виртуальная машина с установленным Linux (дистрибутив не принципиален).
  • X-Сервер для Windows (я использую Xming).
  • IDA Pro версии от 5.7 и старше (можно использовать 6.1 Demo c официального сайта).
  • Python плагин для IDA (для версии Python 2.6.x) и, разумеется, установленный в системе интерпретатор Python 2.6.x.
Суть всех манипуляций по настройке заключается в том, что UbiGraph будет запущен в виртуальной машине с Linux, но при этом его окно с графом будет выводится на Windows-хост благодаря работающему на нем X-серверу:


На Linux загружаем и распаковываем последнюю версию UbiGraph:
# wget http://ubietylab.net/files/alpha-0.2.4/UbiGraph-alpha-0.2.4-Linux32-Debian-4.tgz
# tar -xpf UbiGraph-alpha-0.2.4-Linux32-Debian-4.tgz
# cd UbiGraph-alpha-0.2.4-Linux32-Debian-4/bin/
# ls -la
total 1658
drwxr-xr-x 2 user user     120 May 29  2008 .
drwxr-xr-x 6 user user     328 May 29  2008 ..
-rw-r--r-- 1 user user     927 May 29  2008 REQUIRED_LIBS.txt
-rwxr-xr-x 1 user user 1689496 May 29  2008 ubigraph_server

После этого в Linux систему потребуется установить все библиотеки, с которыми динамически слинкован исполняемый файл ubigraph_server:
# ldd ubigraph_server
 linux-gate.so.1 =>  (0xffffe000)
 libpthread.so.0 => /lib/libpthread.so.0 (0xb789d000)
 libglut.so.3 => /usr/lib/libglut.so.3 (0xb7869000)
 libGL.so.1 => //usr/lib/opengl/xorg-x11/lib/libGL.so.1 (0xb7811000)
 libidn.so.11 => /usr/lib/libidn.so.11 (0xb77de000)
 libstdc++.so.6 => /usr/lib/gcc/i686-pc-linux-gnu/4.4.3/libstdc++.so.6 (0xb76ed000)
 libm.so.6 => /lib/libm.so.6 (0xb76c7000)
 libgcc_s.so.1 => /usr/lib/gcc/i686-pc-linux-gnu/4.4.3/libgcc_s.so.1 (0xb76a9000)
 libc.so.6 => /lib/libc.so.6 (0xb7565000)
 libGLU.so.1 => /usr/lib/libGLU.so.1 (0xb74f6000)
 libdl.so.2 => /lib/libdl.so.2 (0xb74f2000)
 /lib/ld-linux.so.2 (0xb78c8000)
 libX11.so.6 => /usr/lib/libX11.so.6 (0xb73d2000)
 libXext.so.6 => /usr/lib/libXext.so.6 (0xb73c1000)
 libXxf86vm.so.1 => /usr/lib/libXxf86vm.so.1 (0xb73bb000)
 libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0xb73b7000)
 libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0xb73b1000)
 libX11-xcb.so.1 => /usr/lib/libX11-xcb.so.1 (0xb73ae000)
 libxcb-glx.so.0 => /usr/lib/libxcb-glx.so.0 (0xb739a000)
 libxcb.so.1 => /usr/lib/libxcb.so.1 (0xb737f000)
 libdrm.so.2 => /usr/lib/libdrm.so.2 (0xb7374000)
 libXau.so.6 => /usr/lib/libXau.so.6 (0xb7370000)
 libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0xb736a000)
 librt.so.1 => /lib/librt.so.1 (0xb7360000)

Обычно, данный шаг не влечет за собой каких-либо проблем, и в моем Gentoo ubigraph_server без проблем запустился после установки всего, что фигурирует в выдаче ldd выше. Далее, на Windows следует запустить X-Сервер (Xming), для этого удобно создать ярлык со следующей командной строкой:
"С:\Program Files\Xming\Xming.exe" -clipboard -ac -multiwindow :0

После этого в Linux запускаем ubigraph_server:
# DISPLAY=192.168.254.1:0 ./ubigraph_server
freeglut (./ubigraph_server): Unable to create direct context rendering for window 'Ubigraph'
This may hurt performance.
freeglut (./ubigraph_server): Unable to create direct context rendering for window 'freeglut menu'
This may hurt performance.
1 processors
Using single-level layout.
Running Ubigraph/XML-RPC server.

... где 192.168.254.1 -- IP адрес Windows хоста с работающим X-Сервером. Если настройки верны и все шаги были выполнены правильно -- в Windows системе появится пустое чёрное окно UbiGraph. После этого переходим к настройкам IDA Pro.

Настройка IDA Pro


В качестве основы для плагина, который позволял бы выводить граф процедур с помощью UbiGraph, мной был использован написанный на Python плагин MyNav:

MyNav is a plugin for IDA Pro to help reverse engineers in the most typical task like discovering what functions are responsible of some specifical tasks, finding paths between "interesting" functions and data entry points.

Разработанный патч для данного плагина добавляет в его классы построения графов код взаимодействия с сервером UbiGraph. Архив, который включает в себя помимо патча уже модифицированную версию MyNav 1.1 доступен для загрузки в репозитории проекта IDA-UbiGraph на GitHub.

Установка плагина происходит в несколько шагов:
  1. Установите IDAPython согласно инструкциям в его документации.
  2. Из архива IDA-UbiGraph скопируйте в каталог установленной IDA Pro директорию mynav-1.1-ubigraph.
  3. Из архива IDA-UbiGraph скопируйте в каталог установленной IDA Pro файл ubicallback.pyd -- это Python модуль, который используется для обработки on-click событий по узлам графа в окне UbiGraph.
После этого необходимо отредактировать настройки плагина в файле mynav-1.1-ubigraph/ubiconfig.py, указав в нем адреса Linux хоста (на котором запускается ubigraph_server), и Windows хоста (на котором запускается IDA Pro):
 1 
 2 ubi_graph = None
 3 ubi_is_initialized = False
 4 
 5  # ubigraph server XMLRPC URL
 6 ubi_server_url = "http://192.168.254.100:20738/RPC2"
 7 
 8 # ubigraph client IP address 
 9 # i.e., host that runs IDA
10 ubi_local_addr = "192.168.254.1"
11 
12 #
13 # If you're using IDA and UbiGraph server on the
14 # same machine - just write 127.0.0.1 in both of
15 # ubi_server_url and ubi_local_addr
16 #
17

После выполнения всех перечисленных манипуляций можно запускать IDA Pro и начинать работу.

Загрузка плагина MyNav производится с помощью пункта главного меню "File" -> "Script file...", или по горячей клавише Alt+F7. В появившемся диалоге выбора файла требуется открыть mynav-1.1-ubigraph/mynav.py. Если IDAPython корректно установлен, то после этого в главном меню "Edit" -> "Plugins" появится около двух десятков новых пунктов, соответствующих MyNav. Среди них для нашей задачи наиболее интересен "MyNav: Show browser", который так же доступен по горячей клавише Ctrl+Shift+B.

Открыв вкладку с листингом дизассемблированного кода, установив курсор на начало какой-либо процедуры и нажав Ctrl+Shift+B --  мы вызовем MyNav, который задаст вопрос об глубине рекурсивного сканирования дерева функций при построении их графа:



Обычно, оптимальным является число от 1 до 3, так как при указании большей глубины граф получится слишком объёмным. После нажатия на <OK> MyNav построит граф на отдельной вкладке в окне IDA. В это же время, в окне UbiGraph будет построена 3D версия того же графа. При правильных настройках в IDA Output Window так же появится уведомление об успешном подключении к серверу UbiGraph:



Команды, вызываемые в контекстном меню графа MyNav (например: скрыть/показать строки, или скрыть/показать вызовы API), соответствующим образом сказываются и на графе в UbiGraph. Поскольку в самой IDA может быть открыто множество вкладок с графами, в окне UbiGraph будет отображаться самый последний из них.

Работа с UbiGraph в IDA Pro на видео:


3D graphs in IDA Pro with MyNav and UbiGraph from Dmytro on Vimeo.

К сожалению, проект IDA-UbiGraph носит исключительно демонстрационный характер, так как его полноценное развитие не возможно без доработок и глубокой модификации самого UbiGraph. Однако, я буду рад, если после прочтения данной заметки другие программисты и хакеры обратят своё внимание на такую интересную тему, как 3D визуализации в области анализа кода и реверс-инженеринга, и так же начнут свои исследования в данном направлении.

Полезные ссылки:

Monday, June 13, 2011

Выступление на Positive Hack Days 2011

Репост из блога Esage Lab

Этой весной в Москве прошло весьма необычное для отечественного itsec-сообщества мероприятие под названием Positive Hack Days. Делать его детальный обзор я смысла не вижу, поскольку всё уже было неоднократно высказано другими людьми, положительные отзывы которых я вполне разделаю.

На Positive Hack Days я выступил с мастер-классом "Автоматический поиск уязвимостей в программах без исходных текстов", материалы к которому я выкладываю в данной записи.

Слайды к выступлению:

Использовавшиеся на мастер-классе утилиты (многие из них я не успел показать) доступны для загрузки в виде архива. Ниже идёт описание наиболее интересного содержимого этого архива.

****


./AnalyzeDumps - Программа для анализа аварийных дампов памяти с использованием отладчика KD.EXE и расширения !exploitable.
Использование:
> python ./AnalyzeDumps/analyze_dumps.py <dumps_dir> [--noisy]

... где <dumps_dir> - директория, в которой содержатся файлы аварийных дампов. При указании ключа --noisy в консоль будут выведены все сообщения отладчика.

По завершению работы программы в текущей директории будет создан файл Analyze.log c общей информацией по всем проанализированным дампам, а в <dumps_dir> - отдельный лог для каждого аварийного дампа с полным выводом отладчика.
Примеры сгенерированных файлов для различных тестовых приложений: ./Analyze_Norman.log, ./Analyze_RPCExample.log и ./Analyze_Visio.log

Программа analyze_dumps.py требует для своей работы следующие сторонние инструменты (так же включены в архив):
  • ./MSECExtensions_1_0_6 - Расширения для отладчика MSEC Debugger Extensions, в состав которых входит !exploitable.
  • ./Microsoft KD - Консольный отладчик от Microsoft, который, обычно, входит в состав пакета Microsoft Debugging Tools for Windows.

****


./Code Coverage Tools и ./pin-2.8-37300-msvc9-ia32_intel64-windows - Основанный на PIN Toolkit набор средств для построения и анализа карты покрытия кода исследуемого приложения.

Подробная информация по использованию:

Так же в директории ./Kcachegrind находится Win32-версия одноимённого приложения, которое позволяет визуализировать карты деревьев вызовов, которые были получены с помощью Code Coverage Tools.

****


./FileFuzz - Инструменты для примитивного мутационного фаззинга на примере файлов архивов форматов 7z, ACE, ARJ, CAB, GZ, LZH, RAR, TGZ, и ZIP.

Генерация некорректных файлов производится с помощью программы ./FileFuzz/MutateGen.exe (исходные тексты доступны в ./FileFuzz/MutateGen/) на основе "хороших" файлов архивов указанных выше форматов, которые находятся в директории ./FileFuzz/TEST/.

Пример запуска MutateGen.exe для генерации файлов:
> MutateGen.exe C:\TEST.zip C:\output_dir -BLOCK_SIZE 1 -BLOCK_RANGE_START 0xa0 -BLOCK_RANGE_END 0xff -BLOCK_RANGE_N 1

Назначения параметров командной строки программы:
  • -FILE_RANGE_START - Файловое смещение для прочитанных из указанного файла начальных данных, начиная с которого MutateGen.exe осуществляет их модификацию (по умолчанию FILE_RANGE_START равен нулю).
  • -FILE_RANGE_END - Файловое смещение, определяющее конец зоны начальных данных, которую модифицирует MutateGen.exe (по умолчанию FILE_RANGE_END равен размеру начального файла).
  • -BLOCK_SIZE - Размер блока данных, которые MutateGen.exe модифицирует за один проход (допустимые значения: 1, 2 и 4).
  • -BLOCK_RANGE_START - Стартовое значение счётчика, которое используется как значение для генерируемого блока данных.
  • -BLOCK_RANGE_END - Конечное значение счётчика, которое используется как значение для генерируемого блока данных.
  • -BLOCK_RANGE_N - Величина инкремента счётчика за одну итерацию.

Таким образом, количество циклов генерации данных (количество модифицируемых байт) для одного начального файла рассчитывается по формуле:

N = (FILE_RANGE_END &~ (BLOCK_SIZE - 1)) - FILE_RANGE_START

Количество блоков данных:

BLOCKS = N / BLOCK_SIZE

Количество итераций для одного цикла генерации данных:

I_MAX = ((BLOCK_RANGE_END &~ (BLOCK_RANGE_N - 1)) - BLOCK_RANGE_START) / BLOCK_RANGE_N

Количество cгенерированных файлов с некорректными данными:

FILES = BLOCKS * I_MAX

Для генерации данных используются сценарии generate_bs_1.bat, generate_bs_2.bat, generate_bs_4.bat и generate_bs_4_hi.bat, которые запускают MutateGen.exe с различными настройками.

Фаззинг архивов на примере актуальной версии антивируса Norman Security Suite продемонстрирован на видео.


Norman Security Suite Fuzzing from eSage Lab on Vimeo.

Аварийные дампы для Norman Security Suite а так же файл вызывающий падение антивирусного сканера находятся в директории ./XcptMon/_Norman_dumps_7z, а лог анализа этих аварийных дампов с помощью analyze_dumps.py - в ./Analyze_Norman.log

****


./InMemoryFuzzer и ./RPCExample - Инструменты и тестовые приложения для демонстрации in-memory фаззинга RPC сервера.
В качестве фаззера используется программа на Python под названием InMemoryFuzzer by sinn3r, которая подробно описана в статье "In Memory Fuzzing".

Для удобства использования в архив включена её версия в виде исполняемого файла, созданного с помощью py2exe (см. директорию ./InMemoryFuzzer/dist).

В качестве уязвимого сервера используется написанная на C++ программа, исходные тексты и исполняемые файлы которой находятся в ./RPCExample/ (там же есть и клиент для этого сервера). Проведение фаззинга осуществляется в несколько шагов:
  1. Запускается сервер с помощью сценария ./RPCExample/run_server.bat
  2. Запускается фаззер с помощью сценария ./RPCExample/fuzz_server.bat
  3. Запускается клиент для RPC сервера (./RPCExample/DebugExe/ContextExampleClient.exe)
  4. В момент обработки запроса от клиента в контексте серверного процесса фаззер модифицирует переданную функции _HelloProc() ASCII-строку, в результате чего будет спровоцировано переполнение буфера в этой функции.
  5. После аварийного завершения работы серверного процесса фаззер создаст отчёт о его падении в директории ./RPCExample/crashbin

****


./MSOffice - Инструменты для более продвинутого мутационного фаззинга на примере приложения Visio из состава Microsoft Office.

Генерация данных для фаззинга осуществляется приложением ./MSOffice/fuzzgen/, которое использует принцип мутационных преобразований имеющихся .VSD-документов с частичным парсингом формата файла-контейнера Microsoft Office. Для парсинга структуры документов используются функция StgOpenStorageEx() и интерфейс IStorage.

В ./MSOffice/_faults/ находятся примеры сгенерированных фаззером .VSD-документов, обработка которых вызывает падение Visio. Лог анализа этих аварийных дампов с помощью analyze_dumps.py находится в ./Analyze_Visio.log

Для запуска процесса фаззинга используется приложение ./MSOffice/fuzzrun/, работа с ним продемонстрирована на видео.


Microsoft Office Visio Fuzzing from eSage Lab on Vimeo.

****


./XcptMon - Приложение для мониторинга исключений и создания аварийных дампов. Именно оно используется для генерации дампов в описанных выше тестах.

XcptMon работает по принципу внедрения DLL библиотеки (./XcptMon/XcptMonDll.dll) в контекст анализируемого процесса при его запуске. DLL, в свою очередь, перехватывает функцию KiUserExceptionDispatcher(). Для внедрения DLL используется параметр реестра "Debugger" в ключе HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<image_name>, где <image_name> - имя исполняемого файла анализируемого процесса.

Использование XcptMon:
> XcptMon.exe <image_name> [options]

... где в качестве опций возможно указать следующие ключи:
  • --dumpsdir <path> - Путь к директории для сохранения аварийных дампов.
  • --logpath <path> - Путь к файлу, в который будет записана информация об исключениях.
  • --remove - Отключить XcptMon для указанного имени процесса.
  • --noexit - Не завершать целевой процесс при возникновении первого #AV исключения.
Пример лога с информацией об исключениях:
[+] Target command line: "TestApp.exe"
[+] DLL injected into the target process 7404
[+] Exit on first #AV: "No"
ModuleInit(): From process 'E:\_tmp\PHD\XcptMon\TestApp.exe' (PID: 7404)
[!] EXCEPTION OCCURS:
STATUS_ACCESS_VIOLATION at 0x0119101c
  Access type: Write
      Address: 0x00000000
EAX=0x00000000 EBX=0x00000000 ECX=0x6f6e215c EDX=0x773270b4
ESI=0x6f6e20c1 EDI=0x01193380 EBP=0x0012fe54

[+] 22398742 bytes of minidump has been written to the "0xC0000005_0x0119101C_17.05_19.28.54.DMP"
[!] EXCEPTION OCCURS:
STATUS_ACCESS_VIOLATION at 0x011910af
  Access type: Write
      Address: 0x00000000
EAX=0x00000000 EBX=0x00000000 ECX=0x6f6e215c EDX=0x773270b4
ESI=0x6f6e20c1 EDI=0x00000000 EBP=0x0012fe54

[+] 22402854 bytes of minidump has been written to the "0xC0000005_0x011910AF_17.05_19.28.54.DMP"
[+] Process exit code: 0xc0000005

Так же библиотека XcptMonDll.dll экспортирует глобальные переменные m_szLastFilePath, m_szLastExceptionCode, m_szLastExceptionAddr, m_szMainModuleVersion и m_szFaultModuleVersion, в которые на момент создания аварийного дампа записывается информация о возникшем исключении и целевом приложении. Эту информацию, для включения в свой лог-файл, получает упоминавшийся выше analyze_dumps.py

****


./ioctl_fuzzer-1.2 - Исходные тексты и исполняемые файлы программы IOCTL Fuzzer, которая предназначена для автоматического выявления узявимостей в драйверах режима ядра, связанных с некорректной обработкой IOCTL-запросов.
В директории ./ioctl_fuzzer-1.2/_exploits/ находятся примеры эксплойтов к найденным спомощью IOCTL Fuzzer уязвимостям.

scsiprot_smart - "Теоретически эксплуатируемая" Local Admin to Ring0 уязвимость в стандартном драйвере Windows atapi.sys при обработке IOCTL запроса IOCTL_SCSI_MINIPORT. Приведенный демонстрационный эксплойт, к сожалению, DoS only.

TM_TmComm_9000402b_exploit - Полнофункциональный Local Admin to Ring0 эксплойт к уязвимости в драйвере актуальной версии (3.0.0.1303 на момент написания текста) антивирусного продукта под названием Trend Micro Titanium Maximum Security.