Skip to content

Commit

Permalink
0.3.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
dc3-tsd committed Dec 15, 2022
1 parent cbebd8f commit 7e9c8e2
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 154 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## [0.3.0] - 2022-11-29
- Added ability to install custom plugins from the launcher using `install_plugin()`.
- Added ability to register entry_points for customizing launcher before starting up.

## [0.2.1] - 2022-11-03
- Adds compatibility for Ghidra 10.2.

Expand Down Expand Up @@ -45,7 +49,8 @@
## 0.1.0 - 2021-06-14
- Initial release

[Unreleased]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.2.1...HEAD
[Unreleased]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.3.0...HEAD
[0.3.0]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.2.1...0.3.0
[0.2.1]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.2.0...0.2.1
[0.2.0]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.1.5...0.2.0
[0.1.5]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.1.4...0.1.5
Expand Down
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,58 @@ launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true")
launcher.start()
```

### Registering an Entry Point

The `PyhidraLauncher` can also be configured through the use of a registered entry point on your own python project.
This is useful for installing your own Ghidra plugin which uses pyhidra and self-compiles.

First create an [entry_point](https://setuptools.pypa.io/en/latest/userguide/entry_point.html) for `pyhidra.setup`
pointing to a single argument function which accepts the launcher instance.

```python
# setup.py
from setuptools import setup

setup(
# ...,
entry_points={
'pyhidra.setup': [
'acme_plugin = acme.ghidra_plugin.install:setup',
]
}
)
```


Then we create the target function.
This function will be called every time a user starts a pyhidra launcher.
In the same fashion, another entry point `pyhidra.pre_launch` may be registered and will be called after Ghidra and all
plugins have been loaded.

```python
# acme/ghidra_plugin/install.py
from pathlib import Path
import pyhidra

def setup(launcher):
"""
Run by pyhidra launcher to install our plugin.
"""
launcher.add_classpaths("log4j-core-2.17.1.jar", "log4j-api-2.17.1.jar")
launcher.add_vmargs("-Dlog4j2.formatMsgNoLookups=true")

# Install our plugin.
source_path = Path(__file__).parent / "java" / "plugin" # path to uncompiled .java code
details = pyhidra.ExtensionDetails(
name="acme_plugin",
description="My Cool Plugin",
author="acme",
plugin_version="1.2",
)
launcher.install_plugin(source_path, details) # install plugin (if not already)
```


### Analyze a File

To have pyhidra setup a binary file for you, use the `open_program()` function.
Expand Down
6 changes: 4 additions & 2 deletions pyhidra/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@

__version__ = "0.2.1"
__version__ = "0.3.0"

# Expose API
from .ghidra import run_script, start, open_program
from .script import get_current_interpreter
from .launcher import DeferredPyhidraLauncher, HeadlessPyhidraLauncher, GuiPyhidraLauncher
from .version import ExtensionDetails


__all__ = [
"run_script", "start", "open_program",
"DeferredPyhidraLauncher", "HeadlessPyhidraLauncher", "GuiPyhidraLauncher"
"DeferredPyhidraLauncher", "HeadlessPyhidraLauncher", "GuiPyhidraLauncher",
"ExtensionDetails",
]
3 changes: 3 additions & 0 deletions pyhidra/__main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import argparse
import code
import logging

import sys
from pathlib import Path

Expand Down Expand Up @@ -196,6 +198,7 @@ def main():
"""
pyhidra module main function
"""
logging.basicConfig(level=logging.INFO)
parser = _get_parser()
parser.parse_args(namespace=PyhidraArgs(parser)).func()

Expand Down
7 changes: 6 additions & 1 deletion pyhidra/gui.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import contextlib

import logging
import os
import platform
import sys
import warnings

from pyhidra import get_current_interpreter as _get_current_interpreter

logger = logging.getLogger(__name__)


def _gui():
logging.basicConfig(level=logging.INFO)

if platform.system() == 'Windows':
# gui_script works like it is supposed to on windows
gui()
Expand Down
3 changes: 1 addition & 2 deletions pyhidra/java/plugin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
"""
Internal use only
"""
from .handler import install
"""
48 changes: 0 additions & 48 deletions pyhidra/java/plugin/handler.py

This file was deleted.

23 changes: 20 additions & 3 deletions pyhidra/java/plugin/plugin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import contextlib
import ctypes
import itertools
import logging
import rlcompleter
import sys
import threading
Expand All @@ -11,15 +12,18 @@
from ghidra.framework import Application
from java.io import BufferedReader, InputStreamReader, PushbackReader
from java.lang import ClassLoader, Runnable, String
from java.util import Collections
from java.util.function import Consumer
from jpype import JClass, JImplements, JOverride
from resources import ResourceManager
from utility.function import Callback

from pyhidra.java.plugin.completions import PythonCodeCompleter
from pyhidra.script import PyGhidraScript


logger = logging.getLogger(__name__)


def _get_private_class(path: str) -> JClass:
gcl = ClassLoader.getSystemClassLoader()
return JClass(path, loader=gcl)
Expand Down Expand Up @@ -173,6 +177,7 @@ def __init__(self, plugin):
return
self._plugin = plugin
self._actions = None
self._logged_completions_change = False
plugin_cls = _get_plugin_class()
_set_field(plugin_cls, "finalizer", Runnable @ self.dispose, plugin)
self.console = PyConsole(self)
Expand Down Expand Up @@ -219,8 +224,20 @@ def service(self):
return self._plugin.getTool().getService(InterpreterPanelService.class_)

@JOverride
def getCompletions(self, cmd: str):
return self.completer.get_completions(cmd)
def getCompletions(self, *args):
try:
if len(args) == 2:
line, pos = args
line = line[:pos]
else:
# older versions of Ghidra don't have the `end` argument.
line, = args
return self.completer.get_completions(line)
except Exception as e:
if not self._logged_completions_change:
self._logged_completions_change = True
logger.exception(e)
return Collections.emptyList()

@JOverride
def getIcon(self):
Expand Down
Loading

0 comments on commit 7e9c8e2

Please sign in to comment.