HALucinator
Firmware rehosting through abstraction layer modeling.
HALucinator runs embedded firmware binaries without the original hardware. Rather
than emulating every peripheral register, it intercepts calls to the firmware's
hardware abstraction layer — HAL_UART_Transmit, spi_write, and friends —
and answers them in Python. Replacing a handful of HAL functions is usually
enough to boot a binary that would otherwise fault immediately on missing
hardware, which makes firmware reachable for debugging, analysis, and fuzzing.
Install
pip install halucinator
That is a complete, working rehosting setup. The unicorn backend ships by default because it is the only one that needs no externally-built binary, so there is nothing else to install before emulating a binary.
| Extra | Installs | For |
|---|---|---|
[net] |
scapy, pyserial | Host network / serial external devices |
[symbols] |
cle | ELF symbol extraction via hal_make_addr |
[mcp] |
mcp[cli] | The halucinator-mcp server |
[all] |
all of the above | Everything except the dev tooling |
[unicorn] still resolves as a no-op alias, so older instructions saying
pip install halucinator[unicorn] keep working.
Requires Python 3.10 or newer.
Other backends
HALucinator supports several execution backends, selected with --emulator:
unicorn, qemu, avatar2, libafl-qemu, renode, and ghidra. Only
unicorn is installable purely from PyPI — the others depend on an external
QEMU build, a Renode install, or the avatar2 fork tracked in the source
repository. See the repository
README for those setups.
Usage
Emulation is driven by YAML configuration. Configs are conventionally split into three files — memory layout, intercepts, and a symbol/address map — which HALucinator concatenates, with later files taking precedence:
halucinator -c memory.yaml -c intercepts.yaml -c addresses.yaml --emulator unicorn
Splitting them this way keeps the intercept list portable across builds of the same firmware: only the address map changes when the binary is recompiled.
Configuration sketch
Memory layout and emulated peripherals:
memories:
flash: {base_addr: 0x8000000, size: 0x200000, permissions: r-x, file: firmware.bin}
ram: {base_addr: 0x20000000, size: 0x51000}
peripherals:
logger: {base_addr: 0x40000000, size: 0x20000000, permissions: rw-, emulate: GenericPeripheral}
What to intercept, and which handler answers it:
intercepts:
- class: halucinator.bp_handlers.stm32f4.stm32f4_uart.STM32F4UART
function: HAL_UART_Transmit
symbol: HAL_UART_Transmit
- class: halucinator.bp_handlers.generic.common.ReturnZero
function: HAL_RCC_OscConfig
symbol: HAL_RCC_OscConfig
function selects the handler method (matched against the handler's
@bp_handler decorator); symbol resolves the address from the symbol map, so
prefer it over hardcoding addr. Handlers accept class_args for
per-intercept configuration.
The full schema — machine settings, watchpoints, registration_args,
run_once, and the peripheral model list — is documented in the repository
README.
Handler families
Prebuilt intercept handlers ship for common HALs and RTOSes:
- generic —
ReturnZero,ReturnConstant,SkipFunc, counters, timers - stm32f4 — STM32F4 HAL: UART, GPIO, SPI, ethernet, timers, WiFi
- libopencm3 — ADC, DMA, flash, GPIO, RCC, SPI, timer, USART
- atmel_asf_v3 — Atmel ASF: contiki, ethernet, radio, SD/MMC, timers, USART
- mbed — Mbed OS: boot, serial, timer
- vxworks — VxWorks: boot, filesystem, ethernet, interrupts, scheduler, tasks
- zephyr — Zephyr: filesystem, UART
Command-line tools
| Command | Purpose |
|---|---|
halucinator |
Run an emulation from config files |
hal_make_addr |
Extract a symbol/address map from an ELF (needs [symbols]) |
hal_dev_uart |
UART external device — the interactive console |
hal_dev_host_eth, hal_dev_host_eth_server |
Bridge emulated ethernet to the host |
hal_dev_virt_hub, hal_dev_eth_wireless |
Virtual network hub and wireless link |
hal_dev_802_15_4 |
IEEE 802.15.4 radio device |
hal_dev_irq_trigger |
Inject interrupts into a running emulation |
halucinator-mcp |
MCP server for agent-driven rehosting (needs [mcp]) |
qemulog2trace |
Convert QEMU logs to execution traces |
External devices communicate with the emulator over ZeroMQ, so they run as
separate processes — typically one terminal for hal_dev_uart and another for
halucinator itself.
Supported architectures
ARM Cortex-M · ARM (full, e.g. arm926) · AArch64 · MIPS · PowerPC · PowerPC64
Documentation
Full documentation, worked examples, the VSCode extension and debug-adapter integration, and the developer setup live in the source repository:
https://github.com/halucinator/halucinator
License and credit
GPL-3.0-or-later.
HALucinator was initially created by Abraham Clements and Eric Gustafson at Sandia National Laboratories, together with their collaborators and PhD advisors at Purdue University, UC Santa Barbara, and EPFL. The work was published at the 29th USENIX Security Symposium:
HALucinator: Firmware Re-hosting Through Abstraction Layer Emulation. Abraham Clements, Eric Gustafson, Tobias Scharnowski, Paul Grosen, David Fritz, Christopher Kruegel, Giovanni Vigna, Saurabh Bagchi, and Mathias Payer. 29th USENIX Security Symposium (USENIX Security '20), August 2020.
It has since been developed by the Sandia HALucinator team, with later contributions from the GrammaTech HALucinator team and Christopher Wright. The complete contributor list is the project's git history.
Sandia National Laboratories is a multimission laboratory managed and operated by National Technology & Engineering Solutions of Sandia, LLC, a wholly owned subsidiary of Honeywell International Inc., for the U.S. Department of Energy's National Nuclear Security Administration under contract DE-NA0003525.
Copyright 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights in this software.
Metadata
Release files for halucinator 1.9.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| halucinator-1.9.0.tar.gz | 514.6 kB | With provenance | Details for halucinator-1.9.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| halucinator-1.9.0-py3-none-any.whl | Python 3 | none | any | Details for halucinator-1.9.0-py3-none-any.whl |
Total release size: 1.2 MB
Release files / halucinator-1.9.0.tar.gz
| Download URL | halucinator-1.9.0.tar.gz |
|---|---|
| Size | 514.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d3bcbc11d80cdbd3c588c0db13f6419ce03eafeff82bb82356ab924fb9a73050
|
|
BLAKE2b-256 checksum How to use checksums |
3c742ec894047c5901aa17e1eabcf8248d5fd798907e5b7854eefbf8db11aed9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 4, 2026.
Transparency logRelease files / halucinator-1.9.0-py3-none-any.whl
| Download URL | halucinator-1.9.0-py3-none-any.whl |
|---|---|
| Size | 641.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bd3365fe15559d1572ba1e922c9bbb37f7f9e68703f73474d4faa4c3c36fe896
|
|
BLAKE2b-256 checksum How to use checksums |
f0289fae4c1be5a4af2775fe2c6c828a48208c2d2b9e2512fcadd553615c29a9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 4, 2026.
Transparency logSecurity for halucinator 1.9.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for halucinator-1.9.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 4, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.