|
18 | 18 | # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
19 | 19 | # IN THE SOFTWARE. |
20 | 20 |
|
21 | | -from typing import Optional, Union, Any |
| 21 | +from typing import Optional, Union, Any, Dict |
22 | 22 | from dataclasses import dataclass |
23 | 23 | import ctypes |
24 | 24 |
|
@@ -198,6 +198,8 @@ def register(self): |
198 | 198 | if self.recognize_constant_data.__func__ != StringRecognizer.recognize_constant_data: |
199 | 199 | self._cb.recognizeConstantData = self._cb.recognizeConstantData.__class__( |
200 | 200 | self._recognize_constant_data) |
| 201 | + if self.recognize_struct_init.__func__ != StringRecognizer.recognize_struct_init: |
| 202 | + self._cb.recognizeStructInit = self._cb.recognizeStructInit.__class__(self._recognize_struct_init) |
201 | 203 | self.handle = core.BNRegisterStringRecognizer(self.__class__.recognizer_name, self._cb) |
202 | 204 | self.__class__._registered_recognizers.append(self) |
203 | 205 |
|
@@ -279,6 +281,21 @@ def _recognize_constant_data(self, ctxt, hlil, expr, result): |
279 | 281 | log_error_for_exception("Unhandled Python exception in StringRecognizer._recognize_constant_data") |
280 | 282 | return False |
281 | 283 |
|
| 284 | + def _recognize_struct_init(self, ctxt, hlil, expr, type, field_offsets, field_values, field_count, result): |
| 285 | + try: |
| 286 | + hlil = highlevelil.HighLevelILFunction(handle=core.BNNewHighLevelILFunctionReference(hlil)) |
| 287 | + type = types.Type.create(handle=core.BNNewTypeReference(type)) |
| 288 | + instr = hlil.get_expr(highlevelil.ExpressionIndex(expr)) |
| 289 | + vals = {field_offsets[i]: field_values[i] for i in range(field_count)} |
| 290 | + ref = self.recognize_struct_init(instr, type, vals) |
| 291 | + if ref is None: |
| 292 | + return False |
| 293 | + result[0] = ref._to_core_struct(True) |
| 294 | + return True |
| 295 | + except Exception: |
| 296 | + log_error_for_exception("Unhandled Python exception in StringRecognizer._recognize_struct_init") |
| 297 | + return False |
| 298 | + |
282 | 299 | @property |
283 | 300 | def name(self) -> str: |
284 | 301 | if hasattr(self, 'handle'): |
@@ -379,6 +396,25 @@ def recognize_constant_data( |
379 | 396 | """ |
380 | 397 | return None |
381 | 398 |
|
| 399 | + def recognize_struct_init( |
| 400 | + self, instr: 'highlevelil.HighLevelILInstruction', type: 'types.Type', vals: Dict[int, int] |
| 401 | + ) -> Optional['binaryview.DerivedString']: |
| 402 | + """ |
| 403 | + Can be overridden to recognize strings for a structure initializer expression (HLIL_STRUCT_INIT). |
| 404 | + These are produced when the optimizer folds a run of structure field assignments into a single |
| 405 | + initializer. This is only called when all fields of the structure are assigned constants. |
| 406 | + The ``vals`` dictionary maps each field's byte offset within the structure to the constant value |
| 407 | + assigned to that field. If no string is found, this method should return `None`. |
| 408 | +
|
| 409 | + If a string is found, return a :py:class:`~binaryninja.binaryview.DerivedString` with the string information. |
| 410 | +
|
| 411 | + :param instr: High level structure initializer expression |
| 412 | + :param type: Structure type of the initializer |
| 413 | + :param vals: Dictionary mapping field offset to the constant value assigned to that field |
| 414 | + :return: Optional :py:class:`~binaryninja.binaryview.DerivedString` for any string that is found. |
| 415 | + """ |
| 416 | + return None |
| 417 | + |
382 | 418 |
|
383 | 419 | _recognizer_cache = {} |
384 | 420 |
|
@@ -442,3 +478,17 @@ def recognize_constant_data( |
442 | 478 | if not core.BNStringRecognizerRecognizeConstantData(self.handle, instr.function.handle, instr.expr_index, string): |
443 | 479 | return None |
444 | 480 | return binaryview.DerivedString._from_core_struct(string, True) |
| 481 | + |
| 482 | + def recognize_struct_init( |
| 483 | + self, instr: 'highlevelil.HighLevelILInstruction', type: 'types.Type', vals: Dict[int, int] |
| 484 | + ) -> Optional['binaryview.DerivedString']: |
| 485 | + count = len(vals) |
| 486 | + field_offsets = (ctypes.c_ulonglong * count)() |
| 487 | + field_values = (ctypes.c_longlong * count)() |
| 488 | + for i, (offset, value) in enumerate(vals.items()): |
| 489 | + field_offsets[i] = offset |
| 490 | + field_values[i] = value |
| 491 | + string = core.BNDerivedString() |
| 492 | + if not core.BNStringRecognizerRecognizeStructInit(self.handle, instr.function.handle, instr.expr_index, type.handle, field_offsets, field_values, count, string): |
| 493 | + return None |
| 494 | + return binaryview.DerivedString._from_core_struct(string, True) |
0 commit comments