redballoonsecurity / ofrak

OFRAK: unpack, modify, and repack binaries.
https://ofrak.com
Other
1.85k stars 127 forks source link

Example yaml files do not specify disassembler backend for GUI #292

Closed whyitfor closed 1 year ago

whyitfor commented 1 year ago

What is the problem? (Here is where you provide a complete Traceback.) It appears that #168 removed disassembly backends from the OFRAK GUI bundled inside of https://github.com/redballoonsecurity/ofrak/blob/master/ofrak-ghidra.yml and https://github.com/redballoonsecurity/ofrak/blob/master/ofrak-dev.yml

Please provide some information about your environment. When running docker run --rm --detach -it --publish 80:80 redballonsecurity/ofrak/ghidra on a Hello World binary, complex blocks are not discovered when unpacked recursively.

If you've discovered it, what is the root cause of the problem? The root cause is likely that, before #168, Ghidra was a default backend for the OFRAK server. Now, the server does not default to a backend. The entrypoint to the image should be updated to be something like:

python3 -m ofrak gui --backend ghidra -H 0.0.0.0 -p 8877

Other yml files provided in this repository should also be examined, and possibly updated to provide logical backends.

How often does the issue happen?

What are the steps to reproduce the issue? See above.

How would you implement this fix? See above. Each entrypoint that uses an OFRAK server should specify the backend with the --backend argument.

marczalik commented 1 year ago

@whyitfor The fix for this will be a bit more complicated than adding in the --backend ghidra command line argument to the yaml entrypoints. The reason for this is because when we import modules in ofrak_cli, there is a conflict in the Docker images between the module ofrak_ghidra and the top-level directory ofrak_ghidra that leads to the following error:

root@06c4462164f5:/# python3 -m ofrak gui --backend ghidra
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/local/lib/python3.7/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/ofrak_core/ofrak/__main__.py", line 19, in <module>
    main()
  File "/ofrak_core/ofrak/__main__.py", line 15, in main
    ofrak_cli.parse_and_run(sys.argv[1:])
  File "/ofrak_core/ofrak/cli/ofrak_cli.py", line 221, in parse_and_run
    parsed.run(parsed)
  File "/ofrak_core/ofrak/cli/ofrak_cli.py", line 177, in run
    ofrak_pkg = self._import_via_path(ofrak_pkg_name)
  File "/ofrak_core/ofrak/cli/ofrak_cli.py", line 189, in _import_via_path
    raise ImportError(f"Cannot import {path} as it does not appear to be a Python file!")
ImportError: Cannot import ofrak_ghidra as it does not appear to be a Python file!

Unfortunately, simply renaming the top-level directory to remove the name collision isn't enough, because then running commands such as python3 -m ofrak_ghidra.server start do not work since the ofrak_ghidra is not actually installed in the container during building.

The fix I have in mind is to make install the ofrak_ghidra module and then rename the top-level directory to something like ofrak_ghidra_dir. This appears to fix the issues in local testing.

Note, you can also trigger the name collision locally if you try to run python3 ofrak gui --backend <xxx> inside of the disassemblers directory of your repo.

whyitfor commented 1 year ago

I wonder if the logic here (https://github.com/redballoonsecurity/ofrak/blob/master/ofrak_core/ofrak/cli/ofrak_cli.py#L176) should be updated to be something like this:

        for ofrak_pkg_name in ofrak_pkgs:
           try:
                ofrak_pkg = importlib.import_module(ofrak_pkg_name)  
          except whatever the error is:
                ofrak_pkg = self._import_via_path(ofrak_pkg_name)
            ofrak.discover(ofrak_pkg)

@EdwardLarson, this should work, right?