summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorBrian Potchik <brian@vector35.com>2026-04-17 12:10:07 -0400
committerBrian Potchik <brian@vector35.com>2026-04-17 12:10:07 -0400
commitbfd306437f34ebc4d4170c5fb8170261585f6038 (patch)
tree36dd320d130fa23239213dd94546abb9a5ab4114 /python
parent424dc721f5f2a3a7ffd5a6ccbcc7320b5ae7496d (diff)
Add RecognizeConstantData to StringRecognizer API
Adds a new recognize_constant_data method to the StringRecognizer API, enabling plugins to decode constant data expressions (HLIL_CONST_DATA) recovered by the outline resolver. The recognizer receives the full instruction, giving access to the data buffer and builtin type via the constant_data accessor. Also fixes a pre-existing ctypes mismatch in get_constant_data_and_builtin where BNBuiltinType (uint8_t) was incorrectly passed as c_int.
Diffstat (limited to 'python')
-rw-r--r--python/function.py2
-rw-r--r--python/stringrecognizer.py40
2 files changed, 41 insertions, 1 deletions
diff --git a/python/function.py b/python/function.py
index 93eb7d15..bc8def47 100644
--- a/python/function.py
+++ b/python/function.py
@@ -1938,7 +1938,7 @@ class Function:
def get_constant_data_and_builtin(
self, state: RegisterValueType, value: int, size: int = 0
) -> Tuple[databuffer.DataBuffer, BuiltinType]:
- builtin = ctypes.c_int()
+ builtin = ctypes.c_ubyte()
db = databuffer.DataBuffer(
handle=core.BNGetConstantData(self.handle, state, value, size, ctypes.byref(builtin)))
return db, BuiltinType(builtin.value)
diff --git a/python/stringrecognizer.py b/python/stringrecognizer.py
index 055e236d..bdf9423a 100644
--- a/python/stringrecognizer.py
+++ b/python/stringrecognizer.py
@@ -195,6 +195,9 @@ class StringRecognizer(metaclass=_StringRecognizerMetaClass):
self._cb.recognizeExternPointer = self._cb.recognizeExternPointer.__class__(self._recognize_extern_pointer)
if self.recognize_import.__func__ != StringRecognizer.recognize_import:
self._cb.recognizeImport = self._cb.recognizeImport.__class__(self._recognize_import)
+ if self.recognize_constant_data.__func__ != StringRecognizer.recognize_constant_data:
+ self._cb.recognizeConstantData = self._cb.recognizeConstantData.__class__(
+ self._recognize_constant_data)
self.handle = core.BNRegisterStringRecognizer(self.__class__.recognizer_name, self._cb)
self.__class__._registered_recognizers.append(self)
@@ -263,6 +266,19 @@ class StringRecognizer(metaclass=_StringRecognizerMetaClass):
log_error_for_exception("Unhandled Python exception in StringRecognizer._recognize_import")
return False
+ def _recognize_constant_data(self, ctxt, hlil, expr, result):
+ try:
+ hlil = highlevelil.HighLevelILFunction(handle=core.BNNewHighLevelILFunctionReference(hlil))
+ instr = hlil.get_expr(highlevelil.ExpressionIndex(expr))
+ ref = self.recognize_constant_data(instr)
+ if ref is None:
+ return False
+ result[0] = ref._to_core_struct(True)
+ return True
+ except Exception:
+ log_error_for_exception("Unhandled Python exception in StringRecognizer._recognize_constant_data")
+ return False
+
@property
def name(self) -> str:
if hasattr(self, 'handle'):
@@ -347,6 +363,22 @@ class StringRecognizer(metaclass=_StringRecognizerMetaClass):
"""
return None
+ def recognize_constant_data(
+ self, instr: 'highlevelil.HighLevelILInstruction'
+ ) -> Optional['binaryview.DerivedString']:
+ """
+ Can be overridden to recognize strings for constant data expressions (HLIL_CONST_DATA).
+ These expressions are generated by the outline resolver when it recovers constant data
+ streams from scattered stores. The instruction provides access to the data buffer and
+ builtin type via its ``constant_data`` accessor.
+
+ If a string is found, return a :py:class:`~binaryninja.binaryview.DerivedString` with the string information.
+
+ :param instr: High level expression containing the constant data
+ :return: Optional :py:class:`~binaryninja.binaryview.DerivedString` for any string that is found.
+ """
+ return None
+
_recognizer_cache = {}
@@ -402,3 +434,11 @@ class CoreStringRecognizer(StringRecognizer):
if not core.BNStringRecognizerRecognizeImport(self.handle, instr.function.handle, instr.expr_index, type.handle, val, string):
return None
return binaryview.DerivedString._from_core_struct(string, True)
+
+ def recognize_constant_data(
+ self, instr: 'highlevelil.HighLevelILInstruction'
+ ) -> Optional['binaryview.DerivedString']:
+ string = core.BNDerivedString()
+ if not core.BNStringRecognizerRecognizeConstantData(self.handle, instr.function.handle, instr.expr_index, string):
+ return None
+ return binaryview.DerivedString._from_core_struct(string, True)