- Integrated environment for software reverse engineering (IDE for SRE)
- Developed by NSA Research
- Written almost entirely in Java
- Some native code (C/C++)
- ELF
- PE
- Mach-O
- COFF
- PDB
- Raw binaries
- etc
- Multiple users work together on the same program(s)
- Network storage for the shared project
- Controls user access
- Allows files to be versioned (à la primitive Git)
- Others features
- Designed to handle large data sets (not large binaries!)
- Supports collaboration
- Highly configurable environment
- Highly extensible via plugins and scripts
- Multi-platform (Linux, Mac, Windows, FreeBSD, Haiku, etc)
Not to my taste, but…
- GhidraDev plugin (extensions and scripts developing)
- GhidraSleighEditor plugin (Sleigh linter)
- Emacs (Eclipse backend)?
- VIM (Eclipse backend)?
- IntelliJ IDEA (Community Edition) ✓
- Use default
SkeletonprojectCopy
Skeleton’s directory (or yours prepared extension) to needed location
- Create the project
File→New→Project from Existing Sources...(use Gradle model)- Choose the directory
- Set
gradle’s environment (GHIDRA_INSTALL_DIR)- Set in Run/Debug Configurations (Gradle)
- Create
gradle.propertiesfile and set the environment:GHIDRA_INSTALL_DIR = /home/user/ghidra
Point to the directory of sources of Ghidra, when it will be needed
- Create or use existing the
ghidra_scriptsdirectory - Use existing
HelloWorldScriptscript as a template${GHIDRA_HOME}/Ghidra/Features/Base/ghidra_scripts/HelloWorldScript.java
- Import the directory as Existing Sources without models
- Add Ghidra as module to the project:
- Wait while IntelliJ IDEA indexes Ghidra’s files
- Add module dependencies via Context Actions
- Also you can add templates/snippets for scripts
- Run Ghidra in Debug mode
$ /opt/ghidra/support/ghidraDebug - Attach to Process…
- Debug a script/plugin
- Use a recompiling for testing
- Clone the repository
$ git clone https://github.com/NationalSecurityAgency/ghidra - Build Ghidra (see
DevGuide.mdfor details)$ gradle --init-script gradle/support/fetchDependencies.gradle init $ gradle buildGhidra
- Create the project from Existing Sources (Gradle model)
- For testing of patches or new features you can use features of IntelliJ IDEA
or Linux tools (
sed,inotify,(bsd)tar, etc)
Skip Gradle’s tasks for faster building (use -x argument):
createJavadocscreateJsondocssleighCompile- etc
Every piece (Plugins, Scripts, Analyzers, Fields, Importers, Exporters, etc) of Ghidra is extensible!
Extensible components:
ExtensionPointinterface- List suffix in
ExtensionPoint.manifest
./src ├── main │ ├── help │ │ └── help │ │ ├── shared │ │ │ └── Frontpage.css │ │ ├── topics │ │ │ └── skeleton │ │ │ └── help.html │ │ └── TOC_Source.xml │ ├── java │ │ └── skeleton │ │ ├── SkeletonAnalyzer.java │ │ ├── SkeletonExporter.java │ │ ├── SkeletonFileSystem.java │ │ ├── SkeletonLoader.java │ │ └── SkeletonPlugin.java │ └── resources │ └── images └── test └── java
./src/main ├── java │ └── skeleton │ ├── SkeletonAnalyzer.java │ ├── SkeletonExporter.java │ ├── SkeletonFileSystem.java │ ├── SkeletonLoader.java │ └── SkeletonPlugin.java └── resources └── images
- Packaged into a
.jarfile - Hold the Java/Clojure/Kotlin/JVM-based source for this extension
./src/test └── java
- Unit tests are not included in the
.jarfile
./src/main/help └── help ├── shared │ └── Frontpage.css ├── topics │ └── skeleton │ └── help.html └── TOC_Source.xml
- Online help for this extension
- Contains the table of contents to append
- Contains the CSS and HTML components
./ghidra_scripts
- Holds scripts for this extension
- Unpacked as source to the file system on installation
- May provide examples to use an extension’s API
./data ├── languages │ ├── skel.cspec │ ├── skel.ldefs │ ├── skel.opinion │ ├── skel.pspec │ ├── skel.sinc │ └── skel.slaspec ├── buildLanguage.xml └── sleighArgs.txt
- Holds data files for this extension
- Will not end up inside the
.jarfile - Will be present in the distribution
.zipfile - Unpacked to the file system on installation
./lib
- Holds external Java dependencies for this extension
- When working in IntelliJ IDEA, the contents of this directory should be added by Gradle’s task
./os ├── linux64 ├── osx64 └── win64
- Holds native components for this extension
- NEVER EVER USE JNI! Communicate with a native process using sockets, I/O, stream, etc
. ├── build.gradle ├── extension.properties └── Module.manifest
build.gradle
Gradle’s task. No need for changes
extension.properties
name=@extname@ description=The extension description. author= createdOn= version=@extversion@
Module.manifest
MODULE NAME: MODULE DEPENDENCY: MODULE FILE LICENSE: EXCLUDE FROM GHIDRA JAR DATA SEARCH IGNORE DIR: MODULE DIR: FAT JAR:
$ gradleor
$ GHIDRA_INSTALL_DIR=${GHIDRA_HOME} gradleSee ./dist/
- Object-Oriented
- Very deep
ProgramListingInstructionsDataFunctionsBasic Blocks
Comments
MemoryMemory BlocksBytes
Symbol TablesSymbols
- etc
- Can change from version to version
- Flat
- Provides access to most common features
- Is not complete
- Will not change (legacy)
public class FlatProgramAPI {
FlatProgramAPI(Program)
analyze()
clear...()
create...()
find...()
get...()
remove...()
save()
set...()
to...()
}Default:
${HOME}/ghidra_scripts${GHIDRA_HOME}/Features/Base/ghidra_scripts${GHIDRA_MODULE}/ghidra_scripts
public class GhidraScriptAPI extends FlatProgramAPI {
ask...()
create...()
get...()
print...()
run...()
to...()
}//Writes "Hello World" to console.
//@category Examples
//@menupath Help.Examples.Hello World
//@keybinding ctrl shift COMMA
//@toolbar world.png
import ghidra.app.script.GhidraScript;
public class HelloWorldScript extends GhidraScript {
@Override
public void run() throws Exception {
println("Hello World");
}
}The current active open program
The current address of the location of the cursor
The program location of the cursor
OperandFieldLocation@00400260, row=0, col=0, charOffset=8, OpRep = 47h G,
subOpIndex = -1, VariableOffset = nullThe current selection or null if no selection exists
The current highlight or null if no highlight exists
Provides place to store environment variables
- Allows script writer to inform user (messages and/or progress)
- Allows user to cancel script
- Always use inside loops
while (!monitor.isCancelled()) {
...
}Dynamic modules with OSGi
- Intra-bundle (compile time) dependency
my_ghidra_scripts/mylib/MyLibrary.java:
package mylib;
public class MyLibrary {
public void doStuff() {
// ...
}
}my_ghidra_scripts/IntraBundleExampleScript.java:
// Intra-bundle dependency example.
//@category Examples
import ghidra.app.script.GhidraScript;
import mylib.MyLibrary;- Inter-bundle (run time) dependency
@importpackage in a script
your_ghidra_scripts/yourlib/YourLibrary.java:
package yourlib;
public class YourLibrary {
public void doOtherStuff() {
// ...
}
}my_ghidra_scripts/InterBundleExampleScript.java:
// Inter-bundle dependency example.
//@category Examples
//@importpackage yourlib
import ghidra.app.script.GhidraScript;
import yourlib.YourLibrary;
public class InterBundleExampleScript extends GhidraScript {
@Override
public void run() throws Exception {
new YourLibrary().doOtherStuff();
}
}$HOME/.ghidra/.ghidra-<version>/osgi/compiled-bundles/<hash>
- Ghidra can be run from the command line without invoking the user interface
- Can be run on one or more programs
- Any script that does not invoke the GUI can be run in headless mode
Usage: analyzeHeadless
<project_location> <project_name>[/<folder_path>]
| ghidra://<server>[:<port>]/<repository_name>[/<folder_path>]
[[-import [<directory>|<file>]+] | [-process [<project_file>]]]
[-preScript <ScriptName>]
[-postScript <ScriptName>]
[-scriptPath "<path1>[;<path2>...]"]
[-propertiesPath "<path1>[;<path2>...]"]
[-scriptlog <path to script log file>]
[-log <path to log file>]
[-overwrite]
[-recursive][-readOnly]
[-deleteProject]
[-noanalysis]
[-processor <languageID>]
[-cspec <compilerSpecID>]
[-analysisTimeoutPerFile <timeout in seconds>]
[-keystore <KeystorePath>]
[-connect <userID>]
[-p]
[-commit ["<comment>"]]
[-okToDelete]
[-max-cpu <max cpu cores to use>]
[-loader <desired loader name>]Derive from Plugin (directly or indirectly)
/**
* Plugin to for adding/deleting/editing bookmarks.
*/
//@formatter:off
@PluginInfo(
status = PluginStatus.RELEASED,
packageName = CorePluginPackage.NAME,
category = PluginCategoryNames.CODE_VIEWER,
shortDescription = "Manage Bookmarks",
description = "This plugin allows the user to add, edit, " +
"delete, and show bookmarks. It adds navigation markers at " +
"addresses where bookmarks reside.",
servicesRequired = { GoToService.class, MarkerService.class },
servicesProvided = { BookmarkService.class },
eventsProduced = { ProgramSelectionPluginEvent.class }
)
//@formatter:on/**
* Plugin to for adding/deleting/editing bookmarks.
*/
...
servicesRequired = { GoToService.class, MarkerService.class },
servicesProvided = { BookmarkService.class },
.../**
* Visible Plugin to show ByteBlock data in various formats.
*/
//@formatter:off
@PluginInfo(
...
shortDescription = "Displays bytes in memory",
...
servicesRequired = { ProgramManager.class, GoToService.class,
NavigationHistoryService.class, ClipboardService.class },
eventsConsumed = {
ProgramLocationPluginEvent.class, ProgramActivatedPluginEvent.class,
ProgramSelectionPluginEvent.class, ProgramHighlightPluginEvent.class,
ProgramClosedPluginEvent.class, ByteBlockChangePluginEvent.class },
eventsProduced = { ProgramLocationPluginEvent.class,
ProgramSelectionPluginEvent.class, ByteBlockChangePluginEvent.class }
)
//@formatter:on/**
* Visible Plugin to show ByteBlock data in various formats.
*/
...
eventsConsumed = {
ProgramLocationPluginEvent.class, ProgramActivatedPluginEvent.class,
ProgramSelectionPluginEvent.class, ProgramHighlightPluginEvent.class,
ProgramClosedPluginEvent.class, ByteBlockChangePluginEvent.class },
eventsProduced = { ProgramLocationPluginEvent.class,
ProgramSelectionPluginEvent.class, ByteBlockChangePluginEvent.class }
...DockingAction defines a user action associated with a toolbar icon and/or menu
item.
DockingActions can be invoked from the global menu, a popup menu, a toolbar, and/or a keybinding.
A plugin may supply a ComponentProvider that provides a visual component when
the plugin is added to the tool
- All Plugin Classes MUST END IN ”Plugin”*
- Have a
@PluginInfo(...)annotationPluginInfo( status = PluginStatus.RELEASED, packageName = CorePluginPackage.NAME, category = PluginCategoryNames.COMMON, shortDescription = "Short description of plugin", description = "Longer description of plugin.", servicesProvided = { ServiceInterfaceThisPluginProvides.class } servicesRequired = { RequiredServiceInterface1.class, RequiredServiceInterface2.class }, eventsConsumed = { SomePluginEvent.class }, eventsProduced = { AnotherPluginEvent.class }, isSlowInstallation = false )
- Have a constructor with exactly 1 parameter:
PluginToolpublic MyPlugin(PluginTool tool) { ... }
- Register provided service implementations in
constructor - In
init()- Retrieve services consumed
- Create actions
- In
dispose()- Release resources
OptionsChangeListener— to receive notification when a configuration option is changed by the userFrontEndable— marks this Plugin as being suitable for inclusion in the FrontEnd toolFrontEndOnly— marks this Plugin as FrontEnd only, not usable in CodeBrowser or other toolsProgramaticUseOnly— marks this Plugin as special and not for user configuration
Extends Plugin class
Base class to handle common program events:
- Program Open/Close
- Program Location
- Program Selection
- Program Highlight
- Title bar
- Local toolbar
- Menu icon
- Close button
- Mouse cursor provides feedback
- Components can be stacked, docked or floating
Allow users to customize the layout of components within a tool
Not used GUI toolkit
Managed GUI component in the tool
myComponent = new MyComponent(...);
tool.addComponent(this, myComponent);- Permanent — are always available in Window menu and closing just hides them (e.g., Listing)
- Transient — created on the fly and when closed are destroyed and removed from Window menu (e.g., Search Results)
GTableGTreeGComboBox- etc
Provides:
- Custom filtering
- Event handling
- Threaded models
- Navigation
- Look-and-feel
GTable
- Filters
- Columns
- Export to CSV
GTree
- Filters
- Lazy loading to support large data
- Right mouse actions are context sensitive
- List of actions that appear will change based on where the cursor is located
- User can assign/override key bindings (
F4)
- ELF
- PE
- Mach-O
- etc
What is needed for a new format?
- Data structure to parse the format
- Language, if not currently supported
- Loader for Ghidra’s importer
- Analyzers to annotate the binary format
Use Skeleton extension
- Used to disassemble binary to assemble
- Used to decompile assembly into C
- Decompiler optimizes
- Performs data type propagation
- etc
${GHIDRA_HOME}/Ghidra/Processors
Must implement Loader interface (all Loader Classes MUST END IN ”Loader”)
Consider AbstractProgramLoader or AbstractLibraryLoader
public class SkeletonLoader implements Loader {
Collection<LoadSpec> findSupportedLoadSpecs(...);
List<DomainObject> load(...);
...
}Must update the .opinion file for each processor supported by the format
<opinions>
<constraint loader="Skeleton" compilerSpecID="default">
<constraint primary="40" secondary="123"
processor="Skel" size="16" variant="default" />
</constraint>
<constraint loader="MS Common Object File Format (COFF)"
compilerSpecID="default">
<constraint primary="61" processor="Skel" size="16"
variant="default" />
</constraint>
</opinions>Must implement Analyzer interface (all Analyzer Classes MUST END IN
”Analyzer”)
// Display name, input type, priority
String getName();
AnalyzerType getAnalysisType();
AnalysisPriority getPriority();
// Called for changes to analyzers inputs
boolean added(...);
boolean removed(...);
// Register and react to user options
void registerOptions(...);
void optionsChanged(...);
...- BYTES — analyze anywhere defined bytes are present (block of memory added)
- INSTRUCTIONS — analyze anywhere instructions are defined
- FUNCTIONS — analyze where a function is defined
- FUNCTION-MODIFIERS — analyze functions whose modifiers have changed
- FUNCTION-SIGNATURES — analyze functions whose signatures have changed
- DATA — analyze where data has been defined
Provides an alternative importer, which allows importing many programs from a single archive or image
- Drills down into file systems, including nested file systems
- Extract files
- Import binaries
- Perform static analysis
- View as text
- View as image (i.e., picture)
- Android XML
- Android APK
- Apple 8900
- GZIP
- YAFFS2
- Android DEX to JAR
- 7Zip
- COFF Archive
- CPIO
- Crushed PNG
- iOS Disk Image (DMG)
- iOS DYLD Cache Version 1
- etc
Extensible using GFileSystem interface (all GFileSystem Sub-classes MUST END
IN ”FileSystem”)
@FileSystemInfo(type = "ext4",
description = "EXT4",
factory = Ext4FileSystemFactory.class)
public class Ext4FileSystem implements GFileSystem {
...
}


















