google / binexport

Export disassemblies into Protocol Buffers
Apache License 2.0
1.05k stars 206 forks source link

IllegalAccessError when running in Docker Container #137

Open spatti33 opened 2 months ago

spatti33 commented 2 months ago

I am running ghidra in a docker container so I can use the headless analyzer in a pipeline. I have installed the binexport extension in ghidra and am running a custom post script with the headless analyzer to export the file as a .BinExport file. I developed this on my host machine (Ubuntu 22.04 with jdk 21) where it worked perfectly and made the docker container with the same dependencies and OS version.

However, when I run this on the docker container, the analysis succeeds but it is unable to export the .BinExport file and I get the following error:

java.lang.IllegalAccessError: java.lang.IllegalAccessError: class com.google.security.zynamics.BinExport$BinExport2 tried to access method 'com.google.protobuf.LazyStringArrayList and com.google.protobuf.LazyStringArrayList.emptyList()' (com.google.security.zynamics.BinExport$BinExport2 and com.google.protobuf.LazyStringArrayList are in unnamed module of loader ghidra.GhidraClassLoader @6073f712)

I cannot find what is causing this issue or why it is only an issue when I run this workflow in the docker container. Any insight or suggestions would be appreciated!

cblichmann commented 2 months ago

Care to share your Dockerfile and your command-line?

I have never actually tried this out myself and neither have I tried Ghidra's headless mode with BinExport.

spatti33 commented 2 months ago

Dockerfile:

FROM ubuntu:22.04.2

ARG DEBIAN_FRONTEND=noninteractive

RUN apt -y update && apt -y upgrade
RUN apt -y -qq install python3 python3-pip build-essential tshark zip vim nano pkg-config python3-dev openjdk-21-jdk

COPY ./ghidra /ghidra
COPY ./.ghidra /home/user/.ghidra

RUN pip3 install --no-cache-dir --upgrade pip
RUN pip3 install --no-cache-dir python_bindiff-0.2.3-py3-none-any.whl python_binexport-0.3.5-py3-none-any.whl

Command line:

/ghidra/support/analyzeHeadless /home/user/project MyProject -import /home/user/project/program1 -processor "x86:LE:64:default" -cspec gcc -loader ElfLoader -scriptPath /home/user/project -postScript export_script.py -deleteProject

Export Script:

from com.google.security.binexport import BinExportExporter
from java.io import File

exporter = BinExportExporter()
exporter.export(File(currentProgram.getName() + ".BinExport"), currentProgram, currentProgram.getMemory(), monitor)
cblichmann commented 2 months ago

Thanks. Maybe try with a less recent JDK version? I think Ghidra is still on JDK 17.

Other than that, I don't see anthing out of the ordinary in your Dockerfile.

spatti33 commented 2 months ago

I tried with 17 through to 21 and same result, thanks for looking though!

spatti33 commented 1 month ago

I was able to avoid the illegal access error but now I get an import error that there is no module named security

cblichmann commented 1 month ago

Can you please post the full error log?

spatti33 commented 1 month ago
Traceback (most recent call last):
     File "/home/user/auto/export_script.py", line 1, in <module>
          from com.google.security.binexport import BinExportExporter
ImportError: No module named security
spatti33 commented 1 month ago
Traceback (most recent call last):
     File "/home/user/auto/export_script.py", line 1, in <module>
          from com.google.security.binexport import BinExportExporter
ImportError: No module named security

Additionally:

Traceback (most recent call last):
      File "/home/user/auto/export_script.py", line 1, in <module>
          exporter.export(File(currentProgram.getName() + ".BinExport"), currentProgram, currentProgram.getMemory(), monitor)
TypeError: export(): self arg cant be coerced to com.google.security.binexport.BinExportExporter, ghidra.app.util.exporter.Exporter
spatti33 commented 1 month ago

I figured it out. For anyone looking to generate .BinExport files in a gitlab/github pipeline (or any other automated fashion) using headless ghidra:

Ghidra documentation claims that you can install extensions by unzipping them in a specified directory and that they will work with the headless version. However, it looks like when you install them using the GUI, ghidra calls some internal methods to configure the extensions. In the headless version, the methods are NULL so some extensions fail to get configured properly which is what resulted in these errors. Thus, if you install the extensions through the GUI using a VNC connection and save the state of the container, the extensions will be configured properly and you can now use them correctly in headless mode as well.

mkg880 commented 1 month ago

I also ran into this issue and I found a simpler solution. When you install extensions through the Ghidra GUI, they end up in the Ghidra config directory. The way I worked around this issue was to find that directory (in my system it's at /root/.config/ghidra/ghidra<VERSION>) and unzip the extension there instead. It will automatically add ".uninstalled" to the name of some files, so I changed the names of the files back, and it seems to work.