
фреймворк для эксплуатации кучи jemalloc
shadow — это фреймворк для эксплуатации кучи jemalloc. Он спроектирован так, чтобы быть независимым от целевого приложения, использующего jemalloc в качестве аллокатора кучи (будь то libc Android, Firefox, libc FreeBSD, автономный jemalloc или что-то ещё). Текущая версия (2.0) была тщательно протестирована со следующими целями:
Помимо исходного кода инструмента, этот репозиторий также включает документацию по настройке среды отладки пользовательского пространства Android для использования shadow, краткий обзор структур jemalloc в Android с помощью shadow, а также некоторые заметки о том, как уязвимости двойного, невыровненного и произвольного освобождения памяти ведут себя в jemalloc Android.
Когда вы впервые вводите команду, специфичную для jemalloc, shadow анализирует все известные ему метаданные jemalloc и сохраняет их в файл Python pickle. Последующие команды используют этот pickle-файл вместо повторного анализа метаданных из памяти для ускорения работы.
Когда вы знаете, что состояние метаданных jemalloc изменилось (например, после выполнения выделений или запуска сборщика мусора), используйте команду jeparse, чтобы повторно проанализировать метаданные и пересоздать pickle-файл.
Первым шагом установите pyrsistence на вашем хост-компьютере.
На рутированном устройстве выполните следующее:
host$ adb shell
phone$ su root
phone# ps -e
Из вывода ps выберите процесс, например com.google.process.gapps:
...
u0_a19 4679 3214 1668980 69216 SyS_epoll_ 7fa5f41430 S com.google.process.gapps
...
phone$ cd /data/local/tmp
phone$ ./gdbserver64 :5039 --attach 4679
Бинарные файлы GDB server для ARM32 и ARM64 можно найти в каталоге "bin". Или, если вы нам не доверяете, выполните:
host$ git clone http://android.googlesource.com/toolchain/gdb
host$ cd ./gdb/gdb-7.11
host$ mkdir build64; cd build64
host$ ../configure --program-prefix=aarch64-eabi-linux- --target=aarch64-eabi-linux --disable-werror
host$ make
host$ sudo make install
Затем на хост-машине выполните:
host$ adb forward tcp:5039 tcp:5039
host$ aarch64-eabi-linux-gdb
(gdb) target remote :5039
(gdb) source /dir/with/shadow/gdb_driver.py
(gdb) jeparse -c /dir/with/shadow/cfg/android7_64.cfg
(gdb) jeruns -c
Иногда GDB server перестает прослушивать, если вы слишком долго выполняете команду target remote :5039. Поэтому, если вы видите странные ошибки при выполнении команды jeparse, просто начните заново.
shadow для Windows/Firefox был протестирован со следующим:
Примечание: Если вы работаете с версией Firefox старше 36.0, используйте ветку mozjs!
Сначала настройте WinDBG с сервером символов Mozilla. Также необходимо установить pykd. Затем скопируйте каталог shadow, который вы клонировали из GitHub, в какой-либо путь (например, C:\tmp\).
Вы также можете найти пример сценария инициализации WinDBG в файле "windbg-init.cmd". Поместите его в C:\tmp\ и запустите WinDBG с windbg.exe -c "$$>< C:\tmp\windbg-init.cmd".
Наконец, внутри WinDBG выполните следующие команды:
!load pykd.pyd
!py c:\\tmp\\shadow\\pykd_driver help
[shadow] De Mysteriis Dom jemalloc
[shadow] shadow v2.0
[shadow] Firefox v56.0a1 (x86-64)
[shadow] Команды, специфичные для jemalloc:
[shadow] jechunks : вывод информации обо всех доступных чанках
[shadow] jearenas : вывод информации об аренах jemalloc
[shadow] jerun [-m] <address> : вывод информации об одном ране
[shadow] -m : отображение предпросмотра содержимого на метаданные
[shadow] jeruns [-cs] : вывод информации о ранах jemalloc
[shadow] -c : только текущие раны
[shadow] -s <size class> : раны только для указанного класса размера
[shadow] jebins : вывод информации о бинах jemalloc
[shadow] jebininfo : вывод информации о размерах бинов
[shadow] jesize2bin : преобразование размера в индекс бина
[shadow] jeregions <size class> : вывод всех ранов, содержащих регионы
[shadow] указанного класса размера
[shadow] jesearch [-cs] <hex> : поиск в куче указанного шестнадцатеричного dword
[shadow] -c : только текущие раны
[shadow] -s <size class> : только регионы указанного размера
[shadow] jeinfo <address> : отображение всех доступных деталей для адреса
[shadow] jedump [path] : сохранение снимка кучи в текущий
[shadow] рабочий каталог или по указанному пути
[shadow] jestore [path] : псевдоним jedump
[shadow] jetcaches : вывод информации о всех tcache
[shadow] jetcache [-bs] <tid> : вывод информации об одном tcache
[shadow] -b <bin index> : информация только для указанного индекса бина
[shadow] -s <size class> : информация только для указанного класса размера
[shadow] jeparse [-crv] : разбор структур jemalloc из памяти
[shadow] -c <config file> : конфигурационный файл цели jemalloc
[shadow] -r : чтение предпросмотра содержимого
[shadow] -v : создание debug.log
[shadow] Команды, специфичные для Firefox (только pykd):
[shadow] nursery : отображение информации о GC nursery в SpiderMonkey
[shadow] symbol [-vjdx] <size> : отображение всех символов Firefox указанного размера
[shadow] -v : только символы классов с vtable
[shadow] -j : только символы из SpiderMonkey
[shadow] -d : только символы DOM
[shadow] -x : только символы не из SpiderMonkey
[shadow] pa <address> [<length>] : изменение длины ArrayObject (новая длина по умолчанию 0x666)
[shadow] Команды, специфичные для Android:
[shadow] jefreecheck [-bm] : отображение адресов, которые можно передать в free()
[shadow] -b <bin index> : отображение адресов, которые будут освобождены в
[shadow] tcache бин <bin index>
[shadow] -m <name> : поиск только в этом конкретном модуле
[shadow] Общие команды:
[shadow] jeversion : вывод номера версии
[shadow] jehelp : это справочное сообщение
Если вы не видите указанное выше справочное сообщение, вы сделали что-то не так ;)
Примечание: Эта функция в настоящее время доступна только для Firefox/Windows!
Команда symbol позволяет искать классы (и структуры) SpiderMonkey и DOM указанных размеров. Это полезно при попытке эксплуатации уязвимостей типа use-after-free или когда вы хотите расположить интересные объекты-жертвы для перезаписи/повреждения.
В основном каталоге shadow вы можете найти две небольшие утилиты для разбора PDB: symhex.py и pdbdy.py (быстрее). Запустите их на "xul.pdb", чтобы сгенерировать Python pickle-файл, который shadow ожидает в каталоге "pdb" (как "pdb/xul-VERSION.pdb.pkl"). Перед запуском убедитесь, что вы зарегистрировали "msdia90.dll"; например, на Windows 8.1 x86-64 это можно сделать с помощью:
regsvr32 "c:\Program Files (x86)\Common Files\Microsoft Shared\VC\msdia90.dll"
из командной строки с правами администратора. Также требуется модуль Python "comtypes"; установите pip и затем выполните pip install comtypes.
Чтобы получить "xul.pdb", необходимо настроить WinDBG с сервером символов Mozilla.
unmask_jemalloc изначально был переработан с модульной архитектурой для поддержки всех трех основных отладчиков и платформ (WinDBG, GDB и LLDB). Инструмент был переименован в shadow после добавления функций, специфичных только для Firefox/Windows/WinDBG.
Ниже приведен обзор новой архитектуры (читайте стрелки как «импортирует»). Цель, очевидно, состоит в том, чтобы весь код, зависящий от отладчика, находился в модулях *_driver и *_engine.
---------------------------------------------------------------------------------------
внешний интерфейс, требуемый отладчиком (связующее звено)
+------------+ +-------------+ +-------------+
| gdb_driver | | lldb_driver | | pykd_driver |
+------------+ +-------------+ +-------------+
^ ^ ^
| | |
------+-------------------+-------------------+----------------------------------------
| | |
| +--------+ |
+------------------------ | +-----+ основная логика (независимая от отладчика)
| | |
| | |
+-----------------+
+------+ | |
| |---------------> | shadow |<-----+
| util | +------> | | |
| | | +-----------------+ |
+------+ | ^ ^ ^ ^ |
| | | | | | | | | +--------+
| | | +-----+----------+ | +----+--------+---| symbol |
| | | | | | | | +--------+
+-+ | | | +----------+ | | | +---------+
| | | | | jemalloc | | +--------+---| nursery |
| | | | +----------+ | | +---------+
| | | | ^ ^ ^ | |
| | | | | | | | |
| | | | | | +------+--------+ |
| | | | | | | | |
| | +---+---+----+----------+--------+-----+ |
| | | | | | | | |
| +-----+---+----+----+ | | | |
| | | | | | | | |
--+---------+---+----+----+-----+--------+-----+----+----------------------------------
| | | | | | | | |
| | | | | | | | | API, зависимые от отладчика
| | | | | | | | |
| | | | | | | | |
| | | | v | | v |
| +------------+ | +-------------+ | +-------------+
+->| gdb_engine | +--| lldb_engine | +--| pykd_engine |
+------------+ +-------------+ +-------------+
^ ^ ^
| | |
+---+ +---------+ +---------------+
| | |
| | |
-------+-------------+-------------+---------------------------------------------------
| | |
| | | внутренний интерфейс, предоставляемый отладчиком
| | |
| | |
+-----+ +------+ +------+
| gdb | | lldb | | pykd |
+-----+ +------+ +------+
---------------------------------------------------------------------------------------