dod-cyber-crime-center / pyhidra

Pyhidra is a Python library that provides direct access to the Ghidra API within a native CPython interpreter using jpype.
Other
184 stars 16 forks source link

open_program() fails if Ghidra is unable to determine Loader #37

Closed jason-at-cyberdelia closed 1 month ago

jason-at-cyberdelia commented 7 months ago

Problem

If Ghidra is unable to automatically determine the loader for a program, pyhidra.open_program() will fail.

This is because pyhidra's call to GhidraProject.importProgram() does not support allowing the user to optionally specify a Loader. Reference: https://github.com/dod-cyber-crime-center/pyhidra/blob/edbdd64c4e97333183b245143a7f97b4760b8fe9/pyhidra/core.py#L95

Example

Pick a random bare-metal raw firmware image and attempt to load it. Ie, an ARM baseband image for Shannon.

INFO  Opening project: /home/user/firmware.bin_ghidra/firmware.bin_ghidra (DefaultProject)  
INFO  Starting cache cleanup: /tmp/user-Ghidra/fscache2 (FileCacheMaintenanceDaemon)  
INFO  Finished cache cleanup, estimated storage used: 0 (FileCacheMaintenanceDaemon)  
INFO  No load spec found for import file: /home/user/firmware.bin (AutoImporter)  
Traceback (most recent call last):
  File "GhidraProject.java", line 653, in ghidra.base.project.GhidraProject.importProgram
Exception: Java Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/user/ghidra_scripts/test.py", line 15, in <module>
    with pyhidra.open_program("/home/user/firmware.bin") as flat_api:
  File "/usr/lib/python3.10/contextlib.py", line 135, in __enter__
    return next(self.gen)
  File "/home/user/.local/lib/python3.10/site-packages/pyhidra/core.py", line 187, in open_program
    project, program = _setup_project(
  File "/home/user/.local/lib/python3.10/site-packages/pyhidra/core.py", line 95, in _setup_project
    program = project.importProgram(binary_path)
ghidra.app.util.opinion.ghidra.app.util.opinion.LoadException: ghidra.app.util.opinion.LoadException: No load spec found

By supplying the 'language' param, a workaround for this can be explored to avoid the error if a default loader is available. However, if a custom Loader has been developed and is needed to properly load the firmware, then there is still no way to ensure that the custom loader is used instead of the default.

Again with the Shannon baseband example, if this loader is required to property setup the memory layout, there is no way to ensure that it executes.

Solution

Add an optional parameter to load_program() so that the user can specify a Loader. If the Loader param is provided, then instead of calling the current importProgram() method, call the alternative version that specifies the Loader (as documented here, or if the language and compiler are provided, here).

dc3-tsd commented 7 months ago

Thanks for letting us know about this. This should be fixed in the 1.1.0 release. If this doesn't fix it please let us know.