
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 proprio 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
carica ed esegue ancora.
A differenza degli strumenti che si limitano ad analizzare il bytecode, o che lo modificano sul posto senza cambiarne le dimensioni, hermit riserializza 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 a 0.83, e RN 0.84+ con Hermes V1 disabilitato. |
| 94, 95 | Validate. Il formato è identico alla 96, cambiano solo le tabelle degli opcode. |
Le app compilate con Hermes V1 (predefinito da RN 0.84) producono HBC 98, che non è
ancora supportato. Le note sul formato sono in doc/hbc-format/.
Ogni release contiene 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_* autonomi. |
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 vengono prodotte da .github/workflows/release.yml quando viene inviato un tag v*, utilizzando packaging/build-release.sh, che puoi eseguire anche localmente.
FetchContent di CMake, a meno che non siano già installati.graph-easy per il comando cfg (cpanm Graph::Easy), less come relativo 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 necessita solo del modulo Python:
cmake --build build --target _libhbc
Gli strumenti e i test possono essere esclusi da una build, ad 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, ad 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 è installato nel virtualenv. Aggiungi la sua directory di build a PYTHONPATH ogni volta che esegui hermit:
export PYTHONPATH=$PWD/build/bindings:$PYTHONPATH
.hbcUn'app React Native distribuisce il proprio bundle come un semplice file:
| 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, si tratta di bytecode Hermes. Il 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 le app che sei autorizzato a studiare, ad esempio le tue, o app open source per la ricerca.
Per ottenere input piccoli e controllati, compila JavaScript o TypeScript con un
compilatore Hermes che emetta HBC 96 (ad esempio hermesc da react-native 0.73 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 questa operazione 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 viene preso da --hermes (predefinito 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 il REPL si avvia vuoto; 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 completati con il tasto 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 letterali per indice (array:7).