Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow users to specify a custom ghidrathon.save path via an environment variable #99

Merged
merged 18 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
fariss marked this conversation as resolved.
Show resolved Hide resolved
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
Loading