Date: 2026-05-25
Purpose: use EMBA as a firmware triage engine for IoT reverse engineering and vulnerability research. EMBA should produce leads. Manual analysis decides whether a lead is real, reachable, and worth reporting.
- Role Of EMBA
- How To Make The Most Of EMBA
- Kali vs Ubuntu Tool Split
- Safety Rules
- Case Folder Layout
- Preflight
- Walkthrough
- Most Useful Command Combinations
- EMBA Emulation: What To Do
- EMBA vs QEMU vs Qiling vs Unicorn vs Ghidra
- How To Read Results
- Lead Selection
- AI Usage
- Sources
Use EMBA for:
- extraction attempts
- component/version inventory
- SBOM-style package discovery
- CVE and exploitability hints
- weak binary-function ranking
- credential/private-key/config discovery
- web/service/config attack-surface discovery
- report/evidence generation
Do not use EMBA as:
- the final vulnerability judge
- proof of reachability
- proof that a CVE applies to the actual shipped firmware behavior
- a replacement for reading the vulnerable script/binary/config path yourself
Good final-reviewer sentence:
EMBA identified <lead>. I manually verified reachability through <route/service/config>, traced the vulnerable data flow into <file/function>, and reproduced <impact> with <command/request/test>.
Use EMBA in layers:
static inventory -> candidate lead -> reachability proof -> impact proof -> report
For an interview assignment, this is the best workflow:
- Run a quick/default scan and let EMBA build the first inventory.
- Open the HTML report only to orient yourself.
- Move to the raw logs and extracted filesystem for evidence.
- Pick leads with attacker reachability: web route, exposed service, update path, parser, script, credential, or command execution sink.
- Prove one path deeply instead of listing ten unverified CVEs.
The most useful EMBA modules/results are the ones that point to manual verification:
| EMBA result | Manual follow-up |
|---|---|
| Version/SBOM/CVE finding | Confirm exact binary/library/version, then prove the vulnerable code is reachable. |
| Shell/Python/PHP/Lua finding | Trace input to sink and build a minimal request/command that reaches it. |
| Credential/key/config hit | Identify the service or account that consumes it. |
| Weak binary/security hardening result | Find caller, reachable parser, or service context before claiming impact. |
| System-emulated service | Interact with the exposed port/route and capture evidence. |
Use EMBA's AI/OpenAI mode only as an optional explainer for selected snippets. The official AI page now marks the older integration as under heavy rework, and the LocalAI page is still under construction. For now, manual AI usage over small copied evidence bundles is safer and easier to control.
You do not need to give me the full list of tools inside the EMBA Docker image unless a scan fails or you want an exact dependency audit. For your roadmap, the useful split is enough:
If Kali/EMBA works well, Ubuntu is not required for the assignment. The smallest useful setup is:
Kali VM: EMBA + manual Linux CLI checks
Windows host: GUI reverse engineering if needed
Ubuntu VM: optional backup only
| Environment | Job | Why |
|---|---|---|
| Kali VM | EMBA classic Docker mode, broad automated triage, EMBA reports | Matches EMBA's tested workflow best |
| Ubuntu VM | manual workbench: extraction, grep, QEMU/GDB, scripts, tcpdump, report evidence | Keeps manual analysis clean and avoids duplicating EMBA's container-heavy stack |
| Windows host | GUI RE with IDA/Ghidra/Binary Ninja if installed | More comfortable UI, less load inside the VM |
The Ubuntu autoinstall package list is now intentionally lean. It keeps manual tools that complement EMBA:
binwalk, squashfs-tools, cpio, xz/lzma/zstd, file, binutils
ripgrep, jq, tree
python3, pip, venv
qemu-user-static, qemu-system-arm/mips/x86
gdb-multiarch, strace, ltrace
nmap, tcpdump, iproute2, net-tools
It no longer installs Docker by default. Add Docker to Ubuntu only if Ubuntu becomes your fallback EMBA host or you need containerized tools outside Kali.
I checked upstream installer.sh and the installer modules. In default Docker mode (sudo ./installer.sh -d), EMBA still modifies/prepares the host, but the heavy analyzer stack is Docker-centered.
Host-side work includes:
- distribution/architecture/RAM/disk checks
apt-get updatepython3-venvexternal/and EMBA Python virtual environment- Docker CE / Docker Compose plugin if missing
- small host helpers:
jq,shellcheck,unzip,bc,coreutils,ncurses-bin,libnotify-bin,inotify-tools,dbus-x11,git,net-tools,curl,file,python3-pip, Pythonrequests - pull/prepare
embeddedanalyzer/emba - host-side NVD feed setup
Docker/image-centered work includes the large analyzer toolchain modules such as extractors, disassembly/decompilation helpers, unblob/binwalk handling, APK/source/kernel checks, YARA/password/search tooling, CWE checker, system-emulation helpers, CVE tooling, and aggregator/reporting support. In -d mode the installer still calls the module installer functions, but heavy module installers are guarded so they are not broadly installed on the host; they are part of the Docker image/build path.
Implication:
Do not duplicate EMBA's heavy toolchain in Ubuntu by default.
Use Ubuntu only for manual tools or as a no-EMBA fallback.
Always use EMBA classic Docker mode. Avoid developer mode:
Avoid: -D
Reason: developer mode runs on the host without container protection.
Understand EMBA emulation levels:
| Mode | Meaning | Risk |
|---|---|---|
| normal profile scan | mostly static triage, but current quick/default profiles enable some QEMU user-mode version checks | moderate, Dockerized |
-E / QEMULATION=1 |
QEMU user-mode execution of firmware binaries | higher, still Dockerized in classic mode |
-Q / FULL_EMULATION=1 |
QEMU full-system/service emulation | highest |
VMware network rule:
Install/update/Docker pull: NAT
Quick/default profile scan: NAT is acceptable if no bridged networking and no port forwarding
Any full emulation/service testing: Host-only, NAT disconnected if internet is not needed
Avoid: Bridged
Before -Q, default-scan-emulation.emba, or service testing:
ip -br addr
ip routeYou want no bridged adapter and preferably no normal NAT default route.
Use one folder per firmware image. Do not overwrite previous runs.
CASE=fw_case_01
mkdir -p ~/firmware/$CASE/original ~/firmware/$CASE/work ~/emba_logs/$CASECopy the firmware:
cp /path/to/firmware.bin ~/firmware/$CASE/original/
FW=~/firmware/$CASE/original/firmware.bin
LOG=~/emba_logs/$CASERecord facts before scanning:
sha256sum "$FW" | tee "$LOG/sha256.txt"
file "$FW" | tee "$LOG/file.txt"
ls -lh "$FW" | tee "$LOG/size.txt"From the EMBA directory:
cd ~/tools/emba
sudo ./emba -V
sudo ./emba -d 1
ls -1 scan-profilesUse dependency check meanings:
-d 1: host and container dependency check
-d 2: container-only dependency check
If -d 1 fails, fix setup before scanning. If only a non-critical module dependency fails, document it and decide whether the missing module matters.
If the only surprising line is:
Docker image version - Updates available
but the Docker-compose EMBA image version status line in the same EMBA output is ok and scans start, this is usually a digest mismatch against EMBA's online-check metadata. That phrase is EMBA output text, not a command to type. Run sudo ./emba -U before the assignment if you have time. If it still appears, record it in your setup notes and proceed unless Docker/container checks actually fail.
Run this first. On your weaker host, keep it conservative:
cd ~/tools/emba
sudo ./emba \
-l "$LOG/01_quick" \
-f "$FW" \
-p ./scan-profiles/quick-scan.emba \
-P 1 \
-T 1What it is for:
- confirms EMBA can extract/analyze the image
- gives a first report quickly
- avoids several long modules
- gives enough evidence to choose a manual direction
Do not start with full-scan.emba.
Open the HTML report if available:
firefox "$LOG/01_quick/html-report/index.html"Search the text logs:
rg -n "CRITICAL|HIGH|CVE|Exploit|password|passwd|shadow|private key|authorized_keys|dropbear|uhttpd|lighttpd|boa|cgi|command injection|setuid|world writable|strcpy|system\\(|popen\\(" "$LOG/01_quick"Create a small lead table:
Lead | Evidence file/log | Reachable from network? | Exploit idea | Manual verification command
If a lead has no reachable route/service/config path, it is a lower priority.
Run default after quick scan succeeds:
sudo ./emba \
-l "$LOG/02_default" \
-f "$FW" \
-p ./scan-profiles/default-scan.emba \
-P 1 \
-T 1Use -P 2 -T 1 or -P 2 -T 2 only if the VM remains responsive and RAM is stable.
EMBA tells you where to look. Then you verify manually:
mkdir -p ~/firmware/$CASE/work
if [ -d "$LOG/02_default/firmware" ]; then
cp -a "$LOG/02_default/firmware" ~/firmware/$CASE/work/extracted
fi
cd ~/firmware/$CASE/work/extractedManual triage commands:
find . -maxdepth 4 -type d | rg "/www|/web|/htdocs|/cgi|/etc|/init.d|/rc.d"
find . -type f \( -name "*.cgi" -o -name "*.sh" -o -name "*.php" -o -name "*.lua" \)
rg -n "system\\(|popen\\(|eval|exec|shell_exec|passthru|subprocess|os\\.system|`.*`|\\$\\(|nvram|uci|getenv|QUERY_STRING|REQUEST_METHOD" .
rg -n "password|passwd|shadow|authorized_keys|BEGIN .*PRIVATE KEY|telnet|dropbear|uhttpd|lighttpd|boa" .
find . -perm -4000 -o -perm -2000 2>/dev/nullFor a binary lead:
file ./path/to/binary
checksec --file=./path/to/binary 2>/dev/null || true
readelf -h ./path/to/binary
strings -a ./path/to/binary | rg "http|cgi|password|system|popen|strcpy|sprintf|/bin/sh"Then open the binary in Ghidra/IDA/Binary Ninja if the path looks reachable.
Do not emulate just because EMBA can. Emulate only when it helps prove one of these:
- a web route reaches the vulnerable parser
- an init script starts the service
- a binary crashes with controlled input
- a version check proves a vulnerable component is present
Before full-system/service emulation, switch VMware to Host-only.
cd ~/tools/emba
sudo ./emba -V
sudo ./emba -d 1
sudo ./emba -d 2Use when:
- after install
- after an EMBA update
- before a time-boxed assignment
sudo ./emba -l "$LOG/01_quick" -f "$FW" -p ./scan-profiles/quick-scan.emba -P 1 -T 1Use when:
- first scan of any firmware
- weak host
- interview time pressure
sudo ./emba -l "$LOG/02_default" -f "$FW" -p ./scan-profiles/default-scan.emba -P 1 -T 1Use when:
- quick scan completed
- you need a web report, SBOM-style inventory, and prioritized leads
sudo ./emba -l "$LOG/02_default_fast" -f "$FW" -p ./scan-profiles/default-scan.emba -P 2 -T 1Use only if:
- the VM has enough RAM
- the host remains responsive
- you are not already seeing OOM messages in
dmesg
Use this after a baseline run, or when the assignment likely involves web admin panels, CGI, credentials, or startup configs:
sudo ./emba \
-l "$LOG/03_web_auth_secrets" \
-f "$FW" \
-m p \
-m s35 \
-m s40 \
-m s45 \
-m s50 \
-m s65 \
-m s75 \
-m s80 \
-m s85 \
-m s95 \
-m s100 \
-m s106 \
-m s107 \
-m f50 \
-W \
-z \
-s \
-P 1 \
-T 1Why -m p is included: pre-check/extraction modules prepare the firmware tree. Numeric p modules are not normally selected manually, but -m p asks EMBA to run the pre-checker group.
Use this when you already identified reachable native binaries:
sudo ./emba \
-l "$LOG/04_binary_risk" \
-f "$FW" \
-m p \
-m s10 \
-m s12 \
-m s13 \
-m s17 \
-m f50 \
-c \
-W \
-z \
-s \
-P 1 \
-T 1Before relying on exact module numbers, confirm your local EMBA module names:
ls modules/S*_*.sh | rg "S10|S12|S13|S15|S16|S17|cwe|ghidra|radare|binary"Module numbers can move over time. Profiles are safer than handcrafted module lists.
sudo ./emba -l "$LOG/05_sbom" -f "$FW" -p ./scan-profiles/default-sbom.emba -P 1 -T 1Use when:
- you need a clean component inventory
- you want a smaller run focused on packages/versions
- the reviewer cares about CVE triage, but you still need manual reachability proof
Only after switching VMware to Host-only:
sudo ./emba -l "$LOG/06_emulation" -f "$FW" -p ./scan-profiles/default-scan-emulation.emba -P 1 -T 1Use when:
- a static lead needs service/runtime confirmation
- you have time to debug emulation failures
- you already know which service or path you care about
Do not use this as the first scan.
Do not jump to emulation first. Use it only after you already have a candidate that benefits from runtime proof.
Good reasons to emulate:
- confirm that an init script starts a web/service binary
- identify the runtime IP/ports EMBA can bring up
- collect Nmap/web checks from an emulated system
- confirm that a candidate route/service exists at runtime
- produce extra evidence for a report
Bad reasons to emulate:
- "maybe it will find a vulnerability"
- before extraction/static triage works
- before you know what service/path you care about
- while VMware is bridged to your LAN
Safe sequence:
1. Run quick/default scan.
2. Pick one candidate.
3. Snapshot VM.
4. Switch VMware to Host-only if doing service/full-system emulation.
5. Run default-scan-emulation.
6. Search emulation logs for IPs, ports, service names, URLs, and QEMU archive paths.
7. Manually test only the candidate surface.
Run:
sudo ./emba \
-l "$LOG/06_emulation" \
-f "$FW" \
-p ./scan-profiles/default-scan-emulation.emba \
-P 1 \
-T 1Then inspect:
rg -n "open port|Nmap scan report|ONLINE|IP address|network|http|https|login|admin|qemu|archive|emulation" "$LOG/06_emulation"
find "$LOG/06_emulation" -maxdepth 4 -type f | rg "L[0-9].*\\.txt|nmap|web|qemu|archive|html-report"
find "$LOG/06_emulation" -iname "*qemu*" -o -iname "*archive*"If EMBA reports an emulated IP/port on the Host-only network, verify from the VM or Windows host:
nmap -sV -Pn <emulated-ip>
curl -i http://<emulated-ip>/
curl -i http://<emulated-ip>/cgi-bin/<candidate>If EMBA cannot emulate the firmware, do not burn the whole assignment on it. Extract the rootfs and switch to the Ubuntu no-EMBA workflow:
ubuntu-no-emba-backup-guide.md
For a report, phrase emulation carefully:
EMBA system emulation exposed <service/port>. I then manually verified <route/request> and traced it to <file/function>.
Do not write:
EMBA proved the exploit.
EMBA is not "better than Qiling/Unicorn" in the abstract. They answer different questions.
| Tool | What it is | Best use |
|---|---|---|
| EMBA emulation | automated firmware-analysis workflow around QEMU user-mode and full-system/service emulation, with extraction, kernel/rootfs/service setup, logs, Nmap/web checks, and reporting | broad firmware triage and "can this firmware expose services under emulation?" |
| QEMU user-mode | runs one Linux userland binary for another architecture, translating syscalls to the host | quick binary behavior/version tests with target rootfs libraries |
| QEMU system-mode | emulates a whole machine: CPU, memory, devices, kernel, storage, network | booting a firmware/rootfs when you know the kernel/rootfs/device model path |
| Qiling | Python framework built on Unicorn with OS/syscall abstractions, loaders, hooks, and scripting | focused single-binary harnesses where you want hooks and repeatable instrumentation |
| Unicorn | CPU emulator framework | raw function/basic-block emulation when you provide memory/register/syscall scaffolding |
| Ghidra emulator | p-code emulator tied to Ghidra's decompiler/language semantics | stepping a function/basic block, experimenting with state/patches, understanding logic |
Practical choice:
Need broad firmware triage/report: EMBA
Need to run one MIPS/ARM Linux binary with firmware libraries: QEMU user-mode
Need whole router service boot: EMBA first, manual QEMU/FirmAE-style work only if needed
Need hookable scripted harness for one binary: Qiling
Need emulate a function/snippet with full control: Unicorn
Need reason about one function in RE UI: Ghidra p-code emulator
EMBA's system emulation is QEMU-based, but it is not "just qemu." EMBA adds extraction context, architecture/rootfs selection, kernel choice, init/service helpers, networking attempts, follow-up checks, logs, reports, and reusable QEMU archives.
Ghidra's emulator is p-code emulation. It is useful for reasoning about code, not for accurately booting Linux services or proving network reachability.
Only if the assignment allows time and the VM is stable:
sudo ./emba -l "$LOG/99_full" -f "$FW" -p ./scan-profiles/full-scan.emba -P 1 -T 1Use when:
- you already have a manually verified primary finding
- you want additional supporting leads
- you can leave the VM running
Useful if you have two firmware versions:
OLD_FW=~/firmware/$CASE/original/old.bin
NEW_FW=~/firmware/$CASE/original/new.bin
sudo ./emba -l "$LOG/07_diff" -f "$OLD_FW" -o "$NEW_FW" -W -z -s -P 1 -T 1Use when:
- a vendor patched something
- you want to locate changed services/scripts/binaries
- you want to infer a vulnerability from a patch
If you extracted a kernel config:
sudo ./emba -l "$LOG/08_kernel_config" -k ./kernel.configUse when:
- kernel hardening matters
- you need a quick config assessment
| Flag | Use |
|---|---|
-l PATH |
log directory |
-f PATH |
firmware path |
-p PROFILE |
profile from scan-profiles/; safest normal usage |
-m MODULE |
targeted module/group; advanced |
-P N |
max modules in parallel |
-T N |
max threads per module |
-W |
create web report |
-z |
color/format log output |
-s |
short/relative paths |
-E |
user-mode QEMU tests |
-Q |
full-system emulation tests |
-c |
extended binary analysis |
-q |
disable deep extraction |
-e PATH |
exclude path |
-o PATH |
diff against second firmware |
-r |
remove temporary extracted firmware after run |
-y |
overwrite log directory |
-U |
update EMBA and exit |
-Y, -Z, -X, -N |
vendor/device/version/notes metadata; keep values simple |
Avoid -r while learning. Keeping extracted files helps manual verification. Use -r only when disk pressure matters and you already copied evidence.
Avoid -y unless you intentionally want to destroy a previous run's logs.
Avoid -U during an active assignment unless EMBA is broken. Snapshot first.
Start here:
$LOG/<run>/html-report/index.html
$LOG/<run>/emba.log
$LOG/<run>/f50_base_aggregator.txt
$LOG/<run>/csv_logs/
$LOG/<run>/json_logs/
Fast log searches:
rg -n "CRITICAL|HIGH|MEDIUM|CVE|Exploit|EPSS|KEV" "$LOG/02_default"
rg -n "password|passwd|shadow|private key|authorized_keys|root:" "$LOG/02_default"
rg -n "command injection|system\\(|popen\\(|shell|cgi|QUERY_STRING|REQUEST_METHOD" "$LOG/02_default"
rg -n "setuid|world writable|weak permission|dropbear|telnet|uhttpd|lighttpd|boa" "$LOG/02_default"When EMBA shows a CVE:
- Identify the component and version evidence.
- Locate the actual file/binary/package in the firmware.
- Determine whether the vulnerable feature is built/enabled.
- Determine whether an attacker can reach it.
- Reproduce impact or explain exactly why reproduction was not possible.
For a time-boxed firmware analysis, score each lead:
| Factor | Good sign |
|---|---|
| Reachability | exposed web route, network service, update parser, startup script |
| Control | attacker controls a parameter, file, header, config, archive, or network input |
| Sink | command execution, path traversal, auth bypass, memory corruption, default credential, key leak |
| Evidence | exact file/function/line, EMBA log, manual grep, decompiler screenshot, curl/QEMU/GDB output |
| Reproducer | one command or request demonstrates behavior |
Pick one strong reachable finding over five vague CVEs.
Good candidate examples:
CGI route -> unsanitized parameter -> system/popen
web upload/update handler -> tar/path traversal
hardcoded credential/key -> reachable SSH/web/admin path
setuid helper -> attacker-controlled argv/env/file path
network daemon -> unsafe parser -> crash or controlled overwrite
old component CVE -> exact version + vulnerable feature + reachable service
Bad primary candidates:
generic old BusyBox CVE with no reachable applet
private key that is never used
weak function count with no caller/data-flow
kernel CVE with no kernel config/build evidence
EMBA "possible exploit" with no local component proof
Use AI after EMBA has produced concrete artifacts.
Good prompt:
Here are EMBA excerpts for S35/S45/S50/S100 and the relevant files from the firmware.
Build a lead table with: reachable surface, source file, controlled input, dangerous sink, verification command, and confidence.
Do not invent routes or claims not present in the evidence.
Good prompt for a script:
Write a read-only Python script that parses this EMBA log directory and extracts candidate web routes, scripts, binaries, credentials, and CVEs into a CSV. Do not run commands. Do not modify files.
Bad prompt:
Find the vulnerability in this firmware.
The useful AI loop:
EMBA output -> narrow evidence bundle -> AI summary/lead table -> manual verification -> report
Treat EMBA's built-in OpenAI mode as optional.
It can help explain scripts and decompiled snippets, but it is not the best first move for an interview assignment. The current default-scan-gpt.emba profile enables GPT_OPTION=1 and also enables QEMULATION=1, so it is not just "static scan plus AI." The OpenAI module sends selected snippets to the OpenAI chat completions API and records the answers in EMBA logs.
Use it only if:
- uploading firmware snippets is allowed
- cost/rate limits are acceptable
- you already have a normal scan and know what you want to ask
Better default:
Run quick/default scan without EMBA AI.
Bundle only relevant logs/files.
Ask AI for a lead table and verification plan.
Manually prove or reject each lead.
- EMBA usage wiki: https://github.com/e-m-b-a/emba/wiki/Usage
- EMBA installation wiki: https://github.com/e-m-b-a/emba/wiki/Installation
- EMBA feature overview: https://github.com/e-m-b-a/emba/wiki/Feature-overview
- EMBA system emulation: https://github.com/e-m-b-a/emba/wiki/System-emulation
- EMBA FAQ: https://github.com/e-m-b-a/emba/wiki/FAQ
- EMBA SBOM/vulnerability aggregation: https://github.com/e-m-b-a/emba/wiki/The-EMBA-book-%E2%80%90-Chapter-5%3A-SBOM-and-vulnerability-aggregation
- EMBA AI supported firmware analysis: https://github.com/e-m-b-a/emba/wiki/AI-supported-firmware-analysis
- EMBA LocalAI supported firmware analysis: https://github.com/e-m-b-a/emba/wiki/LocalAI-supported-firmware-analysis
- EMBA 2.0 heise report: https://www.heise.de/en/news/EMBA-2-0-Firmware-analyzer-achieves-95-percent-emulation-success-11119751.html
- EMBA scan profiles: https://github.com/e-m-b-a/emba/tree/master/scan-profiles
- EMBA parameter parser: https://github.com/e-m-b-a/emba/blob/master/helpers/helpers_emba_parameter_parser.sh
- EMBA GPT profile: https://github.com/e-m-b-a/emba/blob/master/scan-profiles/default-scan-gpt.emba
- EMBA OpenAI module: https://github.com/e-m-b-a/emba/blob/master/modules/Q02_openai_question.sh
- EMBA GPT config template: https://github.com/e-m-b-a/emba/blob/master/config/gpt_config.env.template
- QEMU user-mode documentation: https://www.qemu.org/docs/master/user/main.html
- QEMU system emulation documentation: https://www.qemu.org/docs/master/system/introduction.html
- Qiling architecture overview: https://github.com/qilingframework/qiling/wiki/Architecture-Overview
- Unicorn engine: https://www.unicorn-engine.org/
- Ghidra p-code emulation: https://ghidra.re/ghidra_docs/GhidraClass/Debugger/B2-Emulation.html