
Ispeziona, decompila e applica patch strutturali al bytecode Hermes (HBC) delle app React Native, con una REPL in stile GDB, CFG, decompilatore e patcher con riserializzazione.
Hermes Reverse Engineering & Manipulation Interactive Toolkit.
hermit ispeziona, decompila e applica patch strutturali al bytecode Hermes (HBC), il formato in cui le app React Native distribuiscono il loro JavaScript. Apri un file .hbc, esplora le sue funzioni, leggi il JavaScript decompilato, modifica istruzioni, stringhe e letterali in un editor interattivo, e riscrivi un file che la VM Hermes riesce ancora a caricare ed eseguire.
A differenza degli strumenti che si limitano ad analizzare il bytecode, o che lo modificano sul posto senza cambiarne le dimensioni, hermit ri-serializza l'intero file. Può inserire ed eliminare istruzioni, ricollocare salti e gestori di eccezioni, ricostruire le tabelle di stringhe e letterali, aggiungere nuove funzioni e ricalcolare il footer SHA-1. Un file non modificato viene riprodotto byte per byte.
.hbc| Versione | Ruolo |
|---|---|
| 96 | Target principale. Quella usata dalle app React Native in distribuzione: RN 0.73 fino a 0.83, e RN 0.84+ con Hermes V1 disabilitato. |
| 94, 95 | Validate. Il formato è identico alla 96, cambiano solo le tabelle di opcode. |
Le app compilate con Hermes V1 (il default da RN 0.84) producono HBC 98, che non è
ancora supportato. Le note sul formato sono in doc/hbc-format/.
Ogni release ha archivi per macOS e Linux, su arm64 e x86_64. Non servono Python né un compilatore:
| Archivio | Contenuto |
|---|---|
hermit-<version>-<platform>.tar.gz | La REPL interattiva: ./hermit file.hbc. |
hermit-tools-<version>-<platform>.tar.gz | Gli strumenti da riga di comando hbc_* standalone. |
SHA256SUMS | Checksum: shasum -a 256 -c SHA256SUMS. |
tar -xzf hermit-0.1.0-macos-arm64.tar.gz
./hermit-0.1.0-macos-arm64/hermit --version
I binari macOS non sono firmati. Dopo il download, rimuovi una volta il flag di quarantena:
xattr -dr com.apple.quarantine hermit-0.1.0-macos-arm64. Le build Linux
richiedono glibc 2.35 o superiore. Il comando cfg richiede comunque graph-easy installato.
Le release sono prodotte da .github/workflows/release.yml quando viene pushato un tag v*,
usando packaging/build-release.sh, che puoi eseguire anche in locale.
FetchContent di CMake, a meno che non siano già installati.graph-easy per il comando cfg
(cpanm Graph::Easy), less come suo pager.Esegui tutto da questa directory (quella che contiene CMakeLists.txt):
cmake -B build
cmake --build build -j
Questo compila la libreria statica libhbc, il modulo Python _libhbc (in
build/bindings/), gli strumenti da riga di comando (in build/tools/) e gli unit
test. La REPL richiede solo il modulo Python:
cmake --build build --target _libhbc
Gli strumenti e i test possono essere esclusi da una build, per esempio per una release:
cmake -B build -DCMAKE_BUILD_TYPE=Release -DHERMIT_BUILD_TOOLS=OFF -DHERMIT_BUILD_TESTS=OFF
Ricompila con lo stesso comando dopo ogni modifica a core/ o bindings/.
macOS: se il linking fallisce con un errore relativo a un SDK malformato, punta la build a un SDK completo, per esempio
SDKROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX26.5.sdk cmake --build build.
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
Il modulo _libhbc non viene installato nel virtualenv. Aggiungi la sua directory di build
al PYTHONPATH ogni volta che esegui hermit:
export PYTHONPATH=$PWD/build/bindings:$PYTHONPATH
.hbcUn'app React Native distribuisce il suo bundle come file semplice:
| Piattaforma | Posizione all'interno del pacchetto |
|---|---|
Android (.apk, uno zip) | assets/index.android.bundle |
iOS (.ipa, uno zip) | Payload/<App>.app/main.jsbundle |
Se il file inizia con i byte C6 1F BC 03 C1 03 19 1F, è bytecode Hermes.
La REPL apre solo file con estensione .hbc, quindi rinominalo:
unzip -p app.apk assets/index.android.bundle > app.hbc
xxd app.hbc | head -1 # c61f bc03 c103 191f ...
Analizza solo app che ti è consentito studiare, per esempio le tue, o app open source per ricerca.
Per ottenere input piccoli e controllati, compila JavaScript o TypeScript con un compilatore
Hermes che emette HBC 96 (per esempio hermesc da react-native 0.73 fino
a 0.83, sotto node_modules/react-native/sdks/hermesc/):
hermes -emit-binary -g0 -out hello.hbc hello.js # -g0: no debug info
Il pacchetto seeder/ automatizza questo per i programmi di esempio in
seeder/samples/ e scrive i risultati in 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 scrive <name>_g0.hbc senza informazioni di debug, --debug scrive
<name>_g.hbc con informazioni di debug complete. I campioni .ts richiedono tsc nel tuo PATH;
il compilatore è preso da --hermes (default hermes). seeder/build-real-bundle.sh
compila una vera app React Native open source in un .hbc.
export PYTHONPATH=$PWD/build/bindings:$PYTHONPATH
.venv/bin/python -m cli.main app.hbc
Senza un argomento file la REPL parte vuota; usa open <file.hbc>. Il
prompt mostra la versione HBC e il nome del file, con un + quando ci sono
modifiche non salvate: [hbc v96 | app+] >. La cronologia è conservata in ~/.hermit_history
e i comandi sono completabili con il tab.
> info
> strings --identifiers filter:fetch
> functions
> disasm func:12
> decompile func:isPremium
> xrefs string:"api.example.com"
> edit func:isPremium
> patch patched.hbc
Le funzioni sono indirizzate per indice o nome (func:12, func:isPremium), le stringhe
per indice o valore (string:42, string:"hello"), i siti dei letterali per indice
(array:7).