
Inspeciona, descompila e aplica patches estruturais ao bytecode Hermes (HBC) de aplicações React Native, com um REPL estilo GDB, CFG, descompilador e patcher de re-serialização.
Hermes Reverse Engineering & Manipulation Interactive Toolkit.
hermit inspeciona, descompila e aplica patches estruturais ao bytecode Hermes (HBC), o
formato no qual os apps React Native distribuem seu JavaScript. Abra um arquivo .hbc, navegue
por suas funções, leia o JavaScript descompilado, edite instruções, strings e
literais em um editor interativo, e grave de volta um arquivo que a VM do Hermes
ainda carrega e executa.
Diferente de ferramentas que apenas analisam bytecode, ou que o aplicam patches no local sem alterar tamanhos, o hermit re-serializa o arquivo inteiro. Ele pode inserir e excluir instruções, realocar saltos e manipuladores de exceção, reconstruir as tabelas de strings e literais, adicionar novas funções e recalcular o rodapé SHA-1. Um arquivo não modificado faz round-trip byte a byte.
.hbc| Versão | Papel |
|---|---|
| 96 | Alvo principal. O que os apps React Native em produção usam: RN 0.73 a 0.83, e RN 0.84+ com Hermes V1 desabilitado. |
| 94, 95 | Validados. O formato é idêntico ao 96, apenas as tabelas de opcodes diferem. |
Apps compilados com Hermes V1 (o padrão a partir do RN 0.84) emitem HBC 98, que ainda não é
suportado. Notas sobre o formato estão em doc/hbc-format/.
Cada release tem arquivos para macOS e Linux, em arm64 e x86_64. Nenhum Python ou compilador é necessário:
| Arquivo | Conteúdo |
|---|---|
hermit-<version>-<platform>.tar.gz | O REPL interativo: ./hermit file.hbc. |
hermit-tools-<version>-<platform>.tar.gz | As ferramentas de linha de comando hbc_* independentes. |
SHA256SUMS | Checksums: shasum -a 256 -c SHA256SUMS. |
tar -xzf hermit-0.1.0-macos-arm64.tar.gz
./hermit-0.1.0-macos-arm64/hermit --version
Os binários do macOS não são assinados. Após o download, remova o sinalizador de quarentena
uma vez: xattr -dr com.apple.quarantine hermit-0.1.0-macos-arm64. As builds para Linux
requerem glibc 2.35 ou mais recente. O comando cfg ainda requer o graph-easy instalado.
As releases são produzidas por .github/workflows/release.yml quando uma tag v* é
enviada, usando packaging/build-release.sh, que você também pode executar localmente.
FetchContent do CMake, a menos que já estejam instalados.graph-easy para o comando cfg
(cpanm Graph::Easy), less como seu paginador.Execute tudo a partir deste diretório (o que contém o CMakeLists.txt):
cmake -B build
cmake --build build -j
Isso compila a biblioteca estática libhbc, o módulo Python _libhbc (em
build/bindings/), as ferramentas de linha de comando (em build/tools/) e os testes
unitários. O REPL precisa apenas do módulo Python:
cmake --build build --target _libhbc
As ferramentas e os testes podem ser deixados de fora de uma build, por exemplo para uma release:
cmake -B build -DCMAKE_BUILD_TYPE=Release -DHERMIT_BUILD_TOOLS=OFF -DHERMIT_BUILD_TESTS=OFF
Recompile com o mesmo comando após cada alteração em core/ ou bindings/.
macOS: se a vinculação falhar com um erro sobre um SDK malformado, aponte a compilação para um SDK completo, por exemplo
SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX26.5.sdk cmake --build build.
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
O módulo _libhbc não está instalado no virtualenv. Adicione seu diretório de build ao PYTHONPATH sempre que você executar o hermit:
export PYTHONPATH=$PWD/build/bindings:$PYTHONPATH
.hbcUm app React Native distribui seu bundle como um arquivo simples:
| Plataforma | Localização dentro do pacote |
|---|---|
Android (.apk, um zip) | assets/index.android.bundle |
iOS (.ipa, um zip) | Payload/<App>.app/main.jsbundle |
Se o arquivo começar com os bytes C6 1F BC 03 C1 03 19 1F, ele é bytecode Hermes. O REPL só abre arquivos com a extensão .hbc, então renomeie-o:
unzip -p app.apk assets/index.android.bundle > app.hbc
xxd app.hbc | head -1 # c61f bc03 c103 191f ...
Analise apenas aplicações que você tem permissão para estudar, por exemplo, as suas próprias, ou aplicações de código aberto para fins de pesquisa.
Para obter entradas pequenas e controladas, compile JavaScript ou TypeScript com um compilador Hermes que emita HBC 96 (por exemplo, hermesc do react-native 0.73 a 0.83, em node_modules/react-native/sdks/hermesc/):
hermes -emit-binary -g0 -out hello.hbc hello.js # -g0: no debug info
O pacote seeder/ automatiza isso para os programas de exemplo em
seeder/samples/ e grava os resultados em seeder/corpus/:
.venv/bin/python -m seeder.compile # all samples
.venv/bin/python -m seeder.compile --g0 seeder/samples/loop_sum.js
.venv/bin/python -m seeder.compile --debug seeder/samples/greeting.js
--g0 grava <name>_g0.hbc sem informações de depuração, --debug grava
<name>_g.hbc com informações completas de depuração. Amostras .ts precisam de tsc no seu PATH;
o compilador é obtido de --hermes (padrão hermes). seeder/build-real-bundle.sh
compila um aplicativo React Native de código aberto real em um .hbc.
export PYTHONPATH=$PWD/build/bindings:$PYTHONPATH
.venv/bin/python -m cli.main app.hbc
Sem um argumento de ficheiro, o REPL inicia vazio; use open <file.hbc>. O prompt mostra a versão do HBC e o nome do ficheiro, com um + quando existem alterações não guardadas: [hbc v96 | app+] >. O histórico é mantido em ~/.hermit_history e os comandos têm conclusão por tabulação.
> info
> strings --identifiers filter:fetch
> functions
> disasm func:12
> decompile func:isPremium
> xrefs string:"api.example.com"
> edit func:isPremium
> patch patched.hbc
As funções são endereçadas por índice ou nome (func:12, func:isPremium), as strings
por índice ou valor (string:42, string:"hello"), os sítios de literais por índice
(array:7).