joernio / joern

Open-source code analysis platform for C/C++/Java/Binary/Javascript/Python/Kotlin based on code property graphs. Discord https://discord.gg/vv4MH284Hc
https://joern.io/
Apache License 2.0
2.12k stars 291 forks source link

ghidra headless invoking UI #2146

Open irwincong opened 1 year ago

irwincong commented 1 year ago

Ghidra 10.1.1 fixes an issue where ghidra headless was incorrectly using java UI elements. Joern's ghidra2cpg is a singlejar build based on 10.1_PUBLIC_20211210a.

An example of this failure happening with joern is as follows:

[root@edd2b76e380e joern]# ./joern-cli/target/universal/stage/ghidra2cpg /workspaces/joern/Stackoverflow_App.debug -o ./Stackoverflow_App.cpg
...
Loading block _elfSectionHeaders at OTHER:00000000 from file offset 273792
Could not initialize class sun.font.SunFontManager
java.lang.NoClassDefFoundError: Could not initialize class sun.font.SunFontManager
        at java.desktop/sun.font.FontDesignMetrics.getMetrics(FontDesignMetrics.java:265)
        at java.desktop/sun.swing.SwingUtilities2.getFontMetrics(SwingUtilities2.java:1231)
        at java.desktop/javax.swing.JComponent.getFontMetrics(JComponent.java:1646)
...
        at java.desktop/javax.swing.JComboBox.addItem(JComboBox.java:716)
        at ghidra.framework.options.PropertySelector.<init>(PropertySelector.java:43)
        at ghidra.app.plugin.core.analysis.GnuDemanglerAnalyzer$FormatSelector.<init>(GnuDemanglerAnalyzer.java:184)
        at ghidra.app.plugin.core.analysis.GnuDemanglerAnalyzer$FormatEditor.<init>(GnuDemanglerAnalyzer.java:131)
        at ghidra.app.plugin.core.analysis.GnuDemanglerAnalyzer.registerOptions(GnuDemanglerAnalyzer.java:80)
        at ghidra.app.plugin.core.analysis.AnalysisScheduler.registerOptions(AnalysisScheduler.java:139)
        at ghidra.app.plugin.core.analysis.AnalysisTaskList.registerOptions(AnalysisTaskList.java:131)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.registerOptions(AutoAnalysisManager.java:1077)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.registerOptions(AutoAnalysisManager.java:1050)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.initializeAnalyzers(AutoAnalysisManager.java:192)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.<init>(AutoAnalysisManager.java:147)
        at ghidra.app.plugin.core.analysis.AutoAnalysisManager.getAnalysisManager(AutoAnalysisManager.java:983)
        at io.joern.ghidra2cpg.Ghidra2Cpg.$anonfun$createCpg$2(Ghidra2Cpg.scala:61)
        at io.joern.ghidra2cpg.Ghidra2Cpg.$anonfun$createCpg$2$adapted(Ghidra2Cpg.scala:45)
...
        at scala.App.main(App.scala:76)
        at scala.App.main$(App.scala:74)
        at io.joern.x2cpg.X2CpgMain.main(X2Cpg.scala:36)
        at io.joern.ghidra2cpg.Main.main(Main.scala)

Two questions:

  1. Assuming no compatibility breaking changes between ghidra 10.1.1 (or 10.2.2) and 10.1, what's the right way to update the build.sbt file to reference a locally built ghidra.jar file?
  2. Can the maven repository and joern's ghidra2cpg be updated to 10.1.1 or newer?
irwincong commented 1 year ago

Assuming no compatibility breaking changes between ghidra 10.1.1 (or 10.2.2) and 10.1, what's the right way to update the build.sbt file to reference a locally built ghidra.jar file?

I would need to create a lib directory and add the single ghidra jar build to it.

After doing so, I would need to reference this unmanaged jar in the build.sbt. See https://www.scala-sbt.org/1.x/docs/Library-Management.html#Manual+Dependency+Management

irwincong commented 1 year ago

Here's what I needed to do to get ghidra2cpg with the following ./devcontainer/Dockerfile, which is different from the production one. Some notes on this:

  1. ghidra 10.2.2 requires java 17+, so updated to graalvm with java17. see https://github.com/graalvm/graalvm-ce-builds/releases
  2. I separately built the ghidra jar file in the docker image using the support/buildGhidraJar script (to ensure jvm classfile version compatibility). Copied the resulting ghidra.jar to./joern-cli/frontends/ghidra2cpg/lib/ghidra.jar
  3. Updated ./joern-cli/frontends/ghidra2cpg/build.sbt
# .devcontainer/Dockerfile
FROM almalinux:9.1-20221201

# install git git-lfs
RUN yum -y --allowerasing install zlib zlib-devel curl perl-ExtUtils-CBuilder perl-ExtUtils-MakeMaker gcc curl-devel expect make wget gettext zip unzip \
    && yum -y remove git \
    && yum -y install git

# install jdk11 sbt
ENV SBT_VERSION 1.8.0
ENV SBT_HOME /usr/local/sbt
ENV PATH ${PATH}:${SBT_HOME}/bin
RUN curl -sL "https://github.com/sbt/sbt/releases/download/v$SBT_VERSION/sbt-$SBT_VERSION.tgz" | tar -zx -C /usr/local \
    && curl -Ls "https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.3.0/graalvm-ce-java17-linux-amd64-22.3.0.tar.gz" | tar -zx -C /usr/local

ENV LANG=en_US.UTF-8
ENV JAVA_HOME=/usr/local/graalvm-ce-java17-22.3.0
ENV PATH=${JAVA_HOME}/bin:${PATH}
diff --git a/joern-cli/frontends/ghidra2cpg/build.sbt b/joern-cli/frontends/ghidra2cpg/build.sbt
index 70981444..3e302915 100644
--- a/joern-cli/frontends/ghidra2cpg/build.sbt
+++ b/joern-cli/frontends/ghidra2cpg/build.sbt
@@ -2,10 +2,12 @@ name := "ghidra2cpg"

 dependsOn(Projects.dataflowengineoss, Projects.x2cpg % "compile->compile;test->test")

+unmanagedBase := baseDirectory.value / "lib"
+
 libraryDependencies ++= Seq(
   "com.github.scopt" %% "scopt"                    % "4.1.0",
   "commons-io"        % "commons-io"               % "2.11.0",
-  "io.shiftleft"      % "ghidra"                   % "10.1_PUBLIC_20211210a",
+//  "io.shiftleft"      % "ghidra"                   % "10.1_PUBLIC_20211210a",
   "io.shiftleft"     %% "codepropertygraph"        % Versions.cpg,
   "io.shiftleft"     %% "codepropertygraph-protos" % Versions.cpg,
   "org.scalatest"    %% "scalatest"                % Versions.scalatest % Test
image
irwincong commented 1 year ago

@mpollmeier or @itsacoderepo https://github.com/joernio/joern/pull/2422 and https://github.com/joernio/joern/pull/2484 probably fixes this issue, right?

mpollmeier commented 1 year ago

yes, since we upgraded ghidra to 10.2.3 it should be fixed - would be great if you could re-test to double check!

irwincong commented 1 year ago

yes, since we upgraded ghidra to 10.2.3 it should be fixed - would be great if you could re-test to double check!

Built docker container to run joern from c793f62f31a77c14aeb14a97a7a3401adb1ec0ee.

/joern # ./joern
Compiling /joern/(console)
creating workspace directory: /joern/workspace

     ██╗ ██████╗ ███████╗██████╗ ███╗   ██╗
     ██║██╔═══██╗██╔════╝██╔══██╗████╗  ██║
     ██║██║   ██║█████╗  ██████╔╝██╔██╗ ██║
██   ██║██║   ██║██╔══╝  ██╔══██╗██║╚██╗██║
╚█████╔╝╚██████╔╝███████╗██║  ██║██║ ╚████║
 ╚════╝  ╚═════╝ ╚══════╝╚═╝  ╚═╝╚═╝  ╚═══╝
Version: 1.1.1650
Type `help` or `browse(help)` to begin

joern> importCode("/bin/ls", language="ghidra");
io.joern.console.ConsoleException: No CPG generator exists for language: ghidra

joern> importCode
res0: cpgcreation.ImportCode[io.joern.joerncli.console.JoernProject] = Type `importCode.<language>` to run a specific language frontend

_________________________________________________________________________________
| name       | description                                            | available|
|================================================================================|
| c          | Eclipse CDT Based Frontend for C/C++                   | true     |
| cpp        | Eclipse CDT Based Frontend for C/C++                   | true     |
| ghidra     | ghidra reverse engineering frontend                    | true     |
| kotlin     | Kotlin Source Frontend                                 | true     |
| java       | Java Source Frontend                                   | true     |
| jvm        | Java/Dalvik Bytecode Frontend (based on SOOT's jimple) | true     |
| javascript | Javascript Source Frontend                             | true     |
| golang     | Golang Source Frontend                                 | false    |
| llvm       | LLVM Bitcode Frontend                                  | false    |
| php        | PHP bytecode frontend                                  | true     |
| python     | Python Source Frontend                                 | true     |
| csharp     | C# Source Frontend (Roslyn)                            | false    |

Attached error output for /joern/joern-cli/target/universal/stage/frontends/ghidra2cpg/bin/ghidra2cpg /bin/ls -o ls.cpg ghidra2cpg.log

joern> importCpg("./ls.cpg")
Creating project `ls.cpg` for CPG at `./ls.cpg`
Creating working copy of CPG to be safe
Loading base CPG from: /joern/workspace/ls.cpg/cpg.bin.tmp
res0: Option[Cpg] = Some(value = Cpg (Graph [0 nodes]))