Skip to content

Commit

Permalink
add kotlin (#16)
Browse files Browse the repository at this point in the history
Adds support for Kotlin scripts and an interactive Kotlin terminal. Kotlin
1.6.0 is included as a list of jars that can be manually downloaded or
done automatically via an included script.

This change also refactors the extension structure to make the addition of
new languages easier, and adds some basic documentation of this new
structure for others to follow.
  • Loading branch information
goatshriek authored Feb 7, 2022
1 parent 4a38a49 commit 8d4c683
Show file tree
Hide file tree
Showing 44 changed files with 1,800 additions and 563 deletions.
44 changes: 26 additions & 18 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,18 @@ jobs:
runs-on: "ubuntu-latest"
strategy:
matrix:
ghidra: ["9.2.4", "10.0.4", "10.1.1"]
ghidra: ["10.0.4", "10.1.2"]
include:
- ghidra: "9.2.4"
ghidra-url: "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_9.2.4_build/ghidra_9.2.4_PUBLIC_20210427.zip"
ghidra-sha256: "c1f18cdb12e2e1c0313e7becf7f0387226937ac67ad6c6e5056fa889229f969a"
ghidra-filename: "ghidra_9.2.4_PUBLIC_20210427.zip"
ghidra-folder: "ghidra_9.2.4_PUBLIC"
- ghidra: "10.0.4"
ghidra-url: "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_10.0.4_build/ghidra_10.0.4_PUBLIC_20210928.zip"
ghidra-sha256: "1ce9bdf2d7f6bdfe5dccd06da828af31bc74acfd800f71ade021d5211e820d5e"
ghidra-filename: "ghidra_10.0.4_PUBLIC_20210928.zip"
ghidra-folder: "ghidra_10.0.4_PUBLIC"
- ghidra: "10.1.1"
ghidra-url: "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_10.1.1_build/ghidra_10.1.1_PUBLIC_20211221.zip"
ghidra-sha256: "d4ee61ed669cec7e20748462f57f011b84b1e8777b327704f1646c0d47a5a0e8"
ghidra-filename: "ghidra_10.1.1_PUBLIC_20211221.zip"
ghidra-folder: "ghidra_10.1.1_PUBLIC"
- ghidra: "10.1.2"
ghidra-url: "https://github.com/NationalSecurityAgency/ghidra/releases/download/Ghidra_10.1.2_build/ghidra_10.1.2_PUBLIC_20220125.zip"
ghidra-sha256: "ac96fbdde7f754e0eb9ed51db020e77208cdb12cf58c08657a2ab87cb2694940"
ghidra-filename: "ghidra_10.1.2_PUBLIC_20220125.zip"
ghidra-folder: "ghidra_10.1.2_PUBLIC"

env:
GHIDRA_INSTALL_DIR: /home/runner/ghidra/${{ matrix.ghidra-folder }}
Expand Down Expand Up @@ -62,32 +57,45 @@ jobs:
run: |
source "/home/runner/.sdkman/bin/sdkman-init.sh"
gradle buildExtension
rm -rf $GHIDRA_INSTALL_DIR/Ghidra/Extensions/*
rm -rf $GHIDRA_INSTALL_DIR/Ghidra/Extensions/ruby-dragon
unzip dist/$(ls dist) -d $GHIDRA_INSTALL_DIR/Ghidra/Extensions
mkdir ~/projects
- name: Download Dependencies
run: |
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -preScript DownloadDependenciesScript.java -deleteProject
- name: JRubyBasics Script
run: |
mkdir ~/projects
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -preScript ./ghidra_scripts/JRubyBasicsScriptRb.rb -deleteProject | grep -v "^\(INFO\)\|\(WARN\)\|\( \)" > actual.txt
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -preScript JRubyBasicsScriptRb.rb -deleteProject | grep -v "^\(INFO\)\|\(WARN\)\|\( \)" > actual.txt
awk '/^=begin$/{flag=1;next}/^=end$/{flag=0}flag' ghidra_scripts/JRubyBasicsScriptRb.rb > expected.txt
diff actual.txt expected.txt
rm actual.txt expected.txt
- name: Ghidra Basics Ruby Script
run: |
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript ./ghidra_scripts/GhidraBasicsScriptRb.rb HeadlessTest -deleteProject | awk '/^INFO SCRIPT:/{flag=1;next}/^INFO /{flag=0}flag' > actual.txt
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript GhidraBasicsScriptRb.rb HeadlessTest -deleteProject | awk '/^INFO SCRIPT:/{flag=1;next}/^INFO /{flag=0}flag' > actual.txt
diff actual.txt src/test/resources/expected/${{ matrix.ghidra }}-GhidraBasicsScriptRb.txt
rm actual.txt
- name: Ghidra Basics Kotlin Script
run: |
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript GhidraBasicsScriptKts.kts HeadlessTest -deleteProject | sed -n "s/^INFO GhidraBasicsScriptKts.kts> \(.*\) (GhidraScript).*$/\1/p" > actual.txt
diff actual.txt src/test/resources/expected/${{ matrix.ghidra }}-GhidraBasicsScriptKts.txt
rm actual.txt
- name: Ghidra Basics Clojure Script
run: |
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript ./ghidra_scripts/GhidraBasicsScriptClj.clj HeadlessTest -deleteProject | awk '/^INFO SCRIPT:/{flag=1;next}/^INFO /{flag=0}flag' > actual.txt
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript GhidraBasicsScriptClj.clj HeadlessTest -deleteProject | awk '/^INFO SCRIPT:/{flag=1;next}/^INFO /{flag=0}flag' > actual.txt
diff actual.txt src/test/resources/expected/${{ matrix.ghidra }}-GhidraBasicsScriptClj.txt
rm actual.txt
- name: Save Strings Ruby Script
run: |
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript ./ghidra_scripts/SaveStringsScriptRb.rb TestStringsRuby.txt -deleteProject
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript SaveStringsScriptRb.rb TestStringsRuby.txt -deleteProject
grep "Hello Ghidra!" TestStringsRuby.txt
rm TestStringsRuby.txt
- name: Save Strings Kotlin Script
run: |
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript SaveStringsScriptKts.kts TestStringsKotlin.txt -deleteProject
grep "Hello Ghidra!" TestStringsKotlin.txt
rm TestStringsKotlin.txt
- name: Save Strings Clojure Script
run: |
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript ./ghidra_scripts/SaveStringsScriptClj.clj TestStringsClojure.txt -deleteProject
$GHIDRA_INSTALL_DIR/support/analyzeHeadless ~/projects/ RubyDragonTest -import ./src/test/resources/bin/HelloGhidra.exe -postScript SaveStringsScriptClj.clj TestStringsClojure.txt -deleteProject
grep "Hello Ghidra!" TestStringsClojure.txt
rm TestStringsClojure.txt
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [1.1.0] - 2022-02-06
### Added
- Kotlin script capability (uses Kotlin 1.6.0)

### Removed
- Support for Ghidra 9.2.4 due to new BouncyCastle dependency.

## [1.0.3] - 2022-01-05
### Changed
- Upgrade to Jruby 9.3.2.0 (Ruby 2.6.8)
Expand Down
6 changes: 6 additions & 0 deletions NOTICE
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ of the project, refer to the project repository at
https://github.com/jruby/jruby. The full terms of the license can be found at
https://github.com/jruby/jruby/blob/master/COPYING.

The Kotlin logo included in the src/main/resources/images folder is
Copyright (c) Kotlin Foundation. Kotlin is covered under the Apache 2.0 license.
For more details on the language and its resources, see https://kotlinlang.org/.
For the full terms of the license included with Kotlin, see
https://github.com/JetBrains/kotlin/blob/master/license/LICENSE.txt.

The Clojure binary included in the lib folder is from the Clojure project,
Copyright (c) Rich Hickey. All rights reserved. It is covered by the EPL 1.0
license. For the source code of the project, refer to the project repository at
Expand Down
51 changes: 38 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[![build](https://github.com/goatshriek/ruby-dragon/actions/workflows/build.yml/badge.svg)](https://github.com/goatshriek/ruby-dragon/actions/workflows/build.yml)
[![Apache 2.0 License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)

Ruby and Clojure support for Ghidra, both interactive and scripting.
Ruby, Kotlin, and Clojure support for Ghidra, both interactive and scripting.


## Installation
Expand All @@ -17,20 +17,29 @@ You will then need to activate the plugin before using it. You might get
prompted to do this next time you open the CodeBrowser tool, in which case you
can simply select OK. Otherwise, you can manually activate it by opening the
CodeBrowser tool, going to `File->Configure...`, and selecting the `RubyDragon`
plugin for Ruby, and the `ClojureDragon` plugin for Clojure. They should appear
appear in the `Ghidra Core` listing, but you can check the `Configure All
Plugins` option if you aren't able to find them.
plugin for Ruby, the `KotlinDragon` plugin for Kotlin, and the `ClojureDragon`
plugin for Clojure. They should appear in the `Ghidra Core` listing, but you
can check the `Configure All Plugins` option if you aren't able to find them.

If you need to remove a language plugin, you can do so by unchecking the box in
the configuration dialog in the CodeBrowser tool, and then in the
`Install Extensions` menu from the project browser as well, and finally
restarting Ghidra. You may also need to manually delete the folder from your
the configuration dialog in the CodeBrowser tool. If you want to remove the
extension as a whole, you'll also need to uncheck it in the `Install Extensions`
menu from the project browser, and finally restart Ghidra. You may also need to
manually delete the folder from your
`.ghidra/<ghidrainstall>/Extensions` folder to completely remove it,
particularly if you want to load the plugin via the Eclipse plugin for
development.

The Kotlin extension has additional dependencies that are not included in the
plugin itself for size reasons. If you try to enable this extension before these
are available in the plugin directory, you'll receive a
`MissingDragonDependency` error. You can either copy the files into the `lib`
folder of the plugin yourself, or run the `DownloadDependenciesScript` Java
script included with the plugin to do this automatically, and finally restart
Ghidra (yet again).

## Basic Ruby Usage

## Ruby Usage
Once the RubyDragon plugin is enabled, you will be able to open an interactive
Ruby session from the CodeBrowser tool by going to `Window->Ruby`. This is a
tandard IRB session provided by JRuby.
Expand Down Expand Up @@ -60,10 +69,26 @@ You can also find help directly in the Ghidra help menu (press `F1`) on the
`Ghidra Functionality->Scripting->Ruby Interpreter` page.


## Basic Clojure Usage
Clojure is used in much the same way as the Ruby toolset with some obvious
differences, such as being provided by the `ClojureDragon` plugin and being
reached from the `Window->Clojure` menu option.
## Kotlin Usage
Kotlin is used in much the same way as the Ruby toolset with some obvious
differences, such as being provided by the `KotlinDragon` plugin and being
reached from the `Window->Kotlin` menu option. The built in variables for
scripts and the interpreter window in Kotlin are the same as Java:

```
currentAddress
currentHighlight
currentLocation
currentProgram
currentSelection
```

Kotlin scripts use a `kts` extension as they are interpreted as scripts rather
than being compiled to java first.

## Clojure Usage
Clojure follows the same patterns as the other languages, being provided in the
`ClojureDragon` plugin and reachable from the `Window->Clojure` menu option.

The Clojure interpreter and scripts also have bindings that make the state
information available to them, within the `ghidra` namespace. They are:
Expand Down Expand Up @@ -93,7 +118,7 @@ out and open an issue if you have any problems. Head over to the
discussion!

If you're feeling adventurous, you can add an example script in your language
of choice. This could be an equiavlent to one of the scripts that come packaged
of choice. This could be an equivalent to one of the scripts that come packaged
with Ghidra, or it could be all new! Just be sure you add a test for it in the
Github Action workflow so that it isn't broken later on. Check out the
`ghidra_scripts` folder to see what's there now, and perhaps draw some
Expand Down
2 changes: 2 additions & 0 deletions data/10_1_1_launch.properties
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,13 @@ VMARGS=-Xshare:off
VMARGS=--add-opens=java.base/java.lang=ALL-UNNAMED
VMARGS=--add-opens=java.base/java.util=ALL-UNNAMED
VMARGS=--add-opens=java.base/java.net=ALL-UNNAMED
VMARGS=--add-opens java.base/java.io=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.file=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.ftp=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.http=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.https=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.jar=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.nio.ch=ALL-UNNAMED
VMARGS=--add-opens=java.desktop/sun.awt.image=ALL-UNNAMED

# Persistent cache directory used by the application. This directory will be used to store
Expand Down
110 changes: 110 additions & 0 deletions data/10_1_2_launch.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Force Ghidra's Java home instead of trying to figure it out automatically.
# If the provided path does not point to a supported Java home that Ghidra
# supports, this property is ignored.
# NOTE: Ghidra requires a JDK to launch.
JAVA_HOME_OVERRIDE=

# Required Ghidra class loader
VMARGS=-Djava.system.class.loader=ghidra.GhidraClassLoader

# Set default encoding to UTF8
VMARGS=-Dfile.encoding=UTF8

# Set locale (only en_US is supported)
VMARGS=-Duser.country=US
VMARGS=-Duser.language=en
VMARGS=-Duser.variant=

# The following options affect rendering on different platforms. It may be necessary to play
# with these settings to get Ghidra to display and perform optimally on HiDPI monitors or in VM's.
VMARGS=-Dsun.java2d.opengl=false
VMARGS_LINUX=-Dsun.java2d.pmoffscreen=false
VMARGS_LINUX=-Dsun.java2d.xrender=true
VMARGS_LINUX=-Dsun.java2d.uiScale=1
VMARGS_LINUX=-Dawt.useSystemAAFontSettings=on
VMARGS_WINDOWS=-Dsun.java2d.d3d=false

# The Ghidra application establishes the default SSLContext for all
# secure client connections based upon Java's default TLS protocol enablement.
# Setting this property will restrict the enabled TLS protocol versions for
# all secure network connections. Specifying multiple protocols must be
# comma-separated (e.g., TLSv1.2,TLSv1.3). See https://java.com/en/configure_crypto.html
# for details on configuring Java's cryptographic algorithms.
VMARGS=-Djdk.tls.client.protocols=TLSv1.2,TLSv1.3

# Force PKI server authentication of all HTTPS and Ghidra Server connections by
# specifying path to installed CA certificates file.
# VMARGS=-Dghidra.cacerts=

# The following property will limit the number of processor cores that Ghidra
# will use for thread pools. If not specified, it will use the default number
# of processors returned from Runtime.getRuntime().getAvailableProcessors().
# Otherwise, it will use the min of the value returned from Runtime and the
# value specified by the following property.
VMARGS=-Dcpu.core.limit=

# The following property is a way to exactly specify the number of processor
# cores that Ghidra will use for thread pools. Note: this will supersede the
# above 'cpu.core.limit' value if it is set.
VMARGS=-Dcpu.core.override=

# Default font size for many java swing elements.
VMARGS=-Dfont.size.override=

# Set Jython console encoding (prevents a console error)
VMARGS=-Dpython.console.encoding=UTF-8

# Eclipse on macOS can have file locking issues if the user home directory is networked. Therefore,
# we will disable file locking by default for macOS. Comment the following line out if Eclipse file
# locking is needed and known to work.
VMARGS_MACOS=-Declipse.filelock.disable=true

# Where the menu bar is displayed on macOS
VMARGS_MACOS=-Dapple.laf.useScreenMenuBar=false

# Prevent log4j from using the Jansi DLL on Windows.
VMARGS_WINDOWS=-Dlog4j.skipJansi=true

# Custom class loader usage forces class data sharing to be disabled which produces a warning.
# Ghidra does not use class data sharing, so explicitly turn it off to avoid the warning.
VMARGS=-Xshare:off

# Permit "illegal reflective accesses" to enable JDK compatibility with Ghidra and 3rd party jars.
VMARGS=--add-opens=java.base/java.lang=ALL-UNNAMED
VMARGS=--add-opens=java.base/java.util=ALL-UNNAMED
VMARGS=--add-opens=java.base/java.net=ALL-UNNAMED
VMARGS=--add-opens java.base/java.io=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.file=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.ftp=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.http=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.https=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.jar=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.nio.ch=ALL-UNNAMED
VMARGS=--add-opens=java.desktop/sun.awt.image=ALL-UNNAMED

# Persistent cache directory used by the application. This directory will be used to store
# persistent application caches for all users. The default location for Mac/Linux is the same as
# specified by java.io.tmpdir property. The default location for Windows corresponds to the
# application local settings directory for the user (e.g., %LOCALAPPDATA%). If you wish to use a
# directory with more storage or avoid system cleanups, it may be desirable to override the default
# location.
#VMARGS=-Dapplication.cachedir=

# Temporary directory used by the application. This directory will be used for all temporary files
# and may also be used for the persistent user cache directory <java.io.tmpdir>/<username>-Ghidra.
# The specified directory must exist and have appropriate read/write/execute permissions
#VMARGS=-Djava.io.tmpdir=

# Disable alternating row colors in tables
#VMARGS=-Ddisable.alternating.row.colors=true

# The ContinuesInterceptor allows the import process to proceed if parsing corrupted headers
# generates uncaught exceptions. Its usage has been deprecated and will be removed in a future
# release of Ghidra. It is disabled by default.
#VMARGS=-DContinuesInterceptor.enabled=true

# Limit on XML parsing. See https://docs.oracle.com/javase/tutorial/jaxp/limits/limits.html
#VMARGS=-Djdk.xml.totalEntitySizeLimit=50000000

# Enables Pdb debug logging during import and analysis to .ghidra/.ghidra_ver/pdb.analyzer.log
#VMARGS=-Dpdb.logging=true
2 changes: 2 additions & 0 deletions data/10_1_launch.properties
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,13 @@ VMARGS=-Xshare:off
VMARGS=--add-opens=java.base/java.lang=ALL-UNNAMED
VMARGS=--add-opens=java.base/java.util=ALL-UNNAMED
VMARGS=--add-opens=java.base/java.net=ALL-UNNAMED
VMARGS=--add-opens java.base/java.io=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.file=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.ftp=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.http=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.https=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.net.www.protocol.jar=ALL-UNNAMED
VMARGS=--add-opens java.base/sun.nio.ch=ALL-UNNAMED
VMARGS=--add-opens=java.desktop/sun.awt.image=ALL-UNNAMED

# Persistent cache directory used by the application. This directory will be used to store
Expand Down
Loading

0 comments on commit 8d4c683

Please sign in to comment.