Skip to content

Commit

Permalink
core: enable users to specify a custom ghidrathon.save path via an en…
Browse files Browse the repository at this point in the history
…vironment variable (#99)

* Allow users to set a custom ghidrathon.save path via env variable

* Add GHIDRATHON_SAVE_PATH documentation to README.md

* Log ghidrathon.save path in debug mode

* Add support for GHIDRATHON_SAVE_PATH in Ghidrathon extension

* Add tests for GHIDRATHON_SAVE_PATH support

* Add GHIDRATHON_SAVE_PATH documentation to README.md

Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>

* Add tests for GHIDRATHON_SAVE_PATH support

* Minor fixes on tests.yml

* Add documentation for -overwrite flag

* Rename GHIDRATHON_SAVE_PATH variable to GHIDRATHON_SAVE_PATH_DEFAULT

* Disallow empty string for GHIDRATHON_SAVE_PATH

* Check validity of GHIDRATHON_SAVE_PATH directory

* Undo renaming of GHIDRATHON_SAVE_PATH

* Disallow empty string for GHIDRATHON_SAVE_PATH

To make sure that Ghidrathon plugin aligns with configure_ghidrathon.py
we need to make sure that the GHIDRATHON_SAVE_PATH is never set to "".

* Fix logic of GHIDRATHON_SAVE_PATH value

The following commit fixes incorrect login in the previous commit.
Please refer to the explination below:

if GHIDRATHON_SAVE_PATH is set to any value (other than None or ""),
check if it exists and is a directory.

elif GHIDRATHON_SAVE_PATH is an empty string, report an invalid
directory to avoid confusion.

else GHIDRATHON_SAVE_PATH is not, use default install path.

* Fix linting

* Add debug output indicating save file location

Added log messages to indicate whether the file path was read from the
environment variable or the default path was used.

* minor fix: indent comments properly in tests.yml

---------

Co-authored-by: Mike Hunhoff <mike.hunhoff@gmail.com>
  • Loading branch information
s-ff and mike-hunhoff committed Apr 30, 2024
1 parent 6183fa9 commit a3deefd
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 11 deletions.
32 changes: 28 additions & 4 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ jobs:
jep-jar-release-url: ["https://github.com/ninia/jep/releases/download/v4.2.0/jep-4.2.0.jar"]
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.8", "3.12"]
include:
- os: ubuntu-latest
ghidrathon-save-path: "/tmp/"
- os: windows-latest
ghidrathon-save-path: "C:\\Temp\\"
- os: macos-latest
ghidrathon-save-path: "/tmp/"
steps:
- name: Checkout Ghidrathon
uses: actions/checkout@v4
Expand Down Expand Up @@ -98,12 +105,29 @@ jobs:
run: |
Rename-Item -Path "./dist/$((Get-ChildItem -Path "./dist").Name)" -NewName "Ghidrathon.zip"
tar -xf ./dist/Ghidrathon.zip -C ../tmp/ghidra/ghidra_PUBLIC/Ghidra/Extensions/
- name: Set Ghidrathon Python interpreter
# test Ghidrathon when GHIDRATHON_SAVE_PATH is unset
- name: Set Ghidrathon Python interpreter (GHIDRATHON_SAVE_PATH is unset)
run: python util/ghidrathon_configure.py ../tmp/ghidra/ghidra_PUBLIC -d
- name: Run tests
- name: Run tests (GHIDRATHON_SAVE_PATH is unset)
run: | # the -overwrite flag ensures that an existing project file that conflicts with an import file is overwritten
../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 -overwrite -PostScript ${{ github.workspace }}/data/python/tests/hello.py -PostScript ${{ github.workspace }}/data/python/tests/runall.py > ../tmp/log.txt
- name: Check tests (GHIDRATHON_SAVE_PATH is unset)
run: |
../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 > ../tmp/log.txt
- name: Check tests
python -c "import pathlib, sys;log_text=pathlib.Path('../tmp/log.txt').read_text(encoding='utf-8');print(log_text);sys.exit(0 if 'runall.py called exit with code 0' in log_text else -1)"
python -c "import pathlib, sys; sys.exit(0 if pathlib.Path('hello.txt').exists() else -1)"
# test Ghidrathon when GHIDRATHON_SAVE_PATH is set
- name: Set Ghidrathon Python interpreter (GHIDRATHON_SAVE_PATH is set)
env:
GHIDRATHON_SAVE_PATH: ${{ matrix.ghidrathon-save-path }}
run: python util/ghidrathon_configure.py ../tmp/ghidra/ghidra_PUBLIC -d
- name: Run tests (GHIDRATHON_SAVE_PATH is set)
env:
GHIDRATHON_SAVE_PATH: ${{ matrix.ghidrathon-save-path }}
run: | # the -overwrite flag ensures that an existing project file that conflicts with an import file is overwritten
../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 -overwrite -PostScript ${{ github.workspace }}/data/python/tests/hello.py -PostScript ${{ github.workspace }}/data/python/tests/runall.py > ../tmp/log.txt
- name: Check tests (GHIDRATHON_SAVE_PATH is set)
run: |
python -c "import pathlib, sys;log_text=pathlib.Path('../tmp/log.txt').read_text(encoding='utf-8');print(log_text);sys.exit(0 if 'runall.py called exit with code 0' in log_text else -1)"
python -c "import pathlib, sys; sys.exit(0 if pathlib.Path('hello.txt').exists() else -1)"
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ Use the following steps to install Ghidrathon to your Ghidra environment:
$ python -m pip install -r requirements.txt
$ python ghidrathon_configure.py <absolute_path_to_ghidra_install_dir>
```
**Note**: `ghidrathon_configure.py` by default attempts to write a file named `ghidrathon.save` to `<absolute_path_to_ghidra_install_dir>`. You can specify the path where this file is written by setting the `GHIDRATHON_SAVE_PATH` environment variable before running `ghidrathon_configure.py` and Ghidra:
```
$ export GHIDRATHON_SAVE_PATH="/path/to/custom/dir" # Linux/MacOS
$ set GHIDRATHON_SAVE_PATH="C:\path\to\custom\dir" # Windows
```
**Note**: you may be prompted to set an environment variable named `JAVA_HOME`. This should reference the absolute path of the JDK that you have configured for your Ghidra install.

3. Install the Ghidrathon extension (`.zip`) into Ghidra:
Expand Down
24 changes: 19 additions & 5 deletions src/main/java/ghidrathon/interpreter/GhidrathonInterpreter.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ private class GhidrathonSave {
}

private static final String GHIDRATHON_SAVE_FILENAME = "ghidrathon.save";
private static final String GHIDRATHON_SAVE_PATH = "GHIDRATHON_SAVE_PATH";
private static final String SUPPORTED_JEP_VERSION = "4.2.0";

private Jep jep_ = null;
Expand Down Expand Up @@ -193,10 +194,23 @@ private void extendPythonSysPath() {
*/
private void configureJepMainInterpreter() throws JepException, FileNotFoundException {

File ghidrathonSaveFile =
new File(
Application.getApplicationRootDirectory().getParentFile().getFile(false),
GhidrathonInterpreter.GHIDRATHON_SAVE_FILENAME);
// get the ghidrathon.save path from the environment variable or use the default path
String ghidrathonSavePath = System.getenv(GHIDRATHON_SAVE_PATH);
File ghidrathonSaveFile;

if (ghidrathonSavePath != null && !ghidrathonSavePath.isEmpty()) {
ghidrathonSaveFile = new File(ghidrathonSavePath, GHIDRATHON_SAVE_FILENAME);
Msg.info(
GhidrathonInterpreter.class,
String.format("Using save file from environment variable %s.", GHIDRATHON_SAVE_PATH));
} else {
ghidrathonSaveFile =
new File(
Application.getApplicationRootDirectory().getParentFile().getFile(false),
GHIDRATHON_SAVE_FILENAME);
Msg.info(GhidrathonInterpreter.class, String.format("Using default save file path."));
}

if (!(ghidrathonSaveFile.exists() && ghidrathonSaveFile.isFile())) {
throw new JepException(
String.format(
Expand All @@ -206,7 +220,7 @@ private void configureJepMainInterpreter() throws JepException, FileNotFoundExce

Msg.info(
GhidrathonInterpreter.class,
String.format("Using save file at %s.", ghidrathonSaveFile.getAbsolutePath()));
String.format("Using save file found at %s.", ghidrathonSaveFile.getAbsolutePath()));

GhidrathonSave ghidrathonSave = null;
try (BufferedReader reader = new BufferedReader(new FileReader(ghidrathonSaveFile))) {
Expand Down
36 changes: 34 additions & 2 deletions util/ghidrathon_configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and limitations under the License.

import os
import sys
import json
import logging
Expand All @@ -17,6 +18,8 @@
SUPPORTED_JEP_VERSION = "4.2.0"
PYTHON_HOME_DIR_KEY = "home"
PYTHON_EXECUTABLE_FILE_KEY = "executable"
GHIDRATHON_SAVE_PATH = "GHIDRATHON_SAVE_PATH"
GHIDRATHON_SAVE_FILENAME = "ghidrathon.save"

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -91,7 +94,34 @@ def main(args):
logger.debug('Using Python home located at "%s".', home_path)

json_: str = json.dumps(ghidrathon_save)
save_path: pathlib.Path = install_path / "ghidrathon.save"
ghidrathon_save_path_env = os.environ.get(GHIDRATHON_SAVE_PATH)

if ghidrathon_save_path_env == "":
logger.error(
'The path specified by the "%s" environment variable "%s" is not a valid directory.',
GHIDRATHON_SAVE_PATH,
ghidrathon_save_path_env,
)
return -1
elif ghidrathon_save_path_env:
save_path: pathlib.Path = pathlib.Path(ghidrathon_save_path_env)
if not all((save_path.exists(), save_path.is_dir())):
logger.error(
'The path specified by the "%s" environment variable "%s" is not a valid directory.',
GHIDRATHON_SAVE_PATH,
ghidrathon_save_path_env,
)
return -1
save_path = save_path / GHIDRATHON_SAVE_FILENAME
logger.debug(
'Using save file path from environment variable "%s": "%s"',
GHIDRATHON_SAVE_PATH,
save_path,
)
else:
save_path: pathlib.Path = install_path / GHIDRATHON_SAVE_FILENAME
logger.debug('Using default save file path "%s"', save_path)

try:
save_path.write_text(json_, encoding="utf-8")
except Exception as e:
Expand Down Expand Up @@ -133,7 +163,9 @@ def main(args):
)

parser.add_argument(
"ghidrathon_install_directory", type=pathlib.Path, help="Absolute path of Ghidra install directory"
"ghidrathon_install_directory",
type=pathlib.Path,
help="Absolute path of Ghidra install directory",
)
parser.add_argument("-d", "--debug", action="store_true", help="Show debug messages")

Expand Down

0 comments on commit a3deefd

Please sign in to comment.