{"id":13792614,"url":"https://github.com/embedded-sec/halucinator","last_synced_at":"2025-05-12T14:31:56.681Z","repository":{"id":54356000,"uuid":"190417678","full_name":"embedded-sec/halucinator","owner":"embedded-sec","description":null,"archived":false,"fork":false,"pushed_at":"2021-10-06T12:03:54.000Z","size":1585,"stargazers_count":159,"open_issues_count":4,"forks_count":25,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-18T06:49:27.066Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/embedded-sec.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-06-05T15:10:41.000Z","updated_at":"2024-11-18T06:42:25.000Z","dependencies_parsed_at":"2022-08-13T13:10:41.790Z","dependency_job_id":null,"html_url":"https://github.com/embedded-sec/halucinator","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/embedded-sec%2Fhalucinator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/embedded-sec%2Fhalucinator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/embedded-sec%2Fhalucinator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/embedded-sec%2Fhalucinator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/embedded-sec","download_url":"https://codeload.github.com/embedded-sec/halucinator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253754967,"owners_count":21958934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T22:01:14.307Z","updated_at":"2025-05-12T14:31:56.041Z","avatar_url":"https://github.com/embedded-sec.png","language":"Python","funding_links":[],"categories":["Resources","Software Tools","Firmware Security"],"sub_categories":["By Purpose","Emulation Tools","Dynamic Analysis and Emulation"],"readme":"# HALucinator - Firmware rehosting through abstraction layer modeling.\n\nNOTE: For a more recent version of HALucinator see https://github.com/halucinator\n\n## Setup\n\nNote:  This has been lightly tested on Ubuntu 16.04, and 18.04\n\n1.  Install dependencies using `./install_deps.sh`\n\n1.  Create and activate a python3 virtual environment (I use virtualmachine \n    wrapper but you can do this however you like)\n    ```\n       mkvirtualenv -p `which python3` halucinator\n    ```\n    If (halucinator) is not in your prompt use `workon halucinator`\n\n    Note: On ubuntu 18.04 you may have to manually configure virtualenvwrapper. Or build you virtual environment using you preferred method\n    ```bash\n        pip3 install virtualenvwrapper\n    ```\n    Then add to `~/.bashrc` using your favorite editor and then run\n    `source ~/.bashrc`.  Replace `your username` in below\n    \n    ```bash\n    export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3\n    export WORKON_HOME=$HOME/.virtualenvs\n    export VIRTUALENVWRAPPER_VIRTUALENV=/home/\u003cyour username\u003e/.local/bin/virtualenv\n    source ~/.local/bin/virtualenvwrapper.sh\n    ```\n\n1.  Install Halucinator \n    Make sure you are in you virtual environment and then run\n    ```\n    pip install -r src/requirements.txt\n    pip install -e src\n    ```\n1. Install Avatar's QEMU and GDB (Select avatar-qemu and gdb-arm)\n   ```\n   python -m avatar2.installer\n   ```\n   This step will take a while the first time, and you may have to make your terminal wider\n\n1. Set environmental variable for HALUCINATOR_QEMU\n  ```\n    export HALUCINATOR_QEMU=`readlink -f ~/.avatar2/avatar-qemu/arm-softmmu/qemu-system-arm`\n  ```\n\n1.  Simlink gdb-multiarch to arm-none-eabi-gdb\n    If you don't have arm-none-eabi-gdb on your path you can apt get it on Ubuntu 16.04.  On Ubuntu 18.04 you can use gdb-multiarch\n    which was installed in step 1.  Just symlink it to `arm-none-eabi-gdb`\n\n    ```bash\n    sudo ln /usr/bin/gdb-multiarch /usr/bin/arm-none-eabi-gdb\n    ```\n    \n### Note on setting HALUCINATOR_QEMU\n\nIf you use virtualenvwrapper as above you \ncan set it up to be automatically set and removed when activating/deactivating\nthe virtual environment using the postactivate and predeactivate scripts below.\n  \nContents of $VIRTUAL_ENV/bin/postactivate\n\n```sh\nexport HALUCINATOR_QEMU=\u003cfull path to your qemu\u003e\n```\n\nContents of $VIRTUAL_ENV/bin/predeactivate\n\n```sh\nunset HALUCINATOR_QEMU\n```\n\n## Running\n\nRunning Halucinator requires a configuration file that lists the functions to \nintercept and the handler to be called on that interception. I usually split \nthis config across three files for portability.  The files are a memory file that\ndescribes the memory layout, an intercept file that describes what to intercept\nand a symbol/address file that maps addresses to symbol names.  See the Config \nFile section below for full details\n\nAll of these commands assume you are in your halucinator virtual environment\n\n```sh\nhalucinator  -c=\u003cmemory_file.yaml\u003e -c=\u003cintercept_file.yaml\u003e -c=\u003caddress_file.yaml\u003e\n```\n\n## Running an Example\n\n### Building STM MX Cube Examples\n\nThis has already been done for Uart example file below.\n\nA tool to convert the STM's Software Workbench for STM (SW4STM) was developed to\nenable compiling their IDE projects using make.\nThis has only been tested on a few STM32F4 examples from STM32Cube_F4_V1.21.0.\nIt compiles them as cortex-m3 devices and not cortex-m4 to enable easier \nemulation in QEMU. \n\nTo use go into the directory below the SW4STM32 directory in the project and run\n`python3 \u003chalucinator_repo_root\u003e/src/tools/stm_tools/build_scripts/CubeMX2Makefile.py .`\nEnter a name for the board, and the applications. Then run `make all`.\nThe binary created will be in `bin` directory\n\nExample\n\n```bash\ncd STM32Cube_FW_F4_V1.21.0/Projects/STM32469I_EVAL/Examples/UART/UART_HyperTerminal_IT/SW4STM32/STM32469I_EVAL\npython3 \u003chalucinator_repo_root\u003e/src/tools/stm_tools/build_scripts/CubeMX2Makefile.py .\nBoard: STM32469I_Eval\nAPP: Uart_IT\nmake all\n```\n\n\n###  STM32F469I Uart Example\n\nTo give an idea how to use Halucinator an example is provided in `test/STM32/example`.\n\n#### Setup\nNote: This was done prior and the files are in the repo in `test/STM/example`. \nIf you just want to run the example without building it just go to Running UART Example below.\n\nThis procedure should be followed for other binaries.\nIn list below after the colon (:) denotes the file/cmd .  \n\n1. Compile binary as above\n2. Copy binary to a dir of you choice and cd to it:  `test/STM32/example`\n3. Create binary file: `\u003chalucinator_repo_root\u003e/src/tools/make_bin.sh Uart_Hyperterminal_IT_O0.elf` creates `Uart_Hyperterminal_IT_O0.elf.bin`\n4. Create Memory Layout (specifies memory map of chip): `Uart_Hyperterminal_IT_O0_memory.yaml`\n5. Create Address File (maps function names to address): `Uart_Hyperterminal_IT_O0_addrs.yaml`\n6. Create Intercept File (defines functions to intercept and what handler to use for it): `Uart_Hyperterminal_IT_O0_config.yaml`\n7. (Optional) create shell script to run it: `run.sh`\n\nNote: Symbols used in the address file can be created from an elf file with symbols\nusing `hal_make_addrs` This requires installing angr in halucinator's virtual environment.\nThis was used to create `Uart_Hyperterminal_IT_O0_addrs.yaml`\n\nTo use it the first time you would. Install angr (e.g. `pip install angr` from\nthe halucinator virtual environment)\n\n```sh\nhal_make_addrs -b \u003cpath to elf file\u003e\n```\n\n#### Running UART Example\n\nStart the UART Peripheral device,  this a script that will subscribe to the Uart \non the peripheral server and enable interacting with it.\n\n```bash\nhal_dev_uart -i=1073811456\n```\n\nIn separate terminal start halucinator with the firmware.\n\n```bash\n\n\u003chalucinator_repo_root\u003e$ halucinator -c=test/STM32/example/Uart_Hyperterminal_IT_O0_config.yaml \\\n  -c=test/STM32/example/Uart_Hyperterminal_IT_O0_addrs.yaml \\\n  -c=test/STM32/example/Uart_Hyperterminal_IT_O0_memory.yaml --log_blocks -n Uart_Example\n\nor\n\u003chalucinator_repo_root\u003e\u0026 test/STM32/example/run.sh\n```\nNote the --log_blocks and -n are optional.\n\nYou will eventually see in both terminals messages containing\n```\n ****UART-Hyperterminal communication based on IT ****\n Enter 10 characters using keyboard :\n```\n\nEnter 10 Characters in the first terminal running `hal_dev_uart` press enter\nshould then see text echoed followed.\n\n```txt\n Example Finished\n```\n\n#### Stopping\n\nPress `ctrl-c`. If for some reason this doesn't work kill it with `ctrl-z` \nand `kill %`, or `killall -9 halucinator`\n\nLogs are kept in the `tmp/\u003cvalue of -n option\u003e`. e.g `tmp/Uart_Example/`\n\n## Config file\n\nHow the emulation is performed is controlled by a yaml config file.  It is passed \nin using the -c flag, which can be repeated with the config files being appended\nand the later files overwriting any collisions from previous file.  The config \nis specified as follows.  Default field values are in () and types are in \u003c\u003e\n\n```yaml\nmachine:   # Optional, describes qemu machine used in avatar entry optional defaults in ()\n           # if never specified default settings as below are used. \n  arch: (cortex-m3)\u003cstr\u003e,\n  cpu_model: (cortex-m3)\u003cstr\u003e,\n  entry_addr: (None)\u003cint\u003e,  # Initial value to pc reg. Obtained from 0x0000_0004\n                        # of memory named init_mem if it exists else memory\n                        # named flash\n  init_sp: (None)\u003cint\u003e,     # Initial value for sp reg, Obtained from 0x0000_0000\n                        # of memory named init_mem if it exists else memory\n                        # named flash\n  gdb_exe: ('arm-none-eabi-gdb')\u003cpath\u003e # Path to gdb to use\n\n\nmemories:  #List of the memories to add to the machine\n  - name: \u003cstr\u003e,       # Required\n    base_addr:  \u003cint\u003e, # Required\n    size: \u003cint\u003e,       # Required\n    perimissions: (rwx)\u003cr--|rw-|r-x\u003e, # Optional \n    file: filename\u003cpath\u003e   # Optional Filename to populate memory with, use full path or\n                      # path relative to this config file, blank memory used if not specified\n    emulate: class\u003cAvatarPeripheral subclass\u003e    # Class to emulate memory \n\nperipherals:  # Optional, A list of memories, same as memories except emulate field required\n\nintercepts:  # Optional, list of intercepts to place\n  - class:  \u003cBPHandler subclass\u003e,  # Required use full import path\n    function: \u003cstr\u003e     # Required: Function name in @bp_handler([]) used to\n                        #   determine class method used to handle this intercept\n    symbol: (Value of function)\u003cstr\u003e  # Optional, Symbol name use to determine \n                                      # address in firmware to intercept, name \n                                      # must be present in symbols,\n                                      # If not use value of function is used\n    addr: (from symbols)\u003cint\u003e  # Optional, Address of where to place this intercept,\n                               # generally recommend not setting this value, but\n                               # instead setting symbol and adding entry to\n                               # symbols (in seperate file) as this makes config \n                               # files more portable. If set will take precidence over symbol\n    class_args: ({})\u003cdict\u003e  # Optional dictionary of args to pass to class's\n                       # __init__ method, keys are parameter names\n    registration_args: ({})\u003cdict\u003e  # Optional: Arguments passed to register_handler\n                                   # method when adding this method\n    run_once: (false)\u003cbool\u003e   # Optional: Set to true if only want intercept to run once\n    watchpoint: (false)\u003cbool\u003e # Optional: Set to true if this is a memory watch point\n\nsymbols:  # Optional, dictionary mapping addresses to symbol names, used to\n          # determine addresses for symbol values in intercepts\n  addr0\u003cint\u003e: symbol_name\u003cstr\u003e\n  addr1\u003cint\u003e: symbol1_name\u003cstr\u003e\n\noptions: # Optional, Key:Value pairs you want accessible during emulation\n\n```\n\nThe symbols in the config can also be specified using one or more symbols files\npassed in using -s. This is a csv file each line defining a symbol as shown below\n\n```csv\nsymbol_name\u003cstr\u003e, start_addr\u003cint\u003e, last_addr\u003cint\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fembedded-sec%2Fhalucinator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fembedded-sec%2Fhalucinator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fembedded-sec%2Fhalucinator/lists"}