summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Potchik <brian@vector35.com>2024-03-14 12:43:05 -0400
committerBrian Potchik <brian@vector35.com>2024-03-14 12:43:05 -0400
commit6e04c943e75ebdfbc6e940d0aa3d88a54b4c264b (patch)
treeb47ffcdaacba453fe39de077f914f4000f732a67
parentbf8b662124aeb1cf6e79045b3d4de3fd1cdd89a8 (diff)
Add support for advanced binary search.
-rw-r--r--binaryninjaapi.h5
-rw-r--r--binaryninjacore.h5
-rw-r--r--binaryview.cpp8
-rw-r--r--python/binaryview.py42
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.