From ecfc518d025359e7d2cf7e5da30f856916bf48b4 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 12 Jan 2024 16:55:19 -0500 Subject: Add APIs for getting the the base Metadata object for BinaryViews and TypeLibraries --- python/binaryview.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ python/metadata.py | 8 ++++++- python/typelibrary.py | 20 +++++++++++++++++- 3 files changed, 84 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/binaryview.py b/python/binaryview.py index 2446f04f..0c475445 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -7458,6 +7458,30 @@ class BinaryView: return None return _types.Type.create(handle, platform=self.platform) + def import_com_type_for_guid(self, guid: Union[str, uuid.UUID]) -> Optional['_types.Type']: + """ + ``import_com_type_for_guid`` recursively imports a com interface given its GUID. + + .. note:: This method is only available on Windows. + + :param str guid: GUID of the COM interface to import + :return: the object type, with any interior `NamedTypeReferences` renamed as necessary to be appropriate for the current view + :rtype: Type + """ + if not isinstance(guid, str): + guid = str(guid) + + tl = self.get_type_library("win32common") + if tl is None: + return None + + type_name = tl.metadata.get("com_interface_guids", {}) + assert isinstance(type_name, dict) + type_name = type_name.get(guid, None) + if type_name is None: + return None + return self.import_library_type(type_name, tl) + def import_library_object(self, name: str, lib: Optional[typelibrary.TypeLibrary] = None) -> Optional['_types.Type']: """ ``import_library_object`` recursively imports an object from the specified type library, or, if \ @@ -8463,6 +8487,40 @@ class BinaryView: """ core.BNBinaryViewRemoveMetadata(self.handle, key) + @property + def metadata(self) -> Dict[str, 'metadata.MetadataValueType']: + """ + `metadata` retrieves the metadata associated with the current BinaryView. + + :rtype: metadata associated with the BinaryView + :Example: + + >>> bv.metadata + + """ + md_handle = core.BNBinaryViewGetMetadata(self.handle) + assert md_handle is not None, "core.BNBinaryViewGetMetadata returned None" + value = metadata.Metadata(handle=md_handle).value + assert isinstance(value, dict), "core.BNBinaryViewGetMetadata did not return a dict" + return value + + @property + def auto_metadata(self) -> Dict[str, 'metadata.MetadataValueType']: + """ + `metadata` retrieves the metadata associated with the current BinaryView. + + :rtype: metadata associated with the BinaryView + :Example: + + >>> bv.metadata + + """ + md_handle = core.BNBinaryViewGetAutoMetadata(self.handle) + assert md_handle is not None, "core.BNBinaryViewGetAutoMetadata returned None" + value = metadata.Metadata(handle=md_handle).value + assert isinstance(value, dict), "core.BNBinaryViewGetAutoMetadata did not return a dict" + return value + def get_load_settings_type_names(self) -> List[str]: """ ``get_load_settings_type_names`` retrieve a list :py:class:`BinaryViewType` names for which load settings exist in \ diff --git a/python/metadata.py b/python/metadata.py index e2483749..e87c5cbb 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -19,7 +19,7 @@ # IN THE SOFTWARE. import ctypes -from typing import Union, Optional, List, Tuple +from typing import Union, Optional, List, Tuple, Any # Binary Ninja components from . import _binaryninjacore as core @@ -184,6 +184,12 @@ class Metadata: raise ValueError("Metadata object is not boolean type") return core.BNMetadataGetBoolean(self.handle) + def get(self, key:str, default:Any=None) -> Any: + try: + return self[key] + except (KeyError, IndexError, ValueError, NotImplementedError): + return default + @property def value(self): if self.is_integer: diff --git a/python/typelibrary.py b/python/typelibrary.py index db22ee22..c9ddd37b 100644 --- a/python/typelibrary.py +++ b/python/typelibrary.py @@ -20,6 +20,7 @@ import ctypes from typing import Optional, List, Dict, Union +import uuid # Binary Ninja components import binaryninja @@ -282,6 +283,24 @@ class TypeLibrary: """ core.BNTypeLibraryRemoveMetadata(self.handle, key) + @property + def metadata(self) -> Dict[str, 'metadata.MetadataValueType']: + """ + `metadata` retrieves the metadata associated with the current type library. + + :rtype: Metadata object + :Example: + + >>> lib.store_metadata("integer", 1337) + >>> lib.metadata["integer"] + 1337 + """ + md_handle = core.BNTypeLibraryGetMetadata(self.handle) + assert md_handle is not None, "core.BNTypeLibraryGetMetadata returned None" + value = metadata.Metadata(handle=md_handle).value + assert isinstance(value, dict), "core.BNTypeLibraryGetMetadata returned non-dict" + return value + @property def type_container(self) -> 'typecontainer.TypeContainer': """ @@ -407,4 +426,3 @@ class TypeLibrary: return result finally: core.BNFreeQualifiedNameAndTypeArray(named_types, count.value) - -- cgit v1.3.1