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
153 stars 14 forks source link

Check GHIDRA_INSTALL_DIR on Launcher initialization #33

Closed TheZ3ro closed 5 months ago

TheZ3ro commented 5 months ago

This PR change the place where the GHIDRA_INSTALL_DIR env variable is checked in PyhidraLauncher, checking it at the top of PyhidraLauncher's constructor. Currently the variable is checked inside the start function.

Rationale When in a "bad" state, the program should exit as soon as possible to avoid continuing the execution.

The fact that the environment variable is checked later in the start function allows some weird behavior, specifically the following python "pseudocode" will crash:

import os
from pyhidra import PyhidraLauncher

del os.environ["GHIDRA_INSTALL_DIR"]
p = PyhidraLauncher()
p.add_vmargs('-XX:+PrintFlagsFinal')
p.start()

This is because inside the __init__ constructor, self.vm_args is set to the return value of _jvm_args(), in pyhidra/launcher.py#L134.

The _jvm_args function will return None since the GHIDRA_INSTALL_DIR is empty/not set, in pyhidra/launcher.py#L40.

When self.add_vmargs is called later, it will trigger a TypeError: unsupported operand type(s) for +=: 'NoneType' and 'tuple', in pyhidra/launcher.py#L148.

For example, ghidriff by @clearbluejar is affected ghidriff/ghidra_diff_engine.py#L98-L120

dc3-tsd commented 5 months ago

Thank you for catching this. Indeed the environment variable should be checked before any function uses it, so moving it up the constructor makes sense.

Incidentally, we are work on a slight refactoring such that the ghidra install directory can be configured during construction of the launcher, with GHIDRA_INSTALL_DIR set as the default if not provided. This should make the Launcher class the source of truth for configuration of the Ghidra launch so it will eventually become more like:

def __init__(self, install_dir = None):
    self.install_dir = install_dir or os.getenv("GHIDRA_INSTALL_DIR")