diff options
| author | Brandon Miller <brandon@vector35.com> | 2024-04-19 16:38:01 -0400 |
|---|---|---|
| committer | Brandon Miller <bkmiller89@icloud.com> | 2024-04-30 10:17:45 -0400 |
| commit | fa38503c09bfbb95404f6fc1993756a855d5c5d1 (patch) | |
| tree | 0cb886808cdc99d553b34491cdc88462f9bc15d6 /python | |
| parent | 5fdf81a051ec363c009bc6ae1811e3cba7d56af3 (diff) | |
Querying base detection reasons from Python API
Diffstat (limited to 'python')
| -rw-r--r-- | python/basedetection.py | 125 |
1 files changed, 81 insertions, 44 deletions
diff --git a/python/basedetection.py b/python/basedetection.py index ac12c92c..e8a1ef95 100644 --- a/python/basedetection.py +++ b/python/basedetection.py @@ -21,15 +21,26 @@ import ctypes from typing import Optional +from dataclasses import dataclass from . import _binaryninjacore as core +@dataclass +class BaseAddressDetectionReason: + """``class BaseAddressDetectionReason`` is a class that is used to store information about why a base address is a + candidate""" + + pointer: int + offset: int + type: int + + class BaseAddressDetection: """ ``class BaseAddressDetection`` is a class that is used to detect the base address of position-dependent raw binaries >>> from binaryninja import * - >>> bv = load("firmware.bin") + >>> bv = BinaryViewType["Raw"].open("firmware.bin") >>> bad = BaseAddressDetection(bv) >>> bad.detect_base_address() True @@ -51,6 +62,53 @@ class BaseAddressDetection: if core is not None: core.BNFreeBaseAddressDetection(self._handle) + @property + def scores(self) -> list[tuple[int, int]]: + """ + ``scores`` returns a list of base addresses and their scores + + :return: list of tuples containing each base address and score + :rtype: OrderedDict + """ + + return self._scores + + @property + def confidence(self) -> "BaseAddressDetectionConfidenceEnum": + """ + ``confidence`` returns an enum that indicates confidence that the top base address candidate is correct + + :return: confidence of the base address detection results + :rtype: BaseAddressDetectionConfidenceEnum + """ + + return self._confidence + + @property + def last_tested_base_address(self) -> int: + """ + ``last_tested_base_address`` returns the last base address candidate that was tested + + :return: last base address tested + :rtype: int + """ + + return self._last_tested_base_address + + @property + def preferred_base_address(self) -> int: + """ + ``preferred_base_address`` returns the base address that is preferred by analysis + + :return: preferred base address + :rtype: int + """ + + if not self._scores: + return None + + return self._scores[0][0] + def detect_base_address( self, arch: Optional[str] = "", @@ -85,8 +143,14 @@ class BaseAddressDetection: raise ValueError("upper boundary must be greater than lower boundary") settings = core.BNBaseAddressDetectionSettings( - arch.encode('utf-8'), analysis.encode('utf-8'), minstrlen, alignment, lowerboundary, upperboundary, - poi_analysis, max_pointers + arch.encode(), + analysis.encode(), + minstrlen, + alignment, + lowerboundary, + upperboundary, + poi_analysis, + max_pointers, ) if not core.BNDetectBaseAddress(self._handle, settings): @@ -108,49 +172,22 @@ class BaseAddressDetection: self._last_tested_base_address = last_base.value return True - @property - def scores(self) -> list[tuple[int, int]]: - """ - ``get_scores`` returns a list of base addresses and their scores - - :return: list of tuples containing each base address and score - :rtype: OrderedDict - """ - - return self._scores - - @property - def confidence(self) -> "BaseAddressDetectionConfidenceEnum": + def get_reasons_for_base_address(self, base_address: int) -> list[BaseAddressDetectionReason]: """ - ``get_confidence`` returns an enum that indicates confidence that the top base address candidate is correct + ``get_reasons_for_base_address`` returns a list of reasons why the specified base address is a candidate - :return: confidence of the base address detection results - :rtype: BaseAddressDetectionConfidenceEnum + :param int base_address: base address to get reasons for + :return: list of reasons for the specified base address + :rtype: list """ - return self._confidence + count = ctypes.c_size_t() + reasons = core.BNGetBaseAddressDetectionReasons(self._handle, base_address, ctypes.byref(count)) + if count.value == 0: + return [] - @property - def last_tested_base_address(self) -> int: - """ - ``last_tested_base_address`` returns the last base address candidate that was tested - - :return: last base address tested - :rtype: int - """ - - return self._last_tested_base_address - - @property - def preferred_base_address(self) -> int: - """ - ``preferred_base_address`` returns the base address that is preferred by analysis - - :return: preferred base address - :rtype: int - """ - - if not self._scores: - return None - - return self._scores[0][0] + result = list() + for i in range(count.value): + result.append(BaseAddressDetectionReason(reasons[i].Pointer, reasons[i].POIOffset, reasons[i].POIType)) + core.BNFreeBaseAddressDetectionReasons(reasons) + return result |
