Skip to content

Commit

Permalink
1.0.0 Release
Browse files Browse the repository at this point in the history
  • Loading branch information
dc3-tsd committed Jan 30, 2024
1 parent 15ec91f commit 439e112
Show file tree
Hide file tree
Showing 20 changed files with 474 additions and 291 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
# This workflow can be matrixed against multiple Python versions if desired. eg. [3.7, 3.8, 3.9, "3.10"]
python-version: [ 3.8 ]
python-version: [ "3.11" ]

steps:
# Get the code from the repository to be linted, packaged, and pushed
Expand Down
16 changes: 14 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## [1.0.0] - 2024-01-30
- Fixed #21, #31 and #34.
- Phidra launcher will no longer terminate Python if a fatal exception occurs when launching, except in GUI mode.
- Adds `this` variable to Python scripts to mirror Ghidra's builtin Python script behavior.
- Plugins are now compiled targeting JDK 17.
- Fixed deprecation warning when compiling plugin.
- Adds compatibility for future Ghidra 11.1 releases.
- Dropped support for versions of Ghidra older than 10.3.
- Removed use of deprecated `ProgramPlugin` constructor.
- Dropped support for Python 3.8.

## [0.5.4] - 2023-12-12
- Fix bug when running a script using the CLI. (#32)

Expand Down Expand Up @@ -75,8 +86,9 @@
## 0.1.0 - 2021-06-14
- Initial release

[Unreleased]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.5.4...HEAD
[0.5.34]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.5.3...0.5.4
[Unreleased]: https://github.com/dod-cyber-crime-center/pyhidra/compare/1.0.0...HEAD
[1.0.0]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.5.4...1.0.0
[0.5.4]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.5.3...0.5.4
[0.5.3]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.5.2...0.5.3
[0.5.2]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.5.1...0.5.2
[0.5.1]: https://github.com/dod-cyber-crime-center/pyhidra/compare/0.5.0...0.5.1
Expand Down
12 changes: 6 additions & 6 deletions pyhidra/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@

__version__ = "0.5.4"
__version__ = "1.0.0"

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


__all__ = [
"run_script", "start", "started", "open_program", "get_current_interpreter",
"DeferredPyhidraLauncher", "HeadlessPyhidraLauncher", "GuiPyhidraLauncher",
"ExtensionDetails",
"get_current_interpreter", "open_program", "run_script", "start", "started",
"ApplicationInfo", "DeferredPyhidraLauncher", "ExtensionDetails",
"GuiPyhidraLauncher", "HeadlessPyhidraLauncher"
]
39 changes: 28 additions & 11 deletions pyhidra/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import argparse
import code
import logging

import sys
from pathlib import Path
Expand Down Expand Up @@ -40,7 +39,9 @@ def __init__(self, parser: argparse.ArgumentParser, **kwargs):
self.script_path: Path = None
self.project_name = None
self.project_path: Path = None
self.install_dir: Path = None
self._script_args = []
self.gui = False

def func(self):
"""
Expand All @@ -50,6 +51,10 @@ def func(self):
self.parser.print_usage()
return

if self.gui:
pyhidra.gui.gui(self.install_dir)
return

if self.script_path is not None:
try:
pyhidra.run_script(
Expand All @@ -59,7 +64,8 @@ def func(self):
project_name=self.project_name,
script_args=self._script_args,
verbose=self.verbose,
analyze=not self.skip_analysis
analyze=not self.skip_analysis,
install_dir=self.install_dir
)
except KeyboardInterrupt:
# gracefully finish when cancelled
Expand All @@ -72,10 +78,11 @@ def func(self):
self.verbose,
not self.skip_analysis
)
with pyhidra.core._flat_api(*args) as api:
with pyhidra.core._flat_api(*args, install_dir=self.install_dir) as api:
_interpreter(api)
else:
pyhidra.HeadlessPyhidraLauncher(verbose=self.verbose).start()
pyhidra.HeadlessPyhidraLauncher(
verbose=self.verbose, install_dir=self.install_dir).start()
_interpreter(globals())

@property
Expand Down Expand Up @@ -143,7 +150,7 @@ def _get_parser():
is_win32 = sys.platform == "win32"
extra_flag = "[-s] " if is_win32 else ""
usage = f"pyhidra [-h] [-v] [-g] {extra_flag}[--no-analysis] [--project-name name] [--project-path path] " \
"[binary_path] [script_path] ..."
"[binary_path] [script_path] ..."
parser = argparse.ArgumentParser(prog="pyhidra", usage=usage)
parser.add_argument(
"-v",
Expand All @@ -155,9 +162,8 @@ def _get_parser():
parser.add_argument(
"-g",
"--gui",
action="store_const",
dest="func",
const=pyhidra.gui.gui,
action="store_true",
dest="gui",
help="Start Ghidra GUI"
)
if is_win32:
Expand All @@ -169,6 +175,15 @@ def _get_parser():
const=_create_shortcut,
help="Creates a shortcut that can be pinned to the taskbar (Windows only)"
)
parser.add_argument(
"--install-dir",
type=Path,
default=None,
dest="install_dir",
metavar="",
help="Path to Ghidra installation. "\
"(defaults to the GHIDRA_INSTALL_DIR environment variable)"
)
parser.add_argument(
"--skip-analysis",
dest="skip_analysis",
Expand All @@ -183,8 +198,10 @@ def _get_parser():
parser.add_argument(
"script_path",
action=PathAction,
help="Headless script path. The script must have a .py extension. " \
help=(
"Headless script path. The script must have a .py extension. "
"If a script is not provided, pyhidra will drop into a repl."
)
)
parser.add_argument(
"script_args",
Expand All @@ -197,15 +214,15 @@ def _get_parser():
dest="project_name",
metavar="name",
help="Project name to use. "
"(defaults to binary filename with \"_ghidra\" suffix if provided else None)"
"(defaults to binary filename with \"_ghidra\" suffix if provided else None)"
)
parser.add_argument(
"--project-path",
type=Path,
dest="project_path",
metavar="path",
help="Location to store project. "
"(defaults to same directory as binary file if provided else None)"
"(defaults to same directory as binary file if provided else None)"
)
return parser

Expand Down
13 changes: 0 additions & 13 deletions pyhidra/constants.py

This file was deleted.

26 changes: 18 additions & 8 deletions pyhidra/core.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import contextlib
from pathlib import Path
from typing import Union, TYPE_CHECKING, Tuple, ContextManager, List
from typing import Union, TYPE_CHECKING, Tuple, ContextManager, List, Optional

from pyhidra.converters import * # pylint: disable=wildcard-import, unused-wildcard-import

Expand Down Expand Up @@ -77,7 +77,7 @@ def _setup_project(
project_location = binary_path.parent
if not project_name:
project_name = f"{binary_path.name}_ghidra"
project_location = project_location / project_name
project_location /= project_name
project_location.mkdir(exist_ok=True, parents=True)

# Open/Create project
Expand Down Expand Up @@ -208,13 +208,15 @@ def open_program(

@contextlib.contextmanager
def _flat_api(
binary_path: Union[str, Path],
binary_path: Union[str, Path] = None,
project_location: Union[str, Path] = None,
project_name: str = None,
verbose=False,
analyze=True,
language: str = None,
compiler: str = None
compiler: str = None,
*,
install_dir: Path = None
):
"""
Runs a given script on a given binary path.
Expand All @@ -232,12 +234,15 @@ def _flat_api(
(Defaults to Ghidra's detected LanguageID)
:param compiler: The CompilerSpecID to use for the program. Requires a provided language.
(Defaults to the Language's default compiler)
:param install_dir: The path to the Ghidra installation directory. This parameter is only
used if Ghidra has not been started yet.
(Defaults to the GHIDRA_INSTALL_DIR environment variable)
:raises ValueError: If the provided language or compiler is invalid.
"""
from pyhidra.launcher import PyhidraLauncher, HeadlessPyhidraLauncher

if not PyhidraLauncher.has_launched():
HeadlessPyhidraLauncher(verbose=verbose).start()
HeadlessPyhidraLauncher(verbose=verbose, install_dir=install_dir).start()

project, program = None, None
if binary_path or project_location:
Expand Down Expand Up @@ -268,15 +273,17 @@ def _flat_api(

# pylint: disable=too-many-arguments
def run_script(
binary_path: Union[str, Path],
binary_path: Optional[Union[str, Path]],
script_path: Union[str, Path],
project_location: Union[str, Path] = None,
project_name: str = None,
script_args: List[str] = None,
verbose=False,
analyze=True,
lang: str = None,
compiler: str = None
compiler: str = None,
*,
install_dir: Path = None
):
"""
Runs a given script on a given binary path.
Expand All @@ -294,9 +301,12 @@ def run_script(
(Defaults to Ghidra's detected LanguageID)
:param compiler: The CompilerSpecID to use for the program. Requires a provided language.
(Defaults to the Language's default compiler)
:param install_dir: The path to the Ghidra installation directory. This parameter is only
used if Ghidra has not been started yet.
(Defaults to the GHIDRA_INSTALL_DIR environment variable)
:raises ValueError: If the provided language or compiler is invalid.
"""
script_path = str(script_path)
args = binary_path, project_location, project_name, verbose, analyze, lang, compiler
with _flat_api(*args) as script:
with _flat_api(*args, install_dir=install_dir) as script:
script.run(script_path, script_args)
Loading

0 comments on commit 439e112

Please sign in to comment.