google / binexport

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

Ghidra: Implement BinExport.java Ghidra script #141

Closed gemesa closed 3 weeks ago

gemesa commented 1 month ago

Overview

I have implemented a Ghidra script to enable scripting as previously .BinExport files could be created only in the UI. The code is mainly a rewrite of BinExportExporter.java with some modifications necessary for Ghidra scripts. I formatted the code using google-java-format:

$ java -jar ~/Downloads/google-java-format-1.24.0-all-deps.jar --replace BinExport.java

Testing

I thoroughly tested the code in both headless mode (its main purpose) and the GUI.

Headless mode

Create a project, import and analyze a binary:

$ ./support/analyzeHeadless /home/gemesa/git-repos/my-projects fidb-rust -import /home/gemesa/git-repos/tmp/rust-lib/rustlib-small/rustc-1.81.0/testlib/1.0.0/x64-debug-build/45c91108d938afe8-absvdi2.o -overwrite

Run BinExport.java which generates the .BinExport file specified in BinExport.properties:

$ cat BinExport.properties
Choose export file Export = test.BinExport
Choose options (IDA Pro Compatibility) OK = "Subtract Imagebase;Remap mnemonics;Prepend Namespace to Function Names"
$ ./support/analyzeHeadless /home/gemesa/git-repos/my-projects fidb-rust -process 45c91108d938afe8-absvdi2.o -propertiesPath /home/gemesa/git-repos/binexport/java/ghidra_scripts -preScript BinExport.java -noanalysis
openjdk version "21.0.4" 2024-07-16 LTS
OpenJDK Runtime Environment Temurin-21.0.4+7 (build 21.0.4+7-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.4+7 (build 21.0.4+7-LTS, mixed mode)
...
INFO  HEADLESS Script Paths:
...
    /home/gemesa/.config/ghidra/ghidra_11.3_DEV/Extensions/BinExport/ghidra_scripts
...
INFO  HEADLESS: execution starts (HeadlessAnalyzer)  
INFO  Opening existing project: /home/gemesa/git-repos/my-projects/fidb-rust (HeadlessAnalyzer)  
INFO  Opening project: /home/gemesa/git-repos/my-projects/fidb-rust (HeadlessProject)  
INFO  REPORT: Processing project file: /45c91108d938afe8-absvdi2.o (HeadlessAnalyzer)  
INFO  Packed database cache: /var/tmp/gemesa-ghidra/packed-db-cache (PackedDatabaseCache)  
INFO  SCRIPT: /home/gemesa/.config/ghidra/ghidra_11.3_DEV/Extensions/BinExport/ghidra_scripts/BinExport.java (HeadlessAnalyzer)  
INFO  Reading script properties file: /home/gemesa/git-repos/binexport/java/ghidra_scripts/BinExport.properties (GhidraScriptProperties)  
INFO  BinExport.java> Binary BinExport (v2) for BinDiff (GhidraScript)  
INFO  BinExport.java> BinExport 12 (c)2019-2024 Google LLC (GhidraScript)  
INFO  BinExport.java> Writing BinExport2 file (GhidraScript)  
INFO  BinExport.java> Export successful (GhidraScript)  
INFO  REPORT: Save succeeded for processed file: /45c91108d938afe8-absvdi2.o (HeadlessAnalyzer)
$ file test.BinExport 
test.BinExport: data

GUI

After installing the plugin the script is available in the Script Manager:

image

When running it, it first asks for the export file name:

image

Then the options can be specified:

image

The console output is the same as when running it in headless mode:

image

Options

Testing if prepending namespaces works:

image

$ binexport2dump std-16341e9decf4fc92.std.58aa595429f4953e-cgu.00.rcgu.o.BinExport | head -n 10 
Original executable name: std-16341e9decf4fc92.std.58aa595429f4953e-cgu.00.rcgu.o
Executable Id:            19c5d70c74fa7c5939acd7f288c0bc4f69121758a0d5d58b659fa0f8ffce3816
Architecture:             x86-64
Creation time (local):    2024-10-16T19:01:16+02:00

Functions:
00100000 n core::ptr::drop_in_place<(std::ffi::os_str::OsString,core::option::Option<std::ffi::os_str::OsString>)>
00100050 n core::ptr::drop_in_place<std::ffi::os_str::OsString>
00100070 n core::ptr::drop_in_place<core::option::Option<std::ffi::os_str::OsString>>
001000A0 n core::ptr::drop_in_place<(std::ffi::os_str::OsString,std::ffi::os_str::OsString)>

Testing if not prepending namespaces works:

image

$ binexport2dump std-16341e9decf4fc92.std.58aa595429f4953e-cgu.00.rcgu.o.BinExport.no-namespace | head -n 10
Original executable name: std-16341e9decf4fc92.std.58aa595429f4953e-cgu.00.rcgu.o
Executable Id:            19c5d70c74fa7c5939acd7f288c0bc4f69121758a0d5d58b659fa0f8ffce3816
Architecture:             x86-64
Creation time (local):    2024-10-16T19:00:52+02:00

Functions:
00100000 n drop_in_place<(std::ffi::os_str::OsString,core::option::Option<std::ffi::os_str::OsString>)>
00100050 n drop_in_place<std::ffi::os_str::OsString>
00100070 n drop_in_place<core::option::Option<std::ffi::os_str::OsString>>
001000A0 n drop_in_place<(std::ffi::os_str::OsString,std::ffi::os_str::OsString)>

References

gemesa commented 3 weeks ago

Thank you for taking the time to review and merge this.