Skip to content

Repository files navigation

IFDA — IoT Firmware Deep Analysis

English | 简体中文

Automated reverse engineering and vulnerability discovery for IoT firmware binaries. This repository implements the analysis core described in firmware-analysis-requirements.md.

Defensive / authorized use only. Analyze firmware you own or are authorized to assess. See requirements §1.3.

Screenshots

The web UI ships with the Go service layer (service/) and is bilingual throughout — every screen below exists in both English and Chinese.

Dashboard Findings
Dashboard — severity and vulnerability-class breakdown Findings list with severity, class and confidence filters
Per-scan totals, severity histogram and a breakdown by vulnerability class. Filter by severity, class, triage state, confidence or free text; export the filtered set as CSV/JSON.
Binaries Sign-in
Binaries table showing arch, libc and exploit mitigations Sign-in screen
Every ELF with its architecture, libc and mitigation posture (NX / canary / RELRO / PIE / FORTIFY), plus function, warning, CVE and string counts. Session auth with a captcha; theme and language are selectable before signing in.

The Chinese UI is shown in dashboard-zh.png and login-zh.png.

Iteration 1 scope

Per the agreed plan, the first iteration delivers binary reverse engineering (FR-RE) and vulnerability discovery (FR-VUL). It assumes ingestion and extraction (FR-ING / FR-EXT) have already produced files on disk — point it at a single ELF or an extracted firmware tree.

Engines wrap existing tooling: capstone (multiarch disassembly, works for MIPS/ARM regardless of host), pyelftools + binutils (ELF parsing, mitigations). A heavier taint engine (angr) is an optional future drop-in behind the same interface.

Architecture

        ┌───────────────────────────── Python analysis core (this repo) ──────┐
 extr.  │ loader/      re/            vuln/           inventory/ scripts/ fs/  │
 arts ──┼► load_elf ─► disassemble ─► dangerous_funcs ► secrets  shell    hard-│─► JSON /
 (FR-   │ (arch,       mitigations    taint (src→sink)  + rules/ (cmd-    ening │   Markdown
  EXT)  │  imports,    call-graph     cve correlation   signatures injection)  │   + SBOM
        │  strings)    xrefs          cross-binary +    + entropy             │   (CycloneDX)
        │                             prioritize/triage                       │
        └─────────────────────────────────────────────────────────────────────┘
                         ▲
                         │ exec `ifda.cli analyze --progress` per job
            Go service / orchestration layer (service/)  ← queue, workers,
            REST API (FR-INT-1), dedup cache, web UI with live progress

The Python core is a library + CLI. The hybrid architecture chosen for the project puts batch/corpus orchestration, the REST API (FR-INT-1), queueing (FR-ING-4), and a web UI in a separate Go service layer (service/, built) that drives this core one job at a time via the CLI. The JSON model (ifda/model.py) is the contract between the two; the core streams @@IFDA@@<json> progress events so the service shows live task progress. See service/README.md to build and run it.

Tech stack

Analysis core (Python 3.10+)

  • capstone — multiarch disassembly (x86/x86_64, ARM, ARM Thumb-2, AArch64, MIPS LE/BE)
  • pyelftools — ELF parsing and mitigation detection (NX/canary/RELRO/PIE/FORTIFY), no external binutils process needed
  • cve-bin-tool — required dependency for FR-VUL-1's broad CVE correlation (NVD/OSV/RedHat/GitLab Advisory/Curl, 350+ components)
  • yara-python (optional) — externalized YARA signature-rule bridge
  • angr (optional, future) — heavier taint/symbolic-execution engine, planned drop-in behind the existing taint interfaces

Service layer (Go 1.22+)

  • Standard library only, zero third-party Go dependencies — the enhanced net/http ServeMux (method + path-parameter routing), a hand-rolled PBKDF2 (crypto/hmac + crypto/sha256) for password hashing, image/image/png for the login CAPTCHA
  • Server-Sent Events (no polling, no WebSocket dependency) for live job progress

Web UI

  • Alpine.js 3.14.1 (vendored locally, no build step, works air-gapped)
  • Plain CSS with custom-property theming (7 built-in themes, light/dark aware)

Optional enrichment

  • Ghidra (headless mode) — decompiled pseudocode enrichment for findings

References & acknowledgements

  • EMBA — the open-source IoT firmware analyzer whose approach to CVE correlation and sensitive-data hunting shaped several design decisions here. IFDA follows EMBA's lead in delegating broad CVE correlation to cve-bin-tool rather than maintaining a hand-curated CVE list, and its config/ signature files (deep_key_search.cfg, password_regex.cfg, the *_files.cfg sensitive-path lists) informed both the sensitive-string keyword dictionary and a PEM-key detection gap this project fixed. Thanks to the EMBA team for the prior art.
  • cve-bin-tool (an OpenSSF project) — the actual engine behind FR-VUL-1's broad CVE coverage, and the same tool EMBA itself wraps for CVE correlation.

Platform support

ifda runs on Linux and macOS (Apple Silicon and Intel). Analysis happens on your machine, not on the firmware's target CPU: capstone disassembles MIPS/ARM/etc. regardless of the host architecture, so no cross-compilers or emulation are needed just to analyze a foreign-arch firmware. The Go service layer builds natively on both platforms — it uses a pure-Go SQLite driver (modernc.org/sqlite, no cgo), so go build needs no C toolchain and produces a self-contained binary. Scan job control (pause / resume / cancel) uses POSIX process groups, which work the same on Linux and macOS (Darwin).

Windows is not targeted; use WSL2 there.

Install

Full step-by-step environment setup (Go upgrade, cross-compilers, Ghidra + JDK pitfalls, verification) is in ENVIRONMENT.md. On macOS, see the dedicated macOS guide below.

# Python analysis core
apt-get install -y python3-capstone python3-pyelftools   # or: pip install -e .
pip install cve-bin-tool   # required: FR-VUL-1 broad CVE coverage (NVD/OSV/RedHat/GitLab/Curl)
pip install yara-python    # optional: enables the YARA stage if data/yara/*.yar exist

# Go service layer (optional — only if you want the REST API + web UI)
cd service && go build -o ifda-service .                # Go 1.22+

Running on macOS

The commands above assume Debian/Ubuntu. On macOS the only differences are the package manager and the Ghidra/JDK install; everything else is identical.

# 1. Toolchain via Homebrew (https://brew.sh)
brew install python@3.12 go            # Go 1.22+ for the service layer

# 2. Python analysis core — capstone/pyelftools ship arm64 + x86_64 wheels,
#    so pip works the same on Apple Silicon and Intel. A venv is recommended
#    so it doesn't touch the system/brew Python.
python3 -m venv .venv && source .venv/bin/activate
pip install -e .            # pulls in capstone + pyelftools
pip install cve-bin-tool    # required: broad CVE coverage
pip install yara-python     # optional: YARA stage

# 3. Go service layer (optional — REST API + web UI). Pure-Go SQLite means no
#    Xcode/CGO is required; it builds and runs natively on arm64 and Intel.
cd service && go build -o ifda-service . && cd ..

# 4. Ghidra pseudocode enrichment (optional; the --decompile flag / service
#    enrichment). Needs a JDK 17+ and Ghidra on PATH or at GHIDRA_HOME.
brew install --cask ghidra          # also pulls a JDK; or: brew install openjdk@17
export GHIDRA_HOME="$(brew --prefix)/opt/ghidra/libexec"   # adjust to your install

Then run exactly as on Linux — the CLI and service invocations in Usage below are platform-independent:

# CLI
python3 -m ifda.cli analyze /path/to/extracted_rootfs --json report.json

# Service (REST API + web UI at http://localhost:8080)
cd service && ./ifda-service -addr :8080

macOS-specific notes:

  • Gatekeeper: a Homebrew-installed Ghidra is already trusted; only a manually-downloaded Ghidra.app may need one right-click → Open, or xattr -dr com.apple.quarantine /path/to/ghidra.
  • Extraction tools (binwalk, unsquashfs, etc.) are ingestion-side and out of this repo's scope, but install cleanly via brew install binwalk squashfs when you need to unpack an image before pointing ifda at the extracted tree.
  • File permissions / hardening checks read standard Unix modes, which macOS provides — the weak_permissions findings (world-readable /etc/shadow, SSH host keys, etc.) work identically.

cve-bin-tool maintains its own local CVE database (NVD + OSV + RedHat + GitLab Advisory + Curl, ~1GB+); the first scan on a machine downloads/updates it, so expect that run to be slow and to need network access. Without it, analyze() still runs but CVE correlation falls back to the small curated data/vuln_db.json and the report carries a visible warning about the missing dependency (NFR-USE-1 — one missing piece degrades, it doesn't crash the job).

Usage

There are two ways to run ifda: the CLI (single run, scriptable) and the service (queue + REST API + web UI with live progress).

A. CLI — one-shot analysis

# Analyze a binary or an extracted tree; JSON to stdout by default.
python3 -m ifda.cli analyze /path/to/extracted_rootfs --json report.json --md report.md

# Emit a CycloneDX SBOM alongside the report.
python3 -m ifda.cli analyze ./rootfs --json report.json --sbom sbom.json

# Stream machine-readable progress events on stderr (used by the service).
python3 -m ifda.cli analyze ./rootfs --json report.json --progress

# Enrich findings with Ghidra decompiled pseudocode (opt-in; needs Ghidra,
# set GHIDRA_HOME or install to /opt/ghidra). Slow; degrades to no-op if absent.
python3 -m ifda.cli analyze ./rootfs --md report.md --decompile

# Triage a finding; persists across re-scans (FR-VUL-8).
python3 -m ifda.cli triage triage.json <finding_id> false_positive
python3 -m ifda.cli analyze ./rootfs --triage triage.json   # muted findings dropped

analyze accepts a single ELF or a directory (an extracted firmware tree). It walks the tree once and runs every stage: per-binary RE/vuln, cross-binary taint, secrets + signature rules + entropy, shell and PHP/Python/Lua script injection, and filesystem hardening.

B. Service — queue, REST API, and web UI

cd service
go build -o ifda-service .                 # Go 1.22+, first time only
./ifda-service -addr :8080 -core ..        # -core = repo dir (auto-detected if omitted)
# open http://localhost:8080

Flags: -addr, -core, -workers (default 2), -queue, -data (triage state

  • uploads dir; default $TMPDIR/ifda-service), -auth (default true), -user/-pass (seed an account on first run only — doesn't overwrite a password already changed via the web UI; add -reset-pass to force it). See service/README.md for the full explanation.

Web UI (Alpine.js, embedded — no build step, works air-gapped): submit a server path or upload a file, then watch live SSE progress and explore:

  • Dashboard — finding/critical/high/binary/CVE cards, severity and vuln-class distribution bars, component/config-file/certificate counts (click-through), a BusyBox overview card row, and a network-services/ open-ports card.
  • Findings — filter by severity toggles, vuln class, triage state, confidence threshold, and full-text search; sort by severity/confidence; expand for evidence, taint path, and Ghidra pseudocode; triage inline (confirm / false-positive / accept-risk / reset).
  • Binaries — per-binary arch, libc, mitigation chips (NX/Canary/RELRO/PIE/ FORTIFY, color-coded), function count, CVEs (server-side paginated).
  • Files — full non-ELF file listing, filterable by kind (binary/script/ config/symlink/other); click a row to expand a syntax-highlighted source preview inline.
  • BusyBox — compiled-in vs. reference-list "crippled" applets, extra bin/sbin executables at any tree depth, and /etc/init.d script source.
  • Network Services — statically identified services (name/category/ banner-derived version/port/port-source/binary path), filterable by category with keyword search.
  • CVE Database — browse the tool's actual CVE coverage (cve-bin-tool's broad set + the curated offline fallback) independent of any scan; CVE numbers throughout the UI link out to the matching NVD page.
  • Sensitive-string dictionary — standalone page to add/remove/reset the keyword dictionary used for secret matching, no scan required.
  • Compare — diff findings/files/strings between two scans (added/ removed/unchanged).
  • Export — download JSON / Markdown / SBOM.
  • User center — change password, log out.

REST endpoints (full table in service/README.md):

# enqueue a job (returns {"id": ...}); dedup cache returns cached unchanged targets
curl -XPOST localhost:8080/api/jobs -H 'Content-Type: application/json' \
     -d '{"target":"/path/to/extracted_rootfs"}'

curl -N  localhost:8080/api/jobs/<id>/events             # live progress (SSE, no polling)
curl     localhost:8080/api/jobs/<id>/report             # findings JSON (triage overlaid)
curl     "localhost:8080/api/jobs/<id>/report?format=md" # or format=sbom; add &download=1

# triage a finding — persisted by fingerprint, survives restarts & re-scans (FR-VUL-8)
curl -XPOST localhost:8080/api/jobs/<id>/triage -H 'Content-Type: application/json' \
     -d '{"finding_id":"<finding_id>","state":"false_positive"}'

# upload an artifact server-side, then submit the returned path as a target
curl -F "file=@firmware.bin" localhost:8080/api/upload   # -> {"target": "...", "name": ...}

Triage states: new | confirmed | false_positive | accepted_risk. Re-submitting an unchanged target returns a cached result.

C. AI-assisted report analysis (optional)

A static scan of a real firmware image easily produces tens of thousands of findings — most of them strcpy/system call sites with no proven input path. Reading that by hand is where the time goes. The service can hand a completed scan to an LLM that works through the findings with tools: it pulls evidence and pseudocode for the calls that look real, reads the init scripts and BusyBox applets to see what actually runs at boot, checks which services are network- reachable, and then writes up what's worth chasing and what's noise. In practice this cuts the false-positive triage down a lot and gets you to the handful of genuinely exploitable issues faster than scrolling the findings list.

Set it up in the web UI under AI settings: add a provider (custom Host URL, API key, model), pick OpenAI-compatible or Anthropic protocol, and run the analysis from a finished scan's AI Analysis tab. Keys are encrypted at rest; results stream live and are saved to the database.

It works with any OpenAI-compatible or Anthropic-protocol endpoint. If you can't reach the official APIs directly (common in mainland China) or just want cheaper access, a relay gateway works well — I run this against Claude (Opus / Sonnet) through aihuangniu, which is the gateway these AI features were tested on. Claude models in particular do a noticeably better job of grounding the analysis in the actual call sites instead of hand-waving. Any gateway that speaks the OpenAI or Anthropic wire format will do — the link is just the one I've been using.

Output

Format How Contents
JSON --json / GET …/report full structured report (the integration contract)
Markdown --md executive summary + per-finding detail
CycloneDX SBOM --sbom components + detected CVEs (Dependency-Track ready)

What's implemented

Requirement Status Where
FR-RE-1 Disassembly (multiarch) re/disasm.py (capstone)
FR-RE-3 CFG / call graph / fn boundaries ✅ (symbol + linear fallback) re/disasm.py
Import call resolution ✅ x86/x86_64 + ARM/AArch64 (PLT) + MIPS (GOT/jalr $t9) re/disasm.py
ARM/Thumb-2 + interworking veneers ✅ (mapping-symbol mode switch, veneer follow) re/disasm.py
FR-INV-4 Embedded secrets/credentials ✅ (keys, hashes, hardcoded creds/tokens, entropy fallback) inventory/secrets.py
FR-INT-3 Externalized signature rules (YARA-style) ✅ (updatable JSON rule library; optional yara-python bridge) rules/engine.py, data/secret_rules.json
FR-INV-3 Script analysis (shell/CGI cmd-injection) ✅ (taint-tiered) scripts/shell.py
FR-INV-3 Script analysis (PHP/Python/Lua injection) ✅ (cmd/code/file-incl/deserialization) scripts/langs.py
FS hardening (setuid, world-writable, weak perms, init) fs/hardening.py
FR-RE-5 Mitigations (NX/canary/RELRO/PIE/fortify) re/mitigations.py
FR-RE-6 Cross-references (call sites, strings) ✅ (call/import xrefs) re/disasm.py
FR-RE-7 Scriptable API ✅ (library + CLI) pipeline.py, cli.py
FR-RE-2 Decompiled pseudocode ✅ (opt-in Ghidra headless; enriches findings) re/decompile.py
FR-VUL-1 Known-CVE correlation ✅ curated offline DB + required cve-bin-tool (NVD/OSV/RedHat/GitLab/Curl, 350+ components); kernel version (own detector, not cve-bin-tool's checker) also correlated vuln/cve.py, vuln/cve_bin_tool.py, data/vuln_db.json
FR-VUL-2 Dangerous-function detection vuln/dangerous_funcs.py
FR-VUL-3 Taint / reachability ✅ (call-graph heuristic) vuln/taint.py
FR-VUL-4 Vuln-class coverage ◑ overflow/cmdi/code-inj/file-incl/deserialization/fmt/weak-crypto/path-traversal/auth-logic vuln/catalog.py, vuln/auth_weak.py, scripts/langs.py
FR-VUL-5 Cross-binary analysis ✅ (global call graph, CGI→lib) vuln/crossbinary.py
FR-VUL-7 Prioritization + evidence vuln/findings.py, model.py
FR-VUL-8 Triage state persistence vuln/findings.py
FR-VUL-6 Emulated/dynamic validation ⬜ planned (optional, sandboxed)
FR-REP-1 JSON + Markdown output report/
FR-REP-2 SBOM (CycloneDX 1.5) ✅ (SPDX TODO) report/sbom.py
FR-INT-1 REST API + queue + web UI (dashboard, filtering, triage, SSE) ✅ (Go service layer, Alpine.js) service/
FR-ING-4 Batch submission + dedup cache ✅ (workers + path-mtime cache) service/job.go
Config-file classification & content hardening audit ✅ (kind classification; content rule for telnet/anonymous-FTP/debug/SNMP-default-community/TLS-verify-off/WPS/UPnP) inventory/firmware_meta.py, vuln/config_audit.py
BusyBox applet audit ✅ (compiled vs. reference-list diff, extra bin/sbin executables, init.d dump) inventory/busybox_audit.py
Certificate detection ✅ (per-certificate RSA/non-RSA counts via cryptography, bundle/chain-aware) inventory/secrets.py
Network service identification ✅ (static-only; banner-derived versions, UCI/inetd/init.d-flag/default port inference) inventory/service_id.py
Stripped-binary function-boundary recovery ✅ (direct-call + prologue discovery, ARM/Thumb auto-detection) re/disasm.py

Legend: ✅ done · ◑ partial · ⬜ not started

Accuracy posture

Decompilation-free static analysis is heuristic (requirements §5). Findings carry confidence scores; precise call-site detections (0.8) rank above import-presence (0.4) and call-graph taint reachability (0.5). Taint findings are explicitly candidate paths for analyst validation, not proven exploits.

Tests

python3 -m pytest tests/ -q

25 passed, 2 skipped with cross-compilers + Ghidra installed (the skips are opt-in live tests — see ENVIRONMENT.md). They build real cross-compiled samples (x86_64, MIPS LE/BE, ARM, ARM Thumb-2, AArch64) and cover: the seeded command-injection acceptance case (source→sink path to system()), per-arch import-call resolution and cross-binary RCE, mitigation detection, CVE correlation — both the curated offline DB (including not flagging patched versions) and cve-bin-tool's entry parsing — embedded secrets (externalized signature rules + entropy fallback, with redaction), shell/CGI command injection, PHP/Python/Lua injection (cmd/code/file-inclusion/deserialization), filesystem hardening, CycloneDX SBOM, prioritization ordering, and triage persistence.

Changelog

Full technical detail (root causes, before/after numbers, test counts) is in PROGRESS.md's 变更记录 (Chinese). Feature-level summary:

  • v4.0 — AI analysis reliability + cross-platform docs. Interrupted provider streams (no [DONE]/finish_reason or message_stop/stop_reason) are now reported as interrupted, keeping the partial output, instead of being stored as a finished analysis ending mid-sentence. Fixes one scan's AI page showing another scan's cached analysis (stale frontend view state on job switch). Documents Linux + macOS support (Apple Silicon and Intel) with a macOS setup guide.
  • v3.9 — Live feedback while an AI analysis runs: a persistent status strip (pulse, phase label, elapsed clock, hairline sweep), a blinking caret on the streaming text, follow-the-tail output that yields to manual scrolling, and prefers-reduced-motion support. Fixes a progress indicator that vanished on the first token, leaving long pauses indistinguishable from a finished analysis.
  • v3.8 — AI-assisted analysis of scan results with a tool-calling agent. Per-provider config (custom Host URL, key, model, OpenAI-compatible or Anthropic protocol, max_tokens) with API keys encrypted at rest and a rotation command. NDJSON streaming with partial-content persistence. The model pulls scan data on demand — findings detail with evidence and pseudocode, init.d scripts, BusyBox audit, network services — instead of being fed a fixed sample, with automatic fallback for gateways lacking tool support. Finding selection collapses near-identical clusters and allocates round-robin across vulnerability classes so one CVE flood can't crowd out every other class.
  • v3.7 — Kernel-version CVE correlation using our own kernel detector (cve-bin-tool's own checker fails on Ubuntu-style compiler strings). Fixed an 8MB scan cap that silently missed kernel banners past that offset on real 35MB images. Dirty Pipe is expressed as three branch-precise version ranges so already-backported branches aren't misflagged.
  • v3.6 — FR-VUL-4 coverage: path traversal (reusing the existing taint engine with fopen/open/unlink/remove sinks) and auth-logic weakness (non-constant-time credential comparison in auth-named functions). Integer-overflow-into-alloc deliberately skipped as too noisy without argument-level analysis.
  • v3.5 — Static network service identification (WEB/SSH/FTP/Telnet/gSOAP/ DNS/SNMP/UPnP/WiFi-management daemons); versions read only from embedded banner strings, never guessed; ports inferred from UCI config → inetd.conf → init.d launch flags → known defaults. New "Network Services" tab + dashboard service/port-count cards. Fixed duplicate service counting from same-named config/init.d files vs. the real ELF binary.
  • v3.4 — Real certificate detection (RSA vs. non-RSA per certificate, bundle/chain-aware, via the cryptography library instead of a PEM-header guess). Dashboard gains component/config-file/certificate counts and a BusyBox overview card row.
  • v3.3 — Fixed a v3.2 regression where config files silently lost their click-to-preview affordance. Binaries/Scripts tabs moved from ?all=1 bulk loads to real server-side pagination.
  • v3.2 — New "config" file classification (extension/basename/UCI-path/ content-sniff) with a server-side Files-tab Kind filter. New config_audit.py content-hardening rule (telnet, anonymous FTP, debug mode, default SNMP community strings, disabled TLS verification, WPS, UPnP left enabled). CVE numbers throughout the UI now link to NVD. Zero-dependency syntax highlighting for file/BusyBox previews. Fixed compare-scan silently reporting "0 added / all removed" instead of a clear error on a failed report fetch.
  • v3.0 — Stripped-ELF function-boundary recovery (direct-call + prologue discovery, ARM/Thumb auto-detection). CVE sync reliability fixes (upstream cve-bin-tool bug patches, NVD GitHub-mirror bootstrap script). Findings/binaries/scripts/components migrated from one JSON blob per job to SQLite with server-side pagination, fixing both a UI crash on large scans and a hidden export-truncation bug. New BusyBox applet audit tab (compiled vs. reference-list diff). Fixed a severe compare-scan accuracy bug caused by absolute-path fingerprint matching. Fixed the dedup cache silently serving pre-upgrade reports after an analyzer version bump.
  • v2.0 — Bilingual docs (this README.zh-CN.md), a Tech stack section, and a References & acknowledgements section (crediting EMBA and cve-bin-tool).
  • v1.0 — Initial release: multi-arch disassembly & import-call resolution (x86/x86_64, ARM, ARM Thumb-2, AArch64, MIPS LE/BE), vulnerability discovery (dangerous functions, taint/reachability, cross-binary taint, CVE correlation, CycloneDX SBOM, prioritization + triage persistence), embedded-secrets and script-injection detection, filesystem hardening, optional Ghidra decompilation, and the Go service layer + Alpine.js web UI.

Next iterations

  • Replace heuristic taint with angr behind the existing detect_taint_paths / detect_cross_binary_taint interfaces.
  • FR-VUL-4: integer-overflow-into-alloc/copy detection (skipped so far — a naive "tainted size reaches malloc/realloc" sink would be too noisy given how ubiquitous allocation is; needs real argument-level analysis, e.g. spot a multiply feeding the size operand, not just reachability).
  • FR-VUL-6 optional sandboxed emulation to confirm reachability, and true dynamic network-service probing (distinct from the static, signature-based service identification already shipped — see inventory/service_id.py).
  • FR-REP-2 SPDX output alongside CycloneDX.
  • Service layer: unify job-queue storage (service/job.go, per-job JSON files) with the report store (service/reportdb.go, SQLite) onto one backend. Auth (pbkdf2 + per-account lockout + login CAPTCHA, service/auth.go
    • service/captcha.go) and persistent report storage are already built.

Call resolution for x86/x86_64, ARM, ARM Thumb-2, AArch64, and MIPS LE/BE is all in place.

About

IoT Firmware Deep Analysis: Automated reverse engineering and vulnerability discovery for IoT firmware binaries.

Topics

Resources

Stars

41 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages