diff options
| author | Brian Potchik <brian@vector35.com> | 2024-03-14 12:43:05 -0400 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2024-03-14 12:43:05 -0400 |
| commit | 6e04c943e75ebdfbc6e940d0aa3d88a54b4c264b (patch) | |
| tree | b47ffcdaacba453fe39de077f914f4000f732a67 | |
| parent | bf8b662124aeb1cf6e79045b3d4de3fd1cdd89a8 (diff) | |
Add support for advanced binary search.
| -rw-r--r-- | binaryninjaapi.h | 5 | ||||
| -rw-r--r-- | binaryninjacore.h | 5 | ||||
| -rw-r--r-- | binaryview.cpp | 8 | ||||
| -rw-r--r-- | python/binaryview.py | 42 |
4 files changed, 59 insertions, 1 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 741f399d..bf9bd9f6 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -6136,6 +6136,8 @@ namespace BinaryNinja { BNFunctionGraphType graph, const std::function<bool(size_t current, size_t total)>& progress, const std::function<bool(uint64_t addr, const LinearDisassemblyLine& line)>& matchCallback); + bool Search(const std::string& query, const std::function<bool(uint64_t offset, const DataBuffer& buffer)>& otherCallback); + void Reanalyze(); Ref<Workflow> GetWorkflow() const; @@ -16071,6 +16073,9 @@ namespace BinaryNinja { std::string string; BNFindFlag flags; bool findAll; + bool advancedSearch; + bool overlap; + int alignment; uint64_t findConstant; DataBuffer findBuffer; diff --git a/binaryninjacore.h b/binaryninjacore.h index d5fcdcce..3e26db68 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,7 +37,7 @@ // Current ABI version for linking to the core. This is incremented any time // there are changes to the API that affect linking, including new functions, // new types, or modifications to existing functions or types. -#define BN_CURRENT_CORE_ABI_VERSION 55 +#define BN_CURRENT_CORE_ABI_VERSION 56 // Minimum ABI version that is supported for loading of plugins. Plugins that // are linked to an ABI version less than this will not be able to load and @@ -3716,6 +3716,9 @@ extern "C" bool (*progress)(void* ctxt, size_t current, size_t total), void* matchCtxt, bool (*matchCallback)(void* matchCtxt, uint64_t addr, BNLinearDisassemblyLine* line)); + BINARYNINJACOREAPI bool BNSearch(BNBinaryView* view, const char* query, void* context, bool (*callback)(void*, uint64_t, BNDataBuffer*)); + BINARYNINJACOREAPI bool BNPerformSearch(const char* query, const uint8_t* buffer, size_t size, bool(*callback)(void*, size_t, size_t), void* context); + BINARYNINJACOREAPI void BNAddAutoSegment( BNBinaryView* view, uint64_t start, uint64_t length, uint64_t dataOffset, uint64_t dataLength, uint32_t flags); BINARYNINJACOREAPI void BNRemoveAutoSegment(BNBinaryView* view, uint64_t start, uint64_t length); diff --git a/binaryview.cpp b/binaryview.cpp index 0dd6d8f8..feb3b765 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -4610,6 +4610,14 @@ bool BinaryView::FindAllConstant(uint64_t start, uint64_t end, uint64_t constant } +bool BinaryView::Search(const string& query, const std::function<bool(uint64_t offset, const DataBuffer& buffer)>& otherCallback) +{ + MatchCallbackContextForDataBuffer mc; + mc.func = otherCallback; + return BNSearch(m_object, query.c_str(), &mc, MatchCallbackForDataBuffer); +} + + void BinaryView::Reanalyze() { BNReanalyzeAllFunctions(m_object); diff --git a/python/binaryview.py b/python/binaryview.py index 70eef953..9dbb3e4d 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -8571,6 +8571,48 @@ class BinaryView: return self.QueueGenerator(t, results) + def search(self, pattern: str, start: int = None, end: int = None, raw: bool = False, ignore_case: bool = False, overlap: bool = False, align: int = 1) -> QueueGenerator: + """ + Searches for matches of the specified `pattern` within this BinaryView with an optionally provided address range specified by `start` and `end`. + The search pattern can be interpreted in various ways: + - specified as a string of hexadecimal digits where whitespace is ignored, and the '?' character acts as a wildcard + - a regular expression suitable for working with bytes + - or if the `raw` option is enabled, the pattern is interpreted as a raw string, and any special characters are escaped and interpreted literally + + :param str pattern: The pattern to search for. + :param int start: The address to start the search from. (default: None) + :param int end: The address to end the search (inclusive). (default: None) + :param bool raw: Whether to interpret the pattern as a raw string (default: False). + :param bool ignore_case: Whether to perform case-insensitive matching (default: False). + :param bool overlap: Whether to allow matches to overlap (default: False). + :param int align: The alignment of matches, must be a power of 2 (default: 1). + + :return: A generator object that yields the offset and matched DataBuffer for each match found. + :rtype: QueueGenerator + """ + if start is None: + start = self.start + if end is None: + end = self.end + if end != 0xffffffffffffffff: + end = end - 1 + if start > end: + raise ValueError("The start address must be less than or equal to end address!") + query = { + "pattern": pattern, + "start": start, + "end": end, + "raw": raw, + "ignoreCase": ignore_case, + "overlap": overlap, + "align": align + } + results = queue.Queue() + match_callback_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.POINTER(core.BNDataBuffer) + )(lambda ctxt, offset, match: results.put((offset, databuffer.DataBuffer(handle=match))) or True) + t = threading.Thread(target=lambda: core.BNSearch(self.handle, json.dumps(query), None, match_callback_obj)) + return self.QueueGenerator(t, results) + def reanalyze(self) -> None: """ ``reanalyze`` causes all functions to be reanalyzed. This function does not wait for the analysis to finish. |
