diff options
| author | kat <kat@vector35.com> | 2023-01-03 14:29:32 -0500 |
|---|---|---|
| committer | kat <kat@vector35.com> | 2023-02-20 13:23:31 -0500 |
| commit | fcfa33a14fc309984880b535b9f9b4fcfc316466 (patch) | |
| tree | 0d2b1c62e9939d357a508a446f440541709625e4 | |
| parent | 982d90f20e400c7fe7b254eee31fe7eca4e11c2c (diff) | |
Allow DataVariables to be added to Components
| -rw-r--r-- | binaryninjaapi.h | 43 | ||||
| -rw-r--r-- | binaryninjacore.h | 25 | ||||
| -rw-r--r-- | binaryview.cpp | 66 | ||||
| -rw-r--r-- | component.cpp | 33 | ||||
| -rw-r--r-- | function.cpp | 18 | ||||
| -rw-r--r-- | python/binaryview.py | 53 | ||||
| -rw-r--r-- | python/component.py | 108 | ||||
| -rw-r--r-- | python/function.py | 9 |
8 files changed, 273 insertions, 82 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 34a45160..a364e5d9 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2017,7 +2017,8 @@ namespace BinaryNinja { void* ctxt, BNBinaryView* data, BNComponent* formerParent, BNComponent* newParent, BNComponent* component); static void ComponentFunctionAddedCallback(void* ctxt, BNBinaryView* data, BNComponent* component, BNFunction* function); static void ComponentFunctionRemovedCallback(void* ctxt, BNBinaryView* data, BNComponent* component, BNFunction* function); - + static void ComponentDataVariableAddedCallback(void* ctxt, BNBinaryView* data, BNComponent* component, BNDataVariable* var); + static void ComponentDataVariableRemovedCallback(void* ctxt, BNBinaryView* data, BNComponent* component, BNDataVariable* var); public: BinaryDataNotification(); @@ -2271,6 +2272,32 @@ namespace BinaryNinja { (void)component; (void)function; } + + /*! This notification is posted whenever a DataVariable is added to a Component + + \param data BinaryView containing the Component and DataVariable + \param component Component the DataVariable was added to + \param var The DataVariable which was added + */ + virtual void OnComponentDataVariableAdded(BinaryView* data, Component* component, const DataVariable& var) + { + (void)data; + (void)component; + (void)var; + } + + /*! This notification is posted whenever a DataVariable is removed from a Component + + \param data BinaryView containing the Component and DataVariable + \param component Component the DataVariable was removed from + \param var The DataVariable which was removed + */ + virtual void OnComponentDataVariableRemoved(BinaryView* data, Component* component, const DataVariable& var) + { + (void)data; + (void)component; + (void)var; + } }; /*! @@ -4279,6 +4306,9 @@ namespace BinaryNinja { */ bool RemoveComponent(std::string guid); + std::vector<Ref<Component>> GetFunctionParentComponents(Ref<Function> function) const; + std::vector<Ref<Component>> GetDataVariableParentComponents(DataVariable var) const; + /*! Check whether the given architecture supports assembling instructions \param arch Architecture to check @@ -8483,7 +8513,6 @@ namespace BinaryNinja { \return Whether this function needs update */ bool NeedsUpdate() const; - std::vector<Ref<Component>> GetParentComponents() const; /*! Get a list of Basic Blocks for this function @@ -14723,6 +14752,8 @@ namespace BinaryNinja { */ bool AddComponent(Ref<Component> component); + bool AddDataVariable(DataVariable dataVariable); + /*! Remove a Component from this Component, moving it to the root component. This will not remove a component from the tree entirely. @@ -14741,6 +14772,8 @@ namespace BinaryNinja { */ bool RemoveFunction(Ref<Function> func); + bool RemoveDataVariable(DataVariable dataVariable); + /*! Get a list of types referenced by the functions in this Component. \return vector of Type objects @@ -14759,6 +14792,12 @@ namespace BinaryNinja { */ std::vector<Ref<Function>> GetContainedFunctions(); + /*! Get a list of datavariables added to this component + + \return list of DataVariables + */ + std::vector<DataVariable> GetContainedDataVariables(); + /*! Get a list of DataVariables referenced by the functions in this Component. \return vector of DataVariable objects diff --git a/binaryninjacore.h b/binaryninjacore.h index f2cc350e..4f8a41d3 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1461,6 +1461,8 @@ extern "C" void (*componentRemoved)(void*ctxt, BNBinaryView* view, BNComponent* formerParent, BNComponent* component); void (*componentFunctionAdded)(void*ctxt, BNBinaryView* view, BNComponent* component, BNFunction* function); void (*componentFunctionRemoved)(void*ctxt, BNBinaryView* view, BNComponent* component, BNFunction* function); + void (*componentDataVariableAdded)(void*ctxt, BNBinaryView* view, BNComponent* component, BNDataVariable* var); + void (*componentDataVariableRemoved)(void*ctxt, BNBinaryView* view, BNComponent* component, BNDataVariable* var); }; struct BNFileAccessor @@ -3786,7 +3788,6 @@ extern "C" BINARYNINJACOREAPI uint64_t BNGetFunctionHighestAddress(BNFunction* func); BINARYNINJACOREAPI uint64_t BNGetFunctionLowestAddress(BNFunction* func); BINARYNINJACOREAPI BNAddressRange* BNGetFunctionAddressRanges(BNFunction* func, size_t* count); - BINARYNINJACOREAPI BNComponent** BNGetFunctionParentComponents(BNFunction *func, size_t* count); BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelIL(BNFunction* func); BINARYNINJACOREAPI BNLowLevelILFunction* BNGetFunctionLowLevelILIfAvailable(BNFunction* func); @@ -5530,6 +5531,9 @@ extern "C" BINARYNINJACOREAPI void BNRemoveExpressionParserMagicValues(BNBinaryView* view, const char** names, size_t count); BINARYNINJACOREAPI bool BNGetExpressionParserMagicValue(BNBinaryView* view, const char* name, uint64_t* value); + BINARYNINJACOREAPI BNComponent** BNGetFunctionParentComponents(BNBinaryView* view, BNFunction *func, size_t* count); + BINARYNINJACOREAPI BNComponent** BNGetDataVariableParentComponents(BNBinaryView* view, uint64_t dataVariable, size_t* count); + // Source code processing BINARYNINJACOREAPI bool BNPreprocessSource(const char* source, const char* fileName, char** output, char** errors, const char** includeDirs, size_t includeDirCount); @@ -6091,6 +6095,7 @@ extern "C" BINARYNINJACOREAPI BNFunction** BNComponentGetContainedFunctions(BNComponent *component, size_t *count); BINARYNINJACOREAPI BNComponent** BNComponentGetContainedComponents(BNComponent *component, size_t *count); + BINARYNINJACOREAPI BNDataVariable* BNComponentGetContainedDataVariables(BNComponent *component, size_t *count); BINARYNINJACOREAPI BNDataVariable* BNComponentGetReferencedDataVariables(BNComponent *component, size_t *count); BINARYNINJACOREAPI BNDataVariable* BNComponentGetReferencedDataVariablesRecursive(BNComponent *component, size_t *count); @@ -6104,17 +6109,23 @@ extern "C" BINARYNINJACOREAPI bool BNComponentContainsFunction(BNComponent* component, BNFunction *function); BINARYNINJACOREAPI bool BNComponentContainsComponent(BNComponent *parent, BNComponent *component); + BINARYNINJACOREAPI bool BNComponentContainsDataVariable(BNComponent* component, uint64_t address); + BINARYNINJACOREAPI bool BNComponentAddFunctionReference(BNComponent* component, BNFunction* function); BINARYNINJACOREAPI bool BNComponentAddComponent(BNComponent* parent, BNComponent* component); + BINARYNINJACOREAPI bool BNComponentAddDataVariable(BNComponent* component, uint64_t address); + BINARYNINJACOREAPI bool BNComponentRemoveComponent(BNComponent* component); - BINARYNINJACOREAPI void BNComponentAddAllMembersFromComponent(BNComponent *component, BNComponent *fromComponent); - BINARYNINJACOREAPI bool BNComponentRemoveFunctionReference(BNComponent *component, BNFunction *function); - BINARYNINJACOREAPI void BNComponentRemoveAllFunctions(BNComponent *component); - BINARYNINJACOREAPI char *BNComponentGetGuid(BNComponent *component); + BINARYNINJACOREAPI bool BNComponentRemoveFunctionReference(BNComponent* component, BNFunction* function); + BINARYNINJACOREAPI void BNComponentRemoveAllFunctions(BNComponent* component); + BINARYNINJACOREAPI bool BNComponentRemoveDataVariable(BNComponent* component, uint64_t address); + + BINARYNINJACOREAPI void BNComponentAddAllMembersFromComponent(BNComponent* component, BNComponent* fromComponent); + BINARYNINJACOREAPI char* BNComponentGetGuid(BNComponent* component); BINARYNINJACOREAPI bool BNComponentsEqual(BNComponent* a, BNComponent* b); BINARYNINJACOREAPI bool BNComponentsNotEqual(BNComponent* a, BNComponent* b); - BINARYNINJACOREAPI char *BNComponentGetDisplayName(BNComponent* component); - BINARYNINJACOREAPI char *BNComponentGetOriginalName(BNComponent* component); + BINARYNINJACOREAPI char* BNComponentGetDisplayName(BNComponent* component); + BINARYNINJACOREAPI char* BNComponentGetOriginalName(BNComponent* component); BINARYNINJACOREAPI void BNComponentSetName(BNComponent* component, const char* name); BINARYNINJACOREAPI BNBinaryView* BNComponentGetView(BNComponent* component); diff --git a/binaryview.cpp b/binaryview.cpp index 52fd3dd3..eeef5a74 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -376,6 +376,30 @@ void BinaryDataNotification::ComponentFunctionRemovedCallback(void* ctxt, BNBina +void BinaryDataNotification::ComponentDataVariableAddedCallback(void* ctxt, BNBinaryView* data, BNComponent* bnComponent, + BNDataVariable* var) +{ + BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; + Ref<BinaryView> view = new BinaryView(BNNewViewReference(data)); + Ref<Component> component = new Component(BNNewComponentReference(bnComponent)); + DataVariable varObj(var->address, + Confidence<Ref<Type>>(new Type(BNNewTypeReference(var->type)), var->typeConfidence), var->autoDiscovered); + notify->OnComponentDataVariableAdded(view, component, varObj); +} + + +void BinaryDataNotification::ComponentDataVariableRemovedCallback(void* ctxt, BNBinaryView* data, + BNComponent* bnComponent, BNDataVariable* var) +{ + BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; + Ref<BinaryView> view = new BinaryView(BNNewViewReference(data)); + Ref<Component> component = new Component(BNNewComponentReference(bnComponent)); + DataVariable varObj(var->address, + Confidence<Ref<Type>>(new Type(BNNewTypeReference(var->type)), var->typeConfidence), var->autoDiscovered); + notify->OnComponentDataVariableRemoved(view, component, varObj); +} + + BinaryDataNotification::BinaryDataNotification() { m_callbacks.context = this; @@ -415,6 +439,8 @@ BinaryDataNotification::BinaryDataNotification() m_callbacks.componentMoved = ComponentMovedCallback; m_callbacks.componentFunctionAdded = ComponentFunctionAddedCallback; m_callbacks.componentFunctionRemoved = ComponentFunctionRemovedCallback; + m_callbacks.componentDataVariableAdded = ComponentDataVariableAddedCallback; + m_callbacks.componentDataVariableRemoved = ComponentDataVariableRemovedCallback; } @@ -3094,6 +3120,46 @@ bool BinaryView::RemoveComponent(std::string guid) } +std::vector<Ref<Component>> BinaryView::GetFunctionParentComponents(Ref<Function> function) const +{ + std::vector<Ref<Component>> components; + + size_t count; + BNComponent** list = BNGetFunctionParentComponents(m_object, function->m_object, &count); + + components.reserve(count); + for (size_t i = 0; i < count; i++) + { + Ref<Component> component = new Component(BNNewComponentReference(list[i])); + components.push_back(component); + } + + BNFreeComponents(list, count); + + return components; +} + + +std::vector<Ref<Component>> BinaryView::GetDataVariableParentComponents(DataVariable var) const +{ + std::vector<Ref<Component>> components; + + size_t count; + BNComponent** list = BNGetDataVariableParentComponents(m_object, var.address, &count); + + components.reserve(count); + for (size_t i = 0; i < count; i++) + { + Ref<Component> component = new Component(BNNewComponentReference(list[i])); + components.push_back(component); + } + + BNFreeComponents(list, count); + + return components; +} + + bool BinaryView::CanAssemble(Architecture* arch) { return BNCanAssemble(m_object, arch->GetObject()); diff --git a/component.cpp b/component.cpp index 88e7a20a..03be498a 100644 --- a/component.cpp +++ b/component.cpp @@ -71,6 +71,12 @@ bool Component::AddComponent(Ref<Component> component) } +bool Component::AddDataVariable(DataVariable dataVariable) +{ + return BNComponentAddDataVariable(m_object, dataVariable.address); +} + + bool Component::RemoveComponent(Ref<Component> component) { return BNComponentRemoveComponent(component->m_object); @@ -83,6 +89,12 @@ bool Component::RemoveFunction(Ref<Function> func) } +bool Component::RemoveDataVariable(DataVariable dataVariable) +{ + return BNComponentRemoveDataVariable(m_object, dataVariable.address); +} + + std::vector<Ref<Component>> Component::GetContainedComponents() { std::vector<Ref<Component>> components; @@ -123,6 +135,27 @@ std::vector<Ref<Function>> Component::GetContainedFunctions() } +std::vector<DataVariable> Component::GetContainedDataVariables() +{ + vector<DataVariable> result; + + size_t count; + BNDataVariable* variables = BNComponentGetContainedDataVariables(m_object, &count); + + result.reserve(count); + for (size_t i = 0; i < count; ++i) + { + result.emplace_back(variables[i].address, + Confidence(new Type(BNNewTypeReference(variables[i].type)), variables[i].typeConfidence), + variables[i].autoDiscovered); + } + + BNFreeDataVariables(variables, count); + return result; +} + + + std::vector<Ref<Type>> Component::GetReferencedTypes() { std::vector<Ref<Type>> types; diff --git a/function.cpp b/function.cpp index 04318393..c9314968 100644 --- a/function.cpp +++ b/function.cpp @@ -1512,24 +1512,6 @@ set<SSAVariable> Function::GetHighLevelILSSAVariablesIfAvailable() } -std::vector<Ref<Component>> Function::GetParentComponents() const -{ - std::vector<Ref<Component>> components; - - size_t count; - BNComponent** list = BNGetFunctionParentComponents(m_object, &count); - - components.reserve(count); - for (size_t i = 0; i < count; i++) - { - Ref<Component> component = new Component(list[i]); - components.push_back(component); - } - - return components; -} - - void Function::CreateAutoVariable( const Variable& var, const Confidence<Ref<Type>>& type, const string& name, bool ignoreDisjointUses) { diff --git a/python/binaryview.py b/python/binaryview.py index 8005630b..0ca357a4 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -252,6 +252,12 @@ class BinaryDataNotification: func: '_function.Function'): pass + def component_data_var_added(self, view: 'BinaryView', _component: component.Component, var: 'DataVariable'): + pass + + def component_data_var_removed(self, view: 'BinaryView', _component: component.Component, var: 'DataVariable'): + pass + @@ -495,6 +501,8 @@ class BinaryDataNotificationCallbacks: self._cb.componentMoved = self._cb.componentMoved.__class__(self._component_moved) self._cb.componentFunctionAdded = self._cb.componentFunctionAdded.__class__(self._component_function_added) self._cb.componentFunctionRemoved = self._cb.componentFunctionRemoved.__class__(self._component_function_removed) + self._cb.componentDataVariableAdded = self._cb.componentDataVariableAdded.__class__(self._component_data_variable_added) + self._cb.componentDataVariableRemoved = self._cb.componentDataVariableRemoved.__class__(self._component_data_variable_removed) def _register(self) -> None: core.BNRegisterDataNotification(self._view.handle, self._cb) @@ -840,6 +848,26 @@ class BinaryDataNotificationCallbacks: except: log_error(traceback.format_exc()) + def _component_data_variable_added(self, ctxt, view: core.BNBinaryView, _component: core.BNComponent, + var: core.BNDataVariable): + try: + component_handle = core.BNNewComponentReference(_component) + assert component_handle is not None, "core.BNNewComponentReference returned None" + result = component.Component(component_handle) + self._notify.component_data_var_added(self._view, result, DataVariable.from_core_struct(var[0], self._view)) + except: + log_error(traceback.format_exc()) + + def _component_data_variable_removed(self, ctxt, view: core.BNBinaryView, _component: core.BNComponent, + var: core.BNDataVariable): + try: + component_handle = core.BNNewComponentReference(_component) + assert component_handle is not None, "core.BNNewComponentReference returned None" + result = component.Component(component_handle) + self._notify.component_data_var_removed(self._view, result, DataVariable.from_core_struct(var[0], self._view)) + except: + log_error(traceback.format_exc()) + @property def view(self) -> 'BinaryView': return self._view @@ -6189,6 +6217,31 @@ class BinaryView: raise TypeError("Removal is only supported with a Component or string representing its Guid") + def get_function_parent_components(self, function: 'function.Function') -> List['component.Component']: + _components = [] + count = ctypes.c_ulonglong(0) + bn_components = core.BNGetFunctionParentComponents(self.handle, function.handle, count) + try: + for i in range(count.value): + _components.append(component.Component(core.BNNewComponentReference(bn_components[i]))) + finally: + core.BNFreeComponents(bn_components, count.value) + return _components + + def get_data_variable_parent_components(self, data_variable: 'DataVariable') -> List['component.Component']: + _components = [] + count = ctypes.c_ulonglong(0) + bn_components = core.BNGetDataVariableParentComponents(self.handle, data_variable.address, count) + try: + for i in range(count.value): + _components.append(component.Component(core.BNNewComponentReference(bn_components[i]))) + finally: + core.BNFreeComponents(bn_components, count.value) + return _components + + def get_constant_data(self, addr: int) -> databuffer.DataBuffer: + return databuffer.DataBuffer(handle=core.BNGetConstantData(self.handle, addr)) + def get_strings(self, start: Optional[int] = None, length: Optional[int] = None) -> List['StringReference']: """ ``get_strings`` returns a list of strings defined in the binary in the optional virtual address range: diff --git a/python/component.py b/python/component.py index 21942297..210ec8c9 100644 --- a/python/component.py +++ b/python/component.py @@ -43,7 +43,8 @@ class Component: return f'<Component "{self.display_name}" "({self.guid[:8]}...")>' def __del__(self): - core.BNFreeComponent(self.handle) + if (hasattr(self, 'handle')): + core.BNFreeComponent(self.handle) def __str__(self): return self._sprawl_component(self) @@ -82,6 +83,15 @@ class Component: """ return core.BNComponentContainsFunction(self.handle, func.handle) + def remove_function(self, func: 'function.Function') -> bool: + """ + Remove function from this component. + + :param func: Function to remove + :return: True if function was successfully removed. + """ + return core.BNComponentRemoveFunctionReference(self.handle, func.handle) + def add_component(self, component: 'Component') -> bool: """ Move component to this component. This will remove it from the old parent. @@ -91,14 +101,14 @@ class Component: """ return core.BNComponentAddComponent(self.handle, component.handle) - def remove_function(self, func: 'function.Function') -> bool: + def contains_component(self, component: 'Component') -> bool: """ - Remove function from this component. + Check whether this component contains a component. - :param func: Function to remove - :return: True if function was successfully removed. + :param component: Component to check + :return: True if this component contains the component. """ - return core.BNComponentRemoveFunctionReference(self.handle, func.handle) + return core.BNComponentContainsComponent(self.handle, component.handle) def remove_component(self, component: 'Component') -> bool: """ @@ -113,14 +123,14 @@ class Component: return self.view.root_component.add_component(component) - def contains_component(self, component: 'Component') -> bool: - """ - Check whether this component contains a component. + def add_data_variable(self, data_variable): + return core.BNComponentAddDataVariable(self.handle, data_variable.address) - :param component: Component to check - :return: True if this component contains the component. - """ - return core.BNComponentContainsComponent(self.handle, component.handle) + def contains_data_variable(self, data_variable): + return core.BNComponentContainsDataVariable(self.handle, data_variable.address) + + def remove_data_variable(self, data_variable): + return core.BNComponentRemoveDataVariable(self.handle, data_variable.address) @property def display_name(self) -> str: @@ -164,61 +174,67 @@ class Component: return None @property - def components(self) -> Iterator['Component']: + def components(self) -> List['Component']: """ ``components`` is an iterator for all Components contained within this Component - :return: An iterator containing Components - :rtype: SubComponentIterator + :return: A list of components :Example: >>> for subcomp in component.components: ... print(repr(component)) """ - @dataclass - class SubComponentIterator: - comp: Component - - def __iter__(self): - count = ctypes.c_ulonglong(0) - bn_components = core.BNComponentGetContainedComponents(self.comp.handle, count) - try: - for i in range(count.value): - yield Component(core.BNNewComponentReference(bn_components[i])) - finally: - core.BNFreeComponents(bn_components, count.value) + count = ctypes.c_ulonglong(0) + bn_components = core.BNComponentGetContainedComponents(self.handle, count) + components = [] + try: + for i in range(count.value): + components.append(Component(core.BNNewComponentReference(bn_components[i]))) + finally: + core.BNFreeComponents(bn_components, count.value) - return iter(SubComponentIterator(self)) + return components @property - def functions(self) -> Iterator['function.Function']: + def functions(self) -> List['function.Function']: """ ``functions`` is an iterator for all Functions contained within this Component - :return: An iterator containing Components - :rtype: ComponentIterator + :return: A list of functions :Example: >>> for func in component.functions: ... print(func.name) """ - @dataclass - class FunctionIterator: - view: 'binaryview.BinaryView' - comp: Component - def __iter__(self): - count = ctypes.c_ulonglong(0) - bn_functions = core.BNComponentGetContainedFunctions(self.comp.handle, count) - try: - for i in range(count.value): - bn_function = core.BNNewFunctionReference(bn_functions[i]) - yield function.Function(self.view, bn_function) - finally: - core.BNFreeFunctionList(bn_functions, count.value) + count = ctypes.c_ulonglong(0) + bn_functions = core.BNComponentGetContainedFunctions(self.handle, count) + funcs = [] + try: + for i in range(count.value): + bn_function = core.BNNewFunctionReference(bn_functions[i]) + funcs.append(function.Function(self.view, bn_function)) + finally: + core.BNFreeFunctionList(bn_functions, count.value) + + return funcs - return iter(FunctionIterator(self.view, self)) + @property + def data_variables(self): + data_vars = [] + + count = ctypes.c_ulonglong(0) + bn_data_vars = core.BNComponentGetContainedDataVariables(self.handle, count) + try: + for i in range(count.value): + bn_data_var = bn_data_vars[i] + data_var = binaryview.DataVariable.from_core_struct(bn_data_var, self.view) + data_vars.append(data_var) + finally: + core.BNFreeDataVariables(bn_data_vars, count.value) + + return data_vars def get_referenced_data_variables(self, recursive=False): """ diff --git a/python/function.py b/python/function.py index 86662cf7..bce4f843 100644 --- a/python/function.py +++ b/python/function.py @@ -2233,15 +2233,6 @@ class Function: core.BNFreeTagList(tags, count.value) return result - @property - def parent_components(self): - _components = [] - count = ctypes.c_ulonglong(0) - bn_components = core.BNGetFunctionParentComponents(self.handle, count) - for i in range(count.value): - _components.append(component.Component(self.view, bn_components[i])) - return _components - def get_lifted_il_at( self, addr: int, arch: Optional['architecture.Architecture'] = None ) -> Optional['lowlevelil.LowLevelILInstruction']: |
