
Инспектирует, декомпилирует и структурно патчит байт-код Hermes (HBC) из приложений React Native, с REPL в стиле GDB, CFG, декомпилятором и патчером с повторной сериализацией.
Hermes Reverse Engineering & Manipulation Interactive Toolkit.
hermit исследует, декомпилирует и структурно патчит байт-код Hermes (HBC) —
формат, в котором React Native приложения поставляют свой JavaScript. Откройте
файл .hbc, просмотрите его функции, прочитайте декомпилированный JavaScript,
отредактируйте инструкции, строки и литералы в интерактивном редакторе и
запишите обратно файл, который Hermes VM всё ещё загружает и выполняет.
В отличие от инструментов, которые только анализируют байт-код или патчат его на месте без изменения размеров, hermit пересобирает весь файл. Он может вставлять и удалять инструкции, перемещать переходы и обработчики исключений, перестраивать таблицы строк и литералов, добавлять новые функции и пересчитывать SHA-1 в конце файла. Неизменённый файл проходит круговой рейс байт в байт.
.hbc| Версия | Роль |
|---|---|
| 96 | Основная цель. То, что используют поставляемые React Native приложения: RN 0.73–0.83 и RN 0.84+ с отключённым Hermes V1. |
| 94, 95 | Проверены. Формат идентичен 96, отличаются только таблицы опкодов. |
Приложения, собранные с Hermes V1 (по умолчанию начиная с RN 0.84), выдают
HBC 98, который пока не поддерживается. Заметки о формате находятся в
doc/hbc-format/.
В каждом релизе есть архивы для macOS и Linux, на arm64 и x86_64. Python или компилятор не нужны:
| Архив | Содержимое |
|---|---|
hermit-<version>-<platform>.tar.gz | Интерактивный REPL: ./hermit file.hbc. |
hermit-tools-<version>-<platform>.tar.gz | Автономные инструменты командной строки hbc_*. |
SHA256SUMS | Контрольные суммы: shasum -a 256 -c SHA256SUMS. |
tar -xzf hermit-0.1.0-macos-arm64.tar.gz
./hermit-0.1.0-macos-arm64/hermit --version
Бинарники для macOS не подписаны. После загрузки один раз снимите флаг
карантина: xattr -dr com.apple.quarantine hermit-0.1.0-macos-arm64. Сборки
для Linux требуют glibc 2.35 или новее. Команде cfg по-прежнему нужен
установленный graph-easy.
Релизы создаются .github/workflows/release.yml при отправке тега v*, с
помощью packaging/build-release.sh, который можно запустить и локально.
FetchContent, если они ещё не установлены.graph-easy для команды
cfg (cpanm Graph::Easy), less в качестве пейджера для неё.Запускайте всё из этого каталога (того, что содержит CMakeLists.txt):
cmake -B build
cmake --build build -j
Это собирает статическую библиотеку libhbc, модуль Python _libhbc (в
build/bindings/), инструменты командной строки (в build/tools/) и
модульные тесты. Для REPL нужен только модуль Python:
cmake --build build --target _libhbc
Инструменты и тесты можно исключить из сборки, например для релиза:
cmake -B build -DCMAKE_BUILD_TYPE=Release -DHERMIT_BUILD_TOOLS=OFF -DHERMIT_BUILD_TESTS=OFF
Пересобирайте той же командой после каждого изменения в core/ или
bindings/.
macOS: если компоновка завершается ошибкой о повреждённом SDK, укажите сборке полный SDK, например
SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX26.5.sdk cmake --build build.
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
Модуль _libhbc не устанавливается в виртуальное окружение. Добавляйте его
каталог сборки в PYTHONPATH всякий раз, когда запускаете hermit:
export PYTHONPATH=$PWD/build/bindings:$PYTHONPATH
.hbcReact Native приложение поставляет свой бандл как обычный файл:
| Платформа | Расположение внутри пакета |
|---|---|
Android (.apk, zip) | assets/index.android.bundle |
iOS (.ipa, zip) | Payload/<App>.app/main.jsbundle |
Если файл начинается с байтов C6 1F BC 03 C1 03 19 1F, это байт-код
Hermes. REPL открывает только файлы с расширением .hbc, поэтому переименуйте
его:
unzip -p app.apk assets/index.android.bundle > app.hbc
xxd app.hbc | head -1 # c61f bc03 c103 191f ...
Анализируйте только те приложения, которые вам разрешено изучать, например свои собственные или приложения с открытым исходным кодом для исследований.
Чтобы получить небольшие контролируемые входные данные, скомпилируйте
JavaScript или TypeScript компилятором Hermes, который выдаёт HBC 96 (например,
hermesc из react-native 0.73–0.83, в
node_modules/react-native/sdks/hermesc/):
hermes -emit-binary -g0 -out hello.hbc hello.js # -g0: без отладочной информации
Пакет seeder/ автоматизирует это для примеров программ в seeder/samples/ и
записывает результаты в seeder/corpus/:
.venv/bin/python -m seeder.compile # все примеры
.venv/bin/python -m seeder.compile --g0 seeder/samples/loop_sum.js
.venv/bin/python -m seeder.compile --debug seeder/samples/greeting.js
--g0 записывает <name>_g0.hbc без отладочной информации, --debug
записывает <name>_g.hbc с полной отладочной информацией. Для примеров .ts
нужен tsc в вашем PATH; компилятор берётся из --hermes (по умолчанию
hermes). seeder/build-real-bundle.sh собирает настоящее React Native
приложение с открытым исходным кодом в .hbc.
export PYTHONPATH=$PWD/build/bindings:$PYTHONPATH
.venv/bin/python -m cli.main app.hbc
Без аргумента с файлом REPL запускается пустым; используйте open <file.hbc>.
Приглашение показывает версию HBC и имя файла, со знаком + при наличии
несохранённых изменений: [hbc v96 | app+] >. История хранится в
~/.hermit_history, а команды дополняются по Tab.
> info
> strings --identifiers filter:fetch
> functions
> disasm func:12
> decompile func:isPremium
> xrefs string:"api.example.com"
> edit func:isPremium
> patch patched.hbc
Функции адресуются по индексу или имени (func:12, func:isPremium), строки
по индексу или значению (string:42, string:"hello"), места литералов по
индексу (array:7).