summaryrefslogtreecommitdiff
path: root/view/sharedcache/api/python/sharedcache.py
diff options
context:
space:
mode:
authorkat <kat@vector35.com>2025-03-18 03:25:27 -0400
committerkat <kat@vector35.com>2025-03-18 03:57:05 -0400
commit1bbb0e1dd640abe0278bf5bf947f9ae453f25373 (patch)
treebd2939499e7197efd486dab3c813138875273ee5 /view/sharedcache/api/python/sharedcache.py
parentc00bf1a9dd87769bb9a85f46fcdb90e176eda1e8 (diff)
Documentation and type hints for sharedcache.py, properly import binaryninja.sharedcache automatically
Diffstat (limited to 'view/sharedcache/api/python/sharedcache.py')
-rw-r--r--view/sharedcache/api/python/sharedcache.py174
1 files changed, 148 insertions, 26 deletions
diff --git a/view/sharedcache/api/python/sharedcache.py b/view/sharedcache/api/python/sharedcache.py
index e3ccbb9b..dab5583e 100644
--- a/view/sharedcache/api/python/sharedcache.py
+++ b/view/sharedcache/api/python/sharedcache.py
@@ -59,14 +59,14 @@ class DSCBackingCache:
return repr(self)
def __repr__(self):
- match self.cacheType:
- case BackingCacheType.BackingCacheTypePrimary:
- cacheTypeStr = 'Primary'
- case BackingCacheType.BackingCacheTypeSecondary:
- cacheTypeStr = 'Secondary'
- case BackingCacheType.BackingCacheTypeSymbols:
- cacheTypeStr = 'Symbols'
- return f"<DSCBackingCache {self.path} {cacheTypeStr} | {len(self.mappings)} mappings>"
+ cache_type_str = 'Unknown'
+ if self.cacheType == BackingCacheType.BackingCacheTypePrimary:
+ cache_type_str = 'Primary'
+ elif self.cacheType == BackingCacheType.BackingCacheTypeSecondary:
+ cache_type_str = 'Secondary'
+ elif self.cacheType == BackingCacheType.BackingCacheTypeSymbols:
+ cache_type_str = 'Symbols'
+ return f"<DSCBackingCache {self.path} {cache_type_str} | {len(self.mappings)} mappings>"
@dataclasses.dataclass
@@ -112,26 +112,75 @@ class DSCSymbol:
class SharedCache:
+ """
+ SharedCache is the primary class for interacting with the shared cache processor and DSCView metadata.
+
+ You can create a SharedCache object from a BinaryView object by calling `SharedCache(bv)`, where `bv` is the BinaryView.
+
+ By default `bv` in the console will return the instance of the BinaryView that is currently open, \
+ so in the UI, you can use `dsc = SharedCache(bv)` to create a SharedCache object in the scripting console.
+
+ Methods and attributes in this class have documentation which can be viewed by typing `SharedCache.method_or_attribute_name?` in the console.
+ """
def __init__(self, view):
self.handle = sccore.BNGetSharedCache(view.handle)
- def load_image_with_install_name(self, installName, skipObjC = False):
- return sccore.BNDSCViewLoadImageWithInstallName(self.handle, installName, skipObjC)
+ def load_image_with_install_name(self, install_name, skip_loading_objective_c = False) -> bool:
+ """
+ Locate an image with the provided install name and load it into the shared cache view
+
+ :param install_name: Install name of the image
+ :param skip_loading_objective_c: Whether to skip process Objective-C information for this image. Default false.
+ :return:
+ """
+ return sccore.BNDSCViewLoadImageWithInstallName(self.handle, install_name, skip_loading_objective_c)
+
+ def load_section_at_address(self, addr) -> bool:
+ """
+ Load a singular section at the provided address into the shared cache view.
+
+ This will partial-load the image, only mapping the requested segment containing this section.
- def load_section_at_address(self, addr):
+ Image info will still be processed, but will only be applied to mapped regions.
+
+ :param addr: Address within the section
+ :return:
+ """
return sccore.BNDSCViewLoadSectionAtAddress(self.handle, addr)
- def load_image_containing_address(self, addr, skipObjC = False):
- return sccore.BNDSCViewLoadImageContainingAddress(self.handle, addr, skipObjC)
+ def load_image_containing_address(self, addr, skip_loading_objective_c = False) -> bool:
+ """
+ Load the image containing the provided address into the shared cache view.
+
+ :param addr: Address within the image to load
+ :param skip_loading_objective_c: Whether to skip processing Objective-C information for this image. Default false.
+ :return:
+ """
+ return sccore.BNDSCViewLoadImageContainingAddress(self.handle, addr, skip_loading_objective_c)
+
+ def process_objc_sections_for_image_with_install_name(self, install_name) -> bool:
+ """
+ Process Objective-C information for the image with the provided install name.
+
+ :param install_name: Install name of the image
+ :return:
+ """
+ return sccore.BNDSCViewProcessObjCSectionsForImageWithInstallName(self.handle, install_name, False)
- def process_objc_sections_for_image_with_install_name(self, installName):
- return sccore.BNDSCViewProcessObjCSectionsForImageWithInstallName(self.handle, installName, False)
+ def process_all_objc_sections(self) -> bool:
+ """
+ Process Objective-C information for all images in the shared cache view.
- def process_all_objc_sections(self):
+ :return:
+ """
return sccore.BNDSCViewProcessAllObjCSections(self.handle)
@property
- def caches(self):
+ def caches(self) -> list[DSCBackingCache]:
+ """
+ Get all backing caches in the shared cache.
+ :return:
+ """
count = ctypes.c_ulonglong()
value = sccore.BNDSCViewGetBackingCaches(self.handle, count)
if value is None:
@@ -157,7 +206,11 @@ class SharedCache:
return result
@property
- def images(self):
+ def images(self) -> list[DSCImage]:
+ """
+ Get all images in the shared cache
+ :return:
+ """
count = ctypes.c_ulonglong()
value = sccore.BNDSCViewGetAllImages(self.handle, count)
if value is None:
@@ -186,7 +239,7 @@ class SharedCache:
return result
@property
- def loaded_regions(self):
+ def loaded_regions(self) -> list[LoadedRegion]:
"""
Get all loaded regions in the shared cache
@@ -214,7 +267,23 @@ class SharedCache:
sccore.BNDSCViewFreeLoadedRegions(value, count)
return result
- def load_all_symbols_and_wait(self):
+ def load_all_symbols_and_wait(self) -> list[DSCSymbol]:
+ """
+ Load all symbols in the shared cache. This will block on the current thread waiting for processing to finish.
+
+ While all functions in this API are synchronous, this function can be particularly slow due to the large number
+ of symbols in the shared cache. "and_wait" is appended to the function name to indicate that this function
+ will block until processing is complete, and for performant applications, you should consider calling this
+ function in a separate thread and waiting on its return. An example of this is provided in the shared cache
+ triage view.
+
+ This may take several seconds if this is the first time this function is called. Subsequent calls will be faster.
+
+ In UI-based API usage, it is likely that the triage view will have already performed this operation, and calls
+ to this function will be much faster.
+
+ :return: A list of all symbols in the shared cache
+ """
count = ctypes.c_ulonglong()
value = sccore.BNDSCViewLoadAllSymbolsAndWait(self.handle, count)
if value is None:
@@ -232,7 +301,11 @@ class SharedCache:
return result
@property
- def image_names(self):
+ def image_names(self) -> list[str]:
+ """
+ Get all image names in the shared cache
+ :return:
+ """
count = ctypes.c_ulonglong()
value = sccore.BNDSCViewGetInstallNames(self.handle, count)
if value is None:
@@ -246,22 +319,71 @@ class SharedCache:
return result
@property
- def state(self):
+ def state(self) -> DSCViewState:
+ """
+ Get the current image state of the shared cache view. Useful for checking if images have been loaded yet or not.
+ :return:
+ """
return DSCViewState(sccore.BNDSCViewGetState(self.handle))
- def get_name_for_address(self, address):
+ def get_name_for_address(self, address) -> str:
+ """
+ Get the "name" for the provided address. Specifically, the name of the memory region this address lies in.
+
+ If this lies within an image segment, this will be in the format image_name + "::" + segment_name.
+
+ It may also be the name of a branch pool or other non-image region.
+
+ This is the API call utilized on the first dynamic entry in the right-click context menu.
+
+ :param address: address to check
+ :return:
+ """
name = sccore.BNDSCViewGetNameForAddress(self.handle, address)
if name is None:
return ""
result = name
return result
- def get_image_name_for_address(self, address):
+ def get_image_name_for_address(self, address) -> str:
+ """
+ Return the install name for the image containing the provided address.
+
+ If the address is not within an image, this will return an empty string.
+
+ This is the API call used in the second dynamic entry in the right-click context menu.
+
+ :param address: address to check
+ :return:
+ """
name = sccore.BNDSCViewGetImageNameForAddress(self.handle, address)
if name is None:
return ""
result = name
return result
- def find_symbol_at_addr_and_apply_to_addr(self, symbolAddress, targetAddress, triggerReanalysis) -> None:
- sccore.BNDSCFindSymbolAtAddressAndApplyToAddress(self.handle, symbolAddress, targetAddress, triggerReanalysis)
+ def find_symbol_at_addr_and_apply_to_addr(self, symbol_address, target_address, trigger_reanalysis) -> None:
+ """
+ This is primarily a function utilized for automated backwards symbol propagation for stubs in the workflow, however
+ it is passed through here as well in the event you need to use it to do something similar, or want to create
+ your own version of the workflow.
+
+ This is currently a blocking function.
+
+ This will check the cache for a symbol located at symbol_address, and apply it to target_address, appending a
+ `j_` to the front of the symbol name copy at `target_address`.
+
+ It will additionally backwards-propagate type information that was specifically applied via TypeLibrary to the stub.
+
+ This includes calling conventions and can be seen in stubs pointing to objc_release_x[register] functions.
+
+ This check will not run if:
+ - The symbol address and target address are the same
+ - The target address has already been given a name by this function
+
+ :param symbol_address: Symbol address to check
+ :param target_address: Target address to apply symbol name and type to
+ :param trigger_reanalysis: Whether to reanalyze the function at target_address if the function already existed.
+ :return: None
+ """
+ sccore.BNDSCFindSymbolAtAddressAndApplyToAddress(self.handle, symbol_address, target_address, trigger_reanalysis)