Skip to content

Commit 32f3969

Browse files
authored
configure Ghidrathon using absolute path of Python interpreter used to install Jep (#85)
* configure Ghidrathon using absolute path of Python interpreter * update license * fixup README
1 parent a7b2d9c commit 32f3969

28 files changed

+435
-306
lines changed

.github/workflows/tests.yml

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
11+
tests:
12+
name: Tests in ${{ matrix.python-version }} on ${{ matrix.os }}
13+
runs-on: ${{ matrix.os }}
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
ghidra-release-url: ["https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_10.3.2_build/ghidra_10.3.2_PUBLIC_20230711.zip", "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_11.0_build/ghidra_11.0_PUBLIC_20231222.zip"]
18+
jep-jar-release-url: ["https://github.com/ninia/jep/releases/download/v4.2.0/jep-4.2.0.jar"]
19+
os: [ubuntu-latest, windows-latest, macos-latest]
20+
python-version: ["3.8", "3.12"]
21+
steps:
22+
- name: Checkout Ghidrathon
23+
uses: actions/checkout@v4
24+
- name: Setup Java
25+
uses: actions/setup-java@v4
26+
with:
27+
distribution: "temurin"
28+
java-version: "17"
29+
- name: Setup Gradle
30+
uses: gradle/actions/setup-gradle@v3
31+
with:
32+
gradle-version: "7.3"
33+
- name: Setup Python ${{ matrix.python-version }}
34+
uses: actions/setup-python@v5
35+
with:
36+
python-version: ${{ matrix.python-version }}
37+
- name: Configure temp folder
38+
run: mkdir ../tmp
39+
- name: Install Python Jep
40+
run: |
41+
pip install numpy
42+
pip install jep==4.2.0
43+
python -c "import importlib.util;import pathlib;print(pathlib.Path(importlib.util.find_spec('jep').origin).parent)"
44+
- name: Download dependencies Linux/macOS
45+
if : ${{ matrix.os != 'windows-latest' }}
46+
run: |
47+
wget ${{ matrix.ghidra-release-url }} -O ../tmp/ghidra.zip
48+
unzip ../tmp/ghidra.zip -d ../tmp/ghidra
49+
mv ../tmp/ghidra/$(ls ../tmp/ghidra) ../tmp/ghidra/ghidra_PUBLIC
50+
wget ${{ matrix.jep-jar-release-url }} -O ./lib/jep-4.2.0.jar
51+
- name: Download dependencies Windows
52+
if : ${{ matrix.os == 'windows-latest' }}
53+
shell: pwsh
54+
run: |
55+
Invoke-WebRequest -URI "${{ matrix.ghidra-release-url }}" -OutFile "../tmp/ghidra.zip"
56+
mkdir ../tmp/ghidra
57+
tar -xf ../tmp/ghidra.zip -C ../tmp/ghidra
58+
Rename-Item -Path "../tmp/ghidra/$((Get-ChildItem -Path "../tmp/ghidra").Name)" -NewName "ghidra_PUBLIC"
59+
Invoke-WebRequest -URI "${{ matrix.jep-jar-release-url }}" -OutFile "./lib/jep-4.2.0.jar"
60+
- name: Build Ghidrathon
61+
run: gradle -PGHIDRA_INSTALL_DIR=${{ github.workspace }}/../tmp/ghidra/ghidra_PUBLIC
62+
- name: Install Ghidrathon Linux/macOS
63+
if : ${{ matrix.os != 'windows-latest' }}
64+
run: |
65+
unzip ./dist/$(ls ./dist) -d ../tmp/ghidra/ghidra_PUBLIC/Ghidra/Extensions/
66+
- name: Install Ghidrathon Windows
67+
if : ${{ matrix.os == 'windows-latest' }}
68+
shell: pwsh
69+
run: |
70+
Rename-Item -Path "./dist/$((Get-ChildItem -Path "./dist").Name)" -NewName "Ghidrathon.zip"
71+
tar -xf ./dist/Ghidrathon.zip -C ../tmp/ghidra/ghidra_PUBLIC/Ghidra/Extensions/
72+
- name: Set Ghidrathon Python interpreter
73+
run: python util/ghidrathon_configure.py ../tmp/ghidra/ghidra_PUBLIC
74+
- name: Run tests
75+
run: |
76+
../tmp/ghidra/ghidra_PUBLIC/support/analyzeHeadless ${{ github.workspace }}/../tmp/ghidra test -Import ${{ github.workspace }}/../tmp/ghidra/ghidra_PUBLIC/GPL/DemanglerGnu/os/linux_x86_64/demangler_gnu_v2_24 -PostScript ${{ github.workspace }}/data/python/tests/hello.py -PostScript ${{ github.workspace }}/data/python/tests/runall.py
77+
python -c "import pathlib, sys; sys.exit(0 if pathlib.Path('hello.txt').exists() else -1)"

LICENSE.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@
187187
same "printed page" as the copyright notice for easier
188188
identification within third-party archives.
189189

190-
Copyright (C) 2022 Mandiant, Inc.
190+
Copyright (C) 2024 Mandiant, Inc.
191191

192192
Licensed under the Apache License, Version 2.0 (the "License");
193193
you may not use this file except in compliance with the License.

README.md

+30-72
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Ghidrathon
22

33
[![License](https://img.shields.io/badge/license-Apache--2.0-green.svg)](LICENSE.txt)
4+
[![CI](https://github.com/mandiant/ghidrathon/actions/workflows/tests.yml/badge.svg)](https://github.com/mandiant/ghidrathon/actions/workflows/tests.yml)
45

5-
Ghidrathon is a Ghidra extension that adds Python 3 scripting capabilities to Ghidra. Why? Ghidra natively supports scripting in Java and Jython. Unfortunately many open-source analysis tools, like [capa](https://github.com/mandiant/capa), [Unicorn Engine](https://github.com/unicorn-engine/unicorn), [angr](https://github.com/angr/angr), etc., are written in Python 3 making it difficult, and in some cases, impossible to use these tools in Ghidra. More so the security community has released several great plugins for other SRE frameworks like IDA Pro and Binary Ninja, but again, because many of these plugins use Python 3 it is difficult to port them to Ghidra. Ghidrathon helps you use existing and develop new Python 3 tooling in Ghidra and script Ghidra using modern Python in a way that tightly integrates with Ghidra's UI.
6+
Ghidrathon is a Ghidra extension that adds Python 3 scripting capabilities to Ghidra. Why? Ghidra natively supports scripting in Java and Jython. Unfortunately, many open-source analysis tools, like [capa](https://github.com/mandiant/capa), [Unicorn Engine](https://github.com/unicorn-engine/unicorn), [angr](https://github.com/angr/angr), etc., are written in Python 3 making it difficult, and in some cases, impossible to use these tools in Ghidra. More so the security community has released several great plugins for other SRE frameworks like IDA Pro and Binary Ninja, but again, because many of these plugins use Python 3 it is difficult to port them to Ghidra. Ghidrathon helps you use existing and develop new Python 3 tooling in Ghidra and script Ghidra using modern Python in a way that tightly integrates with Ghidra's UI.
67

78
Check out:
89

@@ -54,7 +55,7 @@ INFO REPORT: Post-analysis succeeded for file: /example.o (HeadlessAnalyzer)
5455
INFO REPORT: Save succeeded for processed file: /example.o (HeadlessAnalyzer)
5556
```
5657

57-
For more information on running Ghidra in headless mode check out `<ghidra_install>/support/analyzeHeadlessREADME.html`.
58+
For more information on running Ghidra in headless mode check out `<absolute_path_to_ghidra_install_dir>/support/analyzeHeadlessREADME.html`.
5859

5960
## Third-Party Python Modules
6061

@@ -74,87 +75,44 @@ Ghidrathon links your local Python installation to Ghidra using the open-source
7475

7576
For more information on how Jep works to embed Python in Java see their documentation [here](https://github.com/ninia/jep/wiki/How-Jep-Works).
7677

77-
## OS Support
78-
79-
Ghidrathon supports the following operating systems:
80-
81-
* Linux
82-
* Windows
83-
* macOS (x86_64)
84-
85-
## Requirements
86-
87-
The following tools are needed to build, install, and run Ghidrathon:
78+
## Installing Ghidrathon
8879

80+
### Requirements
8981
Tool | Version |Source |
9082
|---|---|---|
91-
| Ghidra | `>= 10.3` | https://ghidra-sre.org |
92-
| Jep | `4.2.0` | https://github.com/ninia/jep |
93-
| Gradle | `>= 7.3` | https://gradle.org/releases |
94-
| Python | `>= 3.8` | https://www.python.org/downloads |
95-
96-
Note: Ghidra >= 10.2 requires [JDK 17 64-bit](https://adoptium.net/temurin/releases/).
97-
98-
## Python Virtual Environments
83+
| Ghidrathon | `>= 4.0.0` | https://github.com/mandiant/Ghidrathon/releases |
84+
| Python | `>= 3.8.0` | https://www.python.org/downloads |
85+
| Jep | `4.2.0` | https://github.com/ninia/jep/releases |
86+
| Ghidra | `>= 10.3.2` | https://github.com/NationalSecurityAgency/ghidra/releases |
87+
| Java | `>= 17.0.0` | https://adoptium.net/temurin/releases/ |
9988

100-
Ghidrathon supports Python virtual environments. To use a Python virtual environment, simply build Ghidrathon inside your virtual environment **and** execute Ghidra inside the **same** virtual environment.
101-
102-
## Building Ghidrathon
103-
104-
**Note:** Review [Python Virtual Environments](#python-virtual-environments) before building if you would like to use a Python virtual environment for Ghidrathon.
105-
106-
**Note**: Building Ghidrathon requires building Jep. If you are running Windows, this requires installing the Microsoft C++ Build Tools found [here](https://visualstudio.microsoft.com/visual-cpp-build-tools/). See Jep's documentation [here](https://github.com/ninia/jep/wiki/Windows) for more information on installing Jep on Windows.
107-
108-
Use the following steps to build Ghidrathon for your environment:
109-
110-
* Install Ghidra using the documentation [here](https://htmlpreview.github.io/?https://github.com/NationalSecurityAgency/ghidra/blob/stable/GhidraDocs/InstallationGuide.html#InstallationNotes)
111-
* Install Gradle from [here](https://gradle.org/releases)
112-
* Download the latest Ghidrathon source release from [here](https://github.com/mandiant/Ghidrathon/releases)
113-
* Run the following command from the Ghidrathon source directory:
114-
* **Note:** Ghidrathon defaults to the Python binary found in your path. You can specify a different Python binary by adding the optional argument `-PPYTHON_BIN=<absolute path to Python binary>` to the command below
115-
* **Note:** you may optionally set an environment variable named `GHIDRA_INSTALL_DIR` instead of specifying `-PGHIDRA_INSTALL_DIR`
89+
Use the following steps to install Ghidrathon to your Ghidra environment:
11690

91+
1. Install Jep:
11792
```
118-
$ gradle -PGHIDRA_INSTALL_DIR=<absolute path to Ghidra install>
93+
$ python -m pip install jep==4.2.0
11994
```
95+
2. Execute `ghidrathon_configure.py`:
96+
```
97+
$ python ghidrathon_configure.py <absolute_path_to_ghidra_install_dir>
98+
```
99+
3. Download and unzip the latest Ghidrathon [release](https://github.com/mandiant/Ghidrathon/releases)
100+
4. Install the Ghidrathon extension (`.zip`) into Ghidra:
101+
* Using Ghidra's UI:
102+
* Navigate to `File > Install Extensions...`
103+
* Click the green `+` button
104+
* Navigate to the Ghidrathon extension (`.zip`)
105+
* Click `Ok`
106+
* Using a limited environment:
107+
* Extract the Ghidrathon extension (`.zip`) to `<absolute_path_to_ghidra_install_dir>\Ghidra\Extensions`
120108

121-
This command installs Jep, configures Ghidrathon with the necessary Jep binaries, and builds Ghidrathon. If successful, you will find a new directory in your Ghidrathon source directory named `dist` containing your Ghidrathon extension (`.zip`). Please open a new issue if you experience any issues building Ghidrathon.
122-
123-
## Installing Ghidrathon
124-
125-
Use the following steps to install your Ghidrathon extension using the Ghidra UI:
126-
127-
* Start Ghidra
128-
* Navigate to `File > Install Extensions...`
129-
* Click the green `+` button
130-
* Navigate to your Ghidrathon extension built earlier (`.zip`)
131-
* Click `Ok`
132-
* Restart Ghidra
133-
134-
**OR**
135-
136-
Extract your Ghidrathon extension (`.zip`) directly to `<absolute path to Ghidra install>\Ghidra\Extensions` to automatically enable Ghidrathon the next time that Ghidra is started. This method works great if you do not have access to the Ghidra UI when installing Ghidrathon.
137-
138-
### Disabling Jython
139-
140-
Ghidrathon disables the built-in Jython script provider to avoid conflicts when Ghidra decides which provider should handle scripts with the `.py` file extension. This means existing Jython scripts cannot be executed with Ghidrathon installed. We recommend completely disabling the Jython extension.
141-
142-
Use the following steps to disable the Jython extension:
143-
144-
* Open a CodeBrowser window (*not the Project Manager window*)
145-
* Navigate to `File > Configure...`
146-
* Click `Ghidra Core`
147-
* Un-check `PythonPlugin`
148-
149-
Use the following steps to enable the Jython extension:
109+
### Switching Python Interpreters
150110

151-
* Uninstall Ghidrathon
152-
* Enable the Jython extension using the steps outlined above
153-
* Restart Ghidra
111+
You can switch Ghidrathon to use a different Python interpreter by running `ghidrathon_configure.py` using the new Python interpreter.
154112

155-
## Using Ghidrathon
113+
### Python Virtual Environments
156114

157-
See [Python 3 Interpreter Window](#python-3-interpreter-window), [Ghidra Script Manager Integration](#ghidra-script-manager-integration), and [Ghidra Headless Mode](#ghidra-headless-mode) for more information about using Ghidrathon.
115+
Ghidrathon supports Python virtual environments. To use a Python virtual environment, complete steps `1` and `2` using the Python interpreter that is configured for your environment. Do the same when running `ghidrathon_configure.py` to switch the Ghidrathon to use a different interpreter.
158116

159117
## Considerations
160118

build.gradle

+1-34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2022 Mandiant, Inc. All Rights Reserved.
1+
// Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
22
// Licensed under the Apache License, Version 2.0 (the "License");
33
// you may not use this file except in compliance with the License.
44
// You may obtain a copy of the License at: [package root]/LICENSE.txt
@@ -22,39 +22,6 @@
2222
// application.gradle.version property in <GHIDRA_INSTALL_DIR>/Ghidra/application.properties
2323
// for the correction version of Gradle to use for the Ghidra installation you specify.
2424

25-
def javaHome
26-
def pythonBin
27-
28-
if (project.hasProperty("PYTHON_BIN")) {
29-
pythonBin = project.getProperty("PYTHON_BIN")
30-
}
31-
else {
32-
pythonBin = "python"
33-
}
34-
35-
// we need to install Jep; this requires C++ build tools on Windows (see README); we need to define
36-
// the env variable "JAVA_HOME" containing absolute path to Java JDK configured for Ghidra
37-
task installJep(type: Exec) {
38-
environment "JAVA_HOME", System.getProperty("java.home")
39-
commandLine pythonBin, '-m', 'pip', 'install', 'jep==4.2'
40-
}
41-
42-
// we need to copy the Jep native binaries built in installJep to our extension directory; we use a small
43-
// utility script written in Python
44-
task copyJepNativeBinaries(type: Exec) {
45-
dependsOn installJep
46-
workingDir "${projectDir}"
47-
commandLine pythonBin, "util${File.separator}configure_jep_native_binaries.py"
48-
}
49-
50-
// make all tasks not matching copyJepNativeBinaries or installJep depend on copyJepNativeBinaries; mostly
51-
// used to ensure our tasks run before Ghidra buildExtension task
52-
tasks.matching { it.name != 'copyJepNativeBinaries' && it.name != 'installJep' }.all { Task task ->
53-
task.dependsOn copyJepNativeBinaries
54-
}
55-
56-
// from here we use the standard Gradle build provided by Ghidra framework
57-
5825
//----------------------START "DO NOT MODIFY" SECTION------------------------------
5926
def ghidraInstallDir
6027

data/GhidrathonConfig.xml

-5
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,5 @@
33
<ARRAY NAME="JAVA_EXCLUDE_LIBS" TYPE="string">
44
<A VALUE="pdb" />
55
</ARRAY>
6-
<ARRAY NAME="PYTHON_SHARED_MODULES" TYPE="string">
7-
<A VALUE="numpy" />
8-
</ARRAY>
9-
<ARRAY NAME="PYTHON_INCLUDE_PATHS" TYPE="string">
10-
</ARRAY>
116
</GHIDRATHON_CONFIG>
127

data/python/jepeval.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2022 Mandiant, Inc. All Rights Reserved.
1+
# Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
22
# Licensed under the Apache License, Version 2.0 (the "License");
33
# you may not use this file except in compliance with the License.
44
# You may obtain a copy of the License at: [package root]/LICENSE.txt

data/python/jeprunscript.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2022 Mandiant, Inc. All Rights Reserved.
1+
# Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
22
# Licensed under the Apache License, Version 2.0 (the "License");
33
# you may not use this file except in compliance with the License.
44
# You may obtain a copy of the License at: [package root]/LICENSE.txt

data/python/jepwelcome.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2022 Mandiant, Inc. All Rights Reserved.
1+
# Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
22
# Licensed under the Apache License, Version 2.0 (the "License");
33
# you may not use this file except in compliance with the License.
44
# You may obtain a copy of the License at: [package root]/LICENSE.txt

data/python/tests/hello.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Run Ghidrathon CI tests.
2+
# @author Mike Hunhoff (mehunhoff@google.com)
3+
# @category Python 3
4+
# Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at: [package root]/LICENSE.txt
8+
# Unless required by applicable law or agreed to in writing, software distributed under the License
9+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
# See the License for the specific language governing permissions and limitations under the License.
11+
12+
import pathlib
13+
import jep
14+
15+
path = pathlib.Path("hello.txt")
16+
path.write_text(f"Hello from Jep {jep.__version__}", encoding="utf-8")

data/python/tests/runall.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Run Ghidrathon unit tests.
2-
# @author Mike Hunhoff (michael.hunhoff@mandiant.com)
2+
# @author Mike Hunhoff (mehunhoff@google.com)
33
# @category Python 3
4-
# Copyright (C) 2022 Mandiant, Inc. All Rights Reserved.
4+
# Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
55
# Licensed under the Apache License, Version 2.0 (the "License");
66
# you may not use this file except in compliance with the License.
77
# You may obtain a copy of the License at: [package root]/LICENSE.txt

data/python/tests/test_cpython.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2022 Mandiant, Inc. All Rights Reserved.
1+
# Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
22
# Licensed under the Apache License, Version 2.0 (the "License");
33
# you may not use this file except in compliance with the License.
44
# You may obtain a copy of the License at: [package root]/LICENSE.txt

data/python/tests/test_jepbridge.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (C) 2022 Mandiant, Inc. All Rights Reserved.
1+
# Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
22
# Licensed under the Apache License, Version 2.0 (the "License");
33
# you may not use this file except in compliance with the License.
44
# You may obtain a copy of the License at: [package root]/LICENSE.txt

doc/building.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Building Ghidrathon
2+
3+
## Requirements
4+
5+
Tool | Version |Source |
6+
|---|---|---|
7+
| Ghidrathon | `>= 4.0.0` | https://github.com/mandiant/Ghidrathon/releases |
8+
| Ghidra | `>= 10.3.2` | https://github.com/NationalSecurityAgency/ghidra/releases |
9+
| Java | `>= 17.0.0` | https://adoptium.net/temurin/releases/ |
10+
| Gradle | `>= 7.3` | https://gradle.org/releases |
11+
12+
Use the following steps to build Ghidrathon:
13+
1. Download the [supported Jep JAR release](https://github.com/ninia/jep/releases/download/v4.2.0/jep-4.2.0.jar) to `<absolute_path_to_ghidrathon_source_dir>\lib`
14+
2. Execute gradle from `<absolute_path_to_ghidrathon_source_dir>`:
15+
```
16+
$ gradle -PGHIDRA_INSTALL_DIR=<absolute_path_to_Ghidra_install_dir>
17+
```
18+
19+
The extension is stored in `<absolute_path_to_ghidrathon_source_dir>\dist`.

extension.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=Ghidrathon
22
description=The FLARE team's open-source extension to add Python 3 scripting to Ghidra.
3-
author=Mike Hunhoff (michael.hunhoff@mandiant.com)
3+
author=Mike Hunhoff (mehunhoff@google.com)
44
createdOn=03/31/2022
55
version=@extversion@

ghidra_scripts/ghidrathon_example.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Print function basic block and instruction counts.
2-
# @author Mike Hunhoff (michael.hunhoff@mandiant.com)
2+
# @author Mike Hunhoff (mehunhoff@google.com)
33
# @category Python 3
44

5-
# Copyright (C) 2022 Mandiant, Inc. All Rights Reserved.
5+
# Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
66
# Licensed under the Apache License, Version 2.0 (the "License");
77
# you may not use this file except in compliance with the License.
88
# You may obtain a copy of the License at: [package root]/LICENSE.txt

os/linux_x86_64/README.txt

-3
This file was deleted.

os/mac_x86_64/README.txt

-3
This file was deleted.

os/win_x86_64/README.txt

-3
This file was deleted.

src/main/java/ghidrathon/GhidrathonClassEnquirer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2022 Mandiant, Inc. All Rights Reserved.
1+
// Copyright (C) 2024 Mandiant, Inc. All Rights Reserved.
22
// Licensed under the Apache License, Version 2.0 (the "License");
33
// you may not use this file except in compliance with the License.
44
// You may obtain a copy of the License at: [package root]/LICENSE.txt

0 commit comments

Comments
 (0)