Files
capa/tests/test_ghidra_features.py
Colton Gabertan 058c1fefd2 ghidra: unit tests (#1727)
* restore from corrupted .git

* lint repo

* temp: remove lint failing rule

* implement dereferencing, clean up extractors

* implement proper dereferencing routines as applicable

* fix nzxor implementation, remediate ghidra analysis issues

* lint repo

* Assert typing, lint repo

* avoid extracting pointers in bytes extraction

* attempt to recover submodule

* implement GhidraFeatureExtractor & ghidra_main()

* lint repo

* document examples, clean-up & testing

* lint repo

* properly map import dict

* properly map fake addresses

* fix fake addr mapping

* properly map externs

* re-align consistency with other backends

* lint repo

* fix dereferencing routine

* clean up helpers

* fix format string

* disable progress bar to exit gracefully

* enable pbar in headless runtime mode

* implement fixture test script

* implement ghidra unit test script

* refactor repo for breaking Ghidrathon change

* bump ghidrathon CI version, run unit test in CI

* change CI config

* fix wget line for ghidrathon

* fix unzip paths

* fix ghidra import issue

* disable pytest faulthandler module

* fix ghidra state variables

* use toAddr

* restructure for consistency

* Bump Ghidrathon version for CI, fix pytest ghidra runtime detection
2023-08-21 12:16:13 -06:00

90 lines
3.2 KiB
Python

# Copyright (C) 2023 Mandiant, Inc. All Rights Reserved.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at: [package root]/LICENSE.txt
# Unless required by applicable law or agreed to in writing, software distributed under the License
# 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.
"""
Must invoke this script from within the Ghidra Runtime Enviornment
"""
import sys
import logging
import pytest
import fixtures
logger = logging.getLogger("test_ghidra_features")
ghidra_present: bool = False
try:
import ghidra # noqa: F401
ghidra_present = True
except ImportError:
pass
def standardize_posix_str(psx_str):
"""fixture test passes the PosixPath to the test data
params: psx_str - PosixPath() to the test data
return: string that matches test-id sample name
"""
if "Practical Malware Analysis Lab" in str(psx_str):
# <PosixPath>/'Practical Malware Analysis Lab 16-01.exe_' -> 'pma16-01'
wanted_str = "pma" + str(psx_str).split("/")[-1][len("Practical Malware Analysis Lab ") : -5]
else:
# <PosixPath>/mimikatz.exe_ -> mimikatz
wanted_str = str(psx_str).split("/")[-1][:-5]
if "_" in wanted_str:
# al-khaser_x86 -> al-khaser x86
wanted_str = wanted_str.replace("_", " ")
return wanted_str
def check_input_file(wanted):
"""check that test is running on the loaded sample
params: wanted - PosixPath() passed from test arg
"""
import capa.ghidra.helpers as ghidra_helpers
found = ghidra_helpers.get_file_md5()
sample_name = standardize_posix_str(wanted)
if not found.startswith(fixtures.get_sample_md5_by_name(sample_name)):
raise RuntimeError(f"please run the tests against sample with MD5: `{found}`")
@pytest.mark.skipif(ghidra_present is False, reason="Ghidra tests must be ran within Ghidra")
@fixtures.parametrize("sample,scope,feature,expected", fixtures.FEATURE_PRESENCE_TESTS, indirect=["sample", "scope"])
def test_ghidra_features(sample, scope, feature, expected):
try:
check_input_file(sample)
except RuntimeError:
pytest.skip(reason="Test must be ran against sample loaded in Ghidra")
fixtures.do_test_feature_presence(fixtures.get_ghidra_extractor, sample, scope, feature, expected)
@pytest.mark.skipif(ghidra_present is False, reason="Ghidra tests must be ran within Ghidra")
@fixtures.parametrize("sample,scope,feature,expected", fixtures.FEATURE_COUNT_TESTS, indirect=["sample", "scope"])
def test_ghidra_feature_counts(sample, scope, feature, expected):
try:
check_input_file(sample)
except RuntimeError:
pytest.skip(reason="Test must be ran against sample loaded in Ghidra")
fixtures.do_test_feature_count(fixtures.get_ghidra_extractor, sample, scope, feature, expected)
if __name__ == "__main__":
# No support for faulthandler module in Ghidrathon, see:
# https://github.com/mandiant/Ghidrathon/issues/70
sys.exit(pytest.main(["--pyargs", "-p no:faulthandler", "test_ghidra_features"]))