
Glass - un'alternativa veloce e gratuita a IDA Pro
nel senso di trasparente e liscio
Un disassembler interattivo veloce, nativo e mobile-app first. Successore spirituale di IDA Pro per il workflow di reverse engineering su Android / iOS, costruito attorno a:
smali per la gestione di APK / DEX / smaliarmv8-encode per AArch64 e ARMv7 (A32 / Thumb) — .so nativi, Mach-O iOSgpui (Zed) per UI nativa accelerata via GPUredb per la persistenza ad indirizzamento per contenutorquickjs per plugin scriptabili (in programma)Licenza: GPL-3.0-only (ereditata da smali).
Abbiamo tutti usato IDA Pro — è lo standard del settore per il reversing e ha anni di plugin alle spalle, ma è lento, costoso e datato. Glass è nativo al 100% in Rust, con una UI accelerata via GPU per un'interazione fluida. È anche gratuito e open source al 100% — contribuite, per favore.
arm64-v8a che armeabi-v7a di una libreria vengono cercate in un'unica query). Grammatica per pattern di byte con mascheramento + gap; grammatica assembly tipizzata per AArch64 e ARMv7, con menu a discesa di autocompletamento consapevole dell'ISA.Una panoramica delle viste principali — clicca su qualsiasi miniatura per vederla a dimensione piena.
Ogni analisi che Glass esegue nella GUI è esposta anche come verbo CLI che emette JSON strutturato. Lo stesso binario glass è il punto di ingresso per l'automazione — scegli un sottocomando e ottieni un risultato one-shot e scriptabile, perfetto per pipeline jq e CI.```sh
glass classes ./app.apk --package com.example. --text
glass callers ./libfoo.so --artifact libfoo.so --symbol "glass::main"
onCreate across DEX, machine-readable:glass search ./app.apk onCreate | jq '.data.hits[] | select(.kind=="method")'
glass types ./app.ipa --kind swift-class --text
glass type ./app.ipa --artifact app --name blackjack.ContentView
Passa `--text` per un output leggibile, omettilo per JSON.
Riferimento completo: **[docs/cli-api.md](https://github.com/azw413/glass/blob/HEAD/docs/cli-api.md)**.
Questo significa che puoi scriptare e automatizzare le operazioni comuni.
## Competenze e MCP
Ogni verbo CLI è anche esposto come strumento tramite un server MCP (Model Context Protocol) integrato, quindi qualsiasi host compatibile con MCP — Claude Desktop, Cursor, Zed, il tuo client — può pilotare Glass direttamente per assistere nelle attività di reversing.```sh
# Print the machine-readable skill catalog (one JSON object listing
# every verb with its schema and an example invocation).
glass skills
# Run as an MCP stdio server. Plug into any MCP host's tool list.
glass mcp
Per registrarti con Claude Desktop, aggiungi Glass a ~/Library/Application Support/Claude/claude_desktop_config.json:```json
{
"mcpServers": {
"glass": { "command": "/usr/local/bin/glass", "args": ["mcp"] }
}
}
Il modello può quindi chiamare `inspect`, `symbols`, `disasm`, `cfg-of`, `dex-callers`, `search` e qualsiasi altro verbo su qualunque bundle gli venga indicato. I risultati degli strumenti vengono restituiti nello stesso envelope JSON che otterresti dalla CLI.
## Ricerca
Tre motori complementari, tutti disponibili dalla stessa palette ⌘F nell'interfaccia grafica e come verbi CLI / MCP.
### Ricerca full-text
Corrispondenza fuzzy su tutto il bundle tra simboli nativi, classi / metodi / campi DEX e literal stringa nelle sezioni di codice e dati. Filtrata in tempo reale durante la digitazione; i risultati vengono indirizzati alla vista corretta (elenco per gli indirizzi nativi, visualizzatore smali per i target DEX, vista esadecimale per i risultati nei dati). Gli indici vengono costruiti su un thread in background dopo il caricamento — un indicatore di avanzamento viene mostrato mentre l'operazione è in corso.```sh
glass search ./app.apk onCreate # all things named like "onCreate"
glass search ./libfoo.so init --limit 20
Riferimento CLI: verbo search in docs/cli-api.md.
Motore di pattern a livello di byte. Ogni atomo è una maschera esadecimale di 2 caratteri (c0, e?, ?f, ??) o un gap (* = 0..=32 byte, *(min..max) per limiti espliciti). Le corrispondenze non si estendono tra sezioni. Nella palette GUI, ⌘2 passa alla modalità Binaria; la casella Solo codice (attiva per impostazione predefinita) limita la scansione alle sezioni di testo, così non vieni sommerso dai risultati dei dati quando cerchi una forma di istruzione.```sh
mov w0, #1 ; retglass bin-search ./libfoo.so --artifact libfoo.so --pattern '20 00 80 52 c0 03 5f d6'
glass bin-search ./libfoo.so --artifact libfoo.so --pattern '?? ?? ?? 9? ?? ?? 4? 91'
glass bin-search ./libfoo.so --artifact libfoo.so --pattern 'de ad be ef'
Grammatica completa + esempi pratici: [`docs/BinSearch.md`](https://github.com/azw413/glass/blob/HEAD/docs/BinSearch.md).
### Ricerca di istruzioni
Scrivi l'assembly, Glass lo compila in byte. Una sequenza separata da `;` viene codificata tramite [armv8-encode](https://github.com/azw413/armv8-encode) — **AArch64** (`mov w0, #1`, `adrp x1, *`) e **ARMv7** in entrambe le modalità (Thumb `mov r1, r7` / `bxeq lr` / `push {r4-r7, lr}` e A32). I caratteri jolly vengono tradotti in maschere di bit degli operandi prima che il motore dei byte prenda il controllo. La scansione è globale — ogni artefatto nativo nel bundle riceve gli atomi dell'ISA corretta (le app Android con librerie sia `arm64-v8a` che `armeabi-v7a` vengono cercate in un'unica query).
Nella modalità Binary della GUI, ⌘B alterna tra le grammatiche **Bytes** e **Asm**; un menu a discesa di autocompletamento che tiene conto dell'ISA mostra le varianti che corrispondono ancora a ciò che hai digitato — `r1` esclude i candidati AArch64, `w0` esclude quelli ARMv7.
Wildcard:
| Token | Significato |
|---|---|
| `*` | qualsiasi operando (tipo dedotto dall'opcode scelto) |
| `#*` | qualsiasi immediato (suggerisce al selettore di opcode) |
| `x`, `w` | qualsiasi registro AArch64 di classe X o W |
| `r` | qualsiasi GPR ARMv7 (`r0..r15`, `sp`, `lr`, `pc`) |
| `<*>`, `<X>`, `<W>`, `<R>`, `<imm>` | equivalenti tra parentesi angolari, utili da annidare in altra sintassi (`[x, #*]`, `[r, #*]`) |```sh
# AArch64 — every `mov w0, #N` (any N)
glass insn-search ./libfoo.so --artifact libfoo.so --pattern 'mov w0, #*'
# AArch64 — any ADRP into x1 followed immediately by ADD into the same reg
glass insn-search ./libfoo.so --artifact libfoo.so --pattern 'adrp x1, * ; add x1, x1, #*'
# ARMv7 (Thumb) — `mov r1, r*` followed by a return
glass insn-search ./libfoo.so --artifact libfoo.so --pattern 'mov r1, r* ; bx lr'
# ARMv7 (any cond) — conditional bx in literal-pool callers
glass insn-search ./libfoo.so --artifact libfoo.so --pattern 'bxeq lr'
# every `ret x30` — concrete, no wildcards
glass insn-search ./libfoo.so --artifact libfoo.so --pattern 'ret'
La risposta contiene bytes_hex che mostra la maschera compilata (ad es. 01/1f ?? ?? 90/9f per adrp x1, *) così puoi vedere esattamente quali bit sono fissi e quali sono wildcard. Le catture (<name:kind> che fanno riferimento allo stesso operando più avanti nel pattern) sono progettate ma non ancora implementate.
Design completo + fasi: docs/InsnPattern.md. Riferimento CLI/MCP: insn-search in docs/cli-api.md.
Glass è oggi utilizzabile per fare reverse engineering di app Android (APK / DEX / .so nativi) e iOS (IPA / Mach-O) destinate ad AArch64 e ad ARMv7 a 32 bit (librerie armeabi-v7a, A32 + Thumb).
Caricamento file
.apk, .aab), bundle iOS (.ipa) o qualsiasi binario ELF / Mach-O standalone (.so, .dylib, eseguibili grezzi) — Glass rileva automaticamente il formato.arm64e, con arm64 semplice come fallback. Funziona sia sui bundle sia sui file standalone (ad es. glass gui /usr/lib/dyld).libfoo.so distribuito in due APK (o lo stesso libswiftCore.dylib in due IPA) condivide lo stato di analisi.smali).iOS — IPA / Mach-O
Payload/*.app/, analizza Info.plist e seleziona la slice arm64 / arm64e da qualsiasi binario fat al suo interno.Frameworks/*.framework + *.dylib vengono caricati come singoli artefatti nativi, con le stesse viste Overview + disassembly per sezione usate per i file .so Android.__objc_classlist — classi, categorie, metodi, ivar, proprietà — con nomi demangiati (incluso il vecchio mangling Swift _TtC...) e salti cliccabili dagli indirizzi dei metodi all'elenco.__swift5_types — classi, struct, enum con i relativi campi e (per le classi) vtable, anch'esso cliccabile nell'elenco.Android — APK / DEX / nativo
.so nativi in lib/<abi>/ vengono caricati per ABI; AArch64 (arm64-v8a) e ARMv7 (armeabi-v7a) ricevono entrambi viste di disassembly completo. Le altre ABI (x86 / x86_64) vengono instradate alla vista hex finché non arriva un decoder.Modifica
r1 mostra solo varianti ARMv7; w0 mostra solo AArch64.AArch64 nativo (ELF + Mach-O thin)
.eh_frame e voci sintetizzate <name>@plt. Demangling C++/Rust/Swift tramite symbolic-demangle.adrp + add/ldr risolte verso target di dati, incluse le stringhe letterali mostrate inline come commenti.ARMv7 nativo (ELF)
00 00), Thumb-2 a 32 bit e A32 mostrano 4..eh_frame e voci sintetizzate <name>@plt (stub da 12 byte).movw + movt: movw R, #lo16 ; movt R, #hi16 viene rilevata tra coppie di istruzioni e la costante a 32 bit risolta riceve un commento ; "..." di stringa rodata sulla riga movt.ldr Rt, [pc, #imm] dereferenziano un livello nella rodata per lo stesso tipo di commento stringa inline che produce il percorso ADRP+ADD di AArch64.UI
change me trova changeMessage e change_me_count, ma non dispatchMenuVisibilityChanged).arm64-v8a + armeabi-v7a ottengono risultati unificati con artefatto + sezione etichettati per ogni corrispondenza.embedded.mobileprovision.resources.arsc).r0, lsl #2) e la memoria pre/post-index ([rN, #imm]!, [rN], #imm) vengono analizzati ma solo in modo concreto — nessuna wildcard tra parentesi.Glass gira su macOS 13+ (il target principale, accelerato via GPU con Metal — nessun SDK extra necessario, il framework Metal è incluso nel sistema operativo), Linux (X11 o Wayland tramite gpui_linux, basato su Vulkan) e Windows 10/11 (basato su Direct3D tramite gpui, compilato con la toolchain MSVC).
C'è un binario precompilato per macOS nella sezione Releases, ma se devi compilare dai sorgenti: la buona notizia è che bastano due comandi.
Questo include libxkbcommon-dev, gli header Wayland e XCB, Vulkan, ALSA e il resto della toolchain necessaria a gpui_linux per il link. Senza questi, la compilazione fallisce in fase di link con simboli xkbcommon / wayland-client mancanti.
Se preferisci non eseguire lo script, i pacchetti equivalenti su Debian / Ubuntu (amd64) sono: ```sh
sudo apt-get update && sudo apt-get install -y
build-essential clang cmake pkg-config
libfontconfig-dev libfreetype-dev
libwayland-dev libxkbcommon-x11-dev
libasound2-dev libvulkan-dev
libzstd-dev libsqlite3-dev libssl-dev
libglib2.0-dev
La build fallisce all'inizio in uno script di build delle dipendenze (`fontconfig was not found in the pkg-config search path`) se `libfontconfig-dev` manca, e in seguito in fase di link per le librerie X11/Wayland/Vulkan. `libglib2.0-dev` è necessario perché il driver Frida collega GLib dinamicamente su Linux (su macOS il devkit di Frida lo include staticamente) — senza di esso il link fallisce con `undefined symbol: g_object_unref`.
**Solo Windows — installa la toolchain di build nativa.** `gpui` richiede la toolchain MSVC (il target GNU/MinGW non è supportato). Usando [winget](https://learn.microsoft.com/windows/package-manager/winget/): ```powershell
# 1. MSVC compiler, linker, and Windows SDK (the "Desktop development with C++" workload).
winget install --id Microsoft.VisualStudio.2022.BuildTools `
--override "--quiet --wait --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended"
# 2. CMake — tree-sitter (via the Zed `language` crates) builds wasmtime's C API with it.
winget install --id Kitware.CMake
# 3. LLVM/Clang — `bindgen` (frida-sys, gpui, media) needs libclang.dll.
winget install --id LLVM.LLVM
Il programma di installazione di LLVM non aggiunge se stesso al PATH, quindi indica a bindgen il percorso di libclang.dll prima della compilazione (impostalo in modo permanente tramite Sistema → Variabili d'ambiente, o per shell): ```powershell
$env:LIBCLANG_PATH = "C:\Program Files\LLVM\bin"
Senza questi la build fallisce negli script di build delle dipendenze: `linker 'link.exe' not found` (senza MSVC), `failed to spawn 'cmake'` (senza CMake), o `Unable to find libclang` (senza `LIBCLANG_PATH`). La riserva di stack del binario `glass` viene aumentata automaticamente su MSVC (vedi `crates/glass-cli/build.rs`) così la CLI non va in overflow sul piccolo stack predefinito del thread principale di Windows — nessuna azione necessaria.
3. **Clona e compila**: ```sh
git clone https://github.com/azw413/Glass.git
cd glass
cargo build --release -p glass-cli
cp target/release/glass <to somewhere on your PATH>
La prima build compilerà gpui e le sue dipendenze e richiederà alcuni minuti. Le build successive sono veloci.
Eseguilo: ```sh
glass ~/path/to/app.apk glass ~/path/to/app.ipa
glass ~/path/to/libfoo.so glass ~/path/to/libBar.dylib glass /usr/lib/dyld
glass
glass bundle ~/path/to/app.apk
glass db-dump ~/path/to/app.apk
Usa sempre la build di release — le build di debug disassemblano ordini di grandezza più lentamente.
cargo build --release -p glass-cli ./packaging/make-app.sh open dist/Glass.app
Il bundle è firmato ad-hoc (non firmato con Developer-ID / non notarizzato), quindi al primo avvio macOS rifiuterà di aprirlo; clic destro → **Apri** per bypassare Gatekeeper una volta.
Due modi per ottenere uno zip precompilato senza compilare in locale:
- **Ultimo `main`** — ogni push carica un `Glass-app-<sha>.zip` come artefatto del workflow conservato per 14 giorni. Scaricalo dalla [scheda Actions](https://github.com/azw413/Glass/actions).
- **Release taggata** — il push di un tag `v*` (es. `v0.1.0`) attiva lo stesso workflow e pubblica inoltre un `Glass-<tag>-macOS.zip` nella [pagina Releases](https://github.com/azw413/Glass/releases) con note di release generate automaticamente.
## Workspace
| Crate | Scopo |
|------------------|------------------------------------------------------------------|
| `glass-core` | Tipi condivisi (`CodeKind`, ID) |
| `glass-arch-arm` | Disassemblaggio AArch64 + ARMv7, mappa dei simboli, sintesi PLT, demangling |
| `glass-arch-dex` | Facade DEX / smali sopra `smali` |
| `glass-mobile` | Caricamento bundle APK + IPA, estrazione librerie native, manifest |
| `glass-db` | Persistenza content-addressed (redb): bundle, schede, impostazioni |
| `glass-device` | Rilevamento dispositivi Android (adb) + iOS (usbmux) |
| `glass-api` | Verbi di analisi (ricerca, xref, CFG, modifiche) condivisi da CLI + MCP + GUI |
| `glass-ui` | Front-end `gpui`: albero, elenco, hex, manifest, palette |
| `glass-cli` | Ispettore headless + launcher GUI |
| `glass-mcp` | Server MCP che espone ogni verbo CLI come strumento |
| `glass-script` | Runtime plugin QuickJS (segnaposto) |
## Roadmap
- **iOS più approfondito** — Parsing di Entitlements e `embedded.mobileprovision`. (I pass di metadati ObjC `__objc_classlist` e Swift `__swift5_types` sono stati implementati — vedi `glass types` / `glass type`.)
- **x86 / x86_64** — Disassemblaggio per build da emulatore di file `.so` Android.
- **Scripting interno** — Host plugin QuickJS con API stabile per pass di analisi.
- **Avanzato** — Ricostruzione di APK firmati, downstream-shift sulle modifiche in-place ARMv7 (così le crescite da 2→4 byte possono essere saldate scavalcando il codice adiacente invece di essere rifiutate).
redb; al riavvio si riapre dove avevi lasciato.