diff options
| author | KyleMiles <krm504@nyu.edu> | 2021-10-02 19:00:41 -0400 |
|---|---|---|
| committer | KyleMiles <krm504@nyu.edu> | 2021-10-05 18:06:43 -0400 |
| commit | c4f4bf5be39c224b619a5928d380d91122ecf1d8 (patch) | |
| tree | 6d6f0ee095259b05d2e2707621263cbb8b24981b | |
| parent | c80d3d99b9e11c4120cd3a36349d8161f01c7a24 (diff) | |
More HLIL API parity; Resolves #2363
| -rw-r--r-- | basicblock.cpp | 9 | ||||
| -rw-r--r-- | binaryninjaapi.h | 33 | ||||
| -rw-r--r-- | binaryninjacore.h | 20 | ||||
| -rw-r--r-- | plugin.cpp | 109 | ||||
| -rw-r--r-- | python/basicblock.py | 5 | ||||
| -rw-r--r-- | python/flowgraph.py | 3 | ||||
| -rw-r--r-- | python/plugin.py | 109 | ||||
| -rw-r--r-- | ui/action.h | 1 | ||||
| -rw-r--r-- | ui/flowgraphwidget.h | 1 | ||||
| -rw-r--r-- | ui/linearview.h | 1 | ||||
| -rw-r--r-- | ui/viewframe.h | 1 | ||||
| -rw-r--r-- | workflow.cpp | 9 |
12 files changed, 300 insertions, 1 deletions
diff --git a/basicblock.cpp b/basicblock.cpp index 6045f6ef..d9b49749 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -484,6 +484,15 @@ Ref<MediumLevelILFunction> BasicBlock::GetMediumLevelILFunction() const } +Ref<HighLevelILFunction> BasicBlock::GetHighLevelILFunction() const +{ + BNHighLevelILFunction* func = BNGetBasicBlockHighLevelILFunction(m_object); + if (!func) + return nullptr; + return new HighLevelILFunction(func); +} + + bool BasicBlock::GetInstructionContainingAddress(uint64_t addr, uint64_t* start) { return BNGetBasicBlockInstructionContainingAddress(m_object, addr, start); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 917341aa..6549c290 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -3161,6 +3161,7 @@ __attribute__ ((format (printf, 1, 2))) Ref<Function> GetFunction(); Ref<LowLevelILFunction> GetLowLevelILFunction(); Ref<MediumLevelILFunction> GetMediumLevelILFunction(); + Ref<HighLevelILFunction> GetHighLevelILFunction(); void SetBasicBlockList(std::vector<Ref<BasicBlock>> basicBlocks); void SetLiftedILFunction(Ref<LowLevelILFunction> liftedIL); @@ -3321,6 +3322,7 @@ __attribute__ ((format (printf, 1, 2))) bool IsMediumLevelILBlock() const; Ref<LowLevelILFunction> GetLowLevelILFunction() const; Ref<MediumLevelILFunction> GetMediumLevelILFunction() const; + Ref<HighLevelILFunction> GetHighLevelILFunction() const; bool GetInstructionContainingAddress(uint64_t addr, uint64_t* start); Ref<BasicBlock> GetSourceBlock() const; @@ -4944,6 +4946,7 @@ __attribute__ ((format (printf, 1, 2))) Ref<Function> function; Ref<LowLevelILFunction> lowLevelILFunction; Ref<MediumLevelILFunction> mediumLevelILFunction; + Ref<HighLevelILFunction> highLevelILFunction; PluginCommandContext(); }; @@ -5000,6 +5003,18 @@ __attribute__ ((format (printf, 1, 2))) std::function<bool(BinaryView*, const MediumLevelILInstruction&)> isValid; }; + struct RegisteredHighLevelILFunctionCommand + { + std::function<void(BinaryView*, HighLevelILFunction*)> action; + std::function<bool(BinaryView*, HighLevelILFunction*)> isValid; + }; + + struct RegisteredHighLevelILInstructionCommand + { + std::function<void(BinaryView*, const HighLevelILInstruction&)> action; + std::function<bool(BinaryView*, const HighLevelILInstruction&)> isValid; + }; + static void DefaultPluginCommandActionCallback(void* ctxt, BNBinaryView* view); static void AddressPluginCommandActionCallback(void* ctxt, BNBinaryView* view, uint64_t addr); static void RangePluginCommandActionCallback(void* ctxt, BNBinaryView* view, uint64_t addr, uint64_t len); @@ -5012,6 +5027,10 @@ __attribute__ ((format (printf, 1, 2))) BNMediumLevelILFunction* func); static void MediumLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr); + static void HighLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNHighLevelILFunction* func); + static void HighLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNHighLevelILFunction* func, size_t instr); static bool DefaultPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view); static bool AddressPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, uint64_t addr); @@ -5025,6 +5044,10 @@ __attribute__ ((format (printf, 1, 2))) BNMediumLevelILFunction* func); static bool MediumLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr); + static bool HighLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNHighLevelILFunction* func); + static bool HighLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNHighLevelILFunction* func, size_t instr); public: PluginCommand(const BNPluginCommand& cmd); @@ -5073,6 +5096,16 @@ __attribute__ ((format (printf, 1, 2))) static void RegisterForMediumLevelILInstruction(const std::string& name, const std::string& description, const std::function<void(BinaryView* view, const MediumLevelILInstruction& instr)>& action, const std::function<bool(BinaryView* view, const MediumLevelILInstruction& instr)>& isValid); + static void RegisterForHighLevelILFunction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, HighLevelILFunction* func)>& action); + static void RegisterForHighLevelILFunction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, HighLevelILFunction* func)>& action, + const std::function<bool(BinaryView* view, HighLevelILFunction* func)>& isValid); + static void RegisterForHighLevelILInstruction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, const HighLevelILInstruction& instr)>& action); + static void RegisterForHighLevelILInstruction(const std::string& name, const std::string& description, + const std::function<void(BinaryView* view, const HighLevelILInstruction& instr)>& action, + const std::function<bool(BinaryView* view, const HighLevelILInstruction& instr)>& isValid); static std::vector<PluginCommand> GetList(); static std::vector<PluginCommand> GetValidList(const PluginCommandContext& ctxt); diff --git a/binaryninjacore.h b/binaryninjacore.h index 4396fdda..7a96db2c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -2024,7 +2024,9 @@ extern "C" LowLevelILFunctionPluginCommand, LowLevelILInstructionPluginCommand, MediumLevelILFunctionPluginCommand, - MediumLevelILInstructionPluginCommand + MediumLevelILInstructionPluginCommand, + HighLevelILFunctionPluginCommand, + HighLevelILInstructionPluginCommand }; struct BNPluginCommand @@ -2042,6 +2044,8 @@ extern "C" void (*lowLevelILInstructionCommand)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr); void (*mediumLevelILFunctionCommand)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func); void (*mediumLevelILInstructionCommand)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr); + void (*highLevelILFunctionCommand)(void* ctxt, BNBinaryView* view, BNHighLevelILFunction* func); + void (*highLevelILInstructionCommand)(void* ctxt, BNBinaryView* view, BNHighLevelILFunction* func, size_t instr); bool (*defaultIsValid)(void* ctxt, BNBinaryView* view); bool (*addressIsValid)(void* ctxt, BNBinaryView* view, uint64_t addr); @@ -2051,6 +2055,8 @@ extern "C" bool (*lowLevelILInstructionIsValid)(void* ctxt, BNBinaryView* view, BNLowLevelILFunction* func, size_t instr); bool (*mediumLevelILFunctionIsValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func); bool (*mediumLevelILInstructionIsValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr); + bool (*highLevelILFunctionIsValid)(void* ctxt, BNBinaryView* view, BNHighLevelILFunction* func); + bool (*highLevelILInstructionIsValid)(void* ctxt, BNBinaryView* view, BNHighLevelILFunction* func, size_t instr); }; struct BNCustomCallingConvention @@ -3532,6 +3538,7 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI BNFunctionGraphType BNGetBasicBlockFunctionGraphType(BNBasicBlock* block); BINARYNINJACOREAPI BNLowLevelILFunction* BNGetBasicBlockLowLevelILFunction(BNBasicBlock* block); BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetBasicBlockMediumLevelILFunction(BNBasicBlock* block); + BINARYNINJACOREAPI BNHighLevelILFunction* BNGetBasicBlockHighLevelILFunction(BNBasicBlock* block); BINARYNINJACOREAPI bool BNGetBasicBlockInstructionContainingAddress(BNBasicBlock* block, uint64_t addr, uint64_t* start); BINARYNINJACOREAPI BNBasicBlock* BNGetBasicBlockSourceBlock(BNBasicBlock* block); @@ -4038,6 +4045,7 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI BNFunction* BNAnalysisContextGetFunction(BNAnalysisContext* analysisContext); BINARYNINJACOREAPI BNLowLevelILFunction* BNAnalysisContextGetLowLevelILFunction(BNAnalysisContext* analysisContext); BINARYNINJACOREAPI BNMediumLevelILFunction* BNAnalysisContextGetMediumLevelILFunction(BNAnalysisContext* analysisContext); + BINARYNINJACOREAPI BNHighLevelILFunction* BNAnalysisContextGetHighLevelILFunction(BNAnalysisContext* analysisContext); BINARYNINJACOREAPI void BNSetBasicBlockList(BNAnalysisContext* analysisContext, BNBasicBlock** basicBlocks, size_t count); BINARYNINJACOREAPI void BNSetLiftedILFunction(BNAnalysisContext* analysisContext, BNLowLevelILFunction* liftedIL); @@ -4944,6 +4952,12 @@ __attribute__ ((format (printf, 1, 2))) BINARYNINJACOREAPI void BNRegisterPluginCommandForMediumLevelILInstruction(const char* name, const char* description, void (*action)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr), bool (*isValid)(void* ctxt, BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForHighLevelILFunction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNHighLevelILFunction* func), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNHighLevelILFunction* func), void* context); + BINARYNINJACOREAPI void BNRegisterPluginCommandForHighLevelILInstruction(const char* name, const char* description, + void (*action)(void* ctxt, BNBinaryView* view, BNHighLevelILFunction* func, size_t instr), + bool (*isValid)(void* ctxt, BNBinaryView* view, BNHighLevelILFunction* func, size_t instr), void* context); BINARYNINJACOREAPI BNPluginCommand* BNGetAllPluginCommands(size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommands(BNBinaryView* view, size_t* count); @@ -4961,6 +4975,10 @@ __attribute__ ((format (printf, 1, 2))) BNMediumLevelILFunction* func, size_t* count); BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForMediumLevelILInstruction(BNBinaryView* view, BNMediumLevelILFunction* func, size_t instr, size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForHighLevelILFunction(BNBinaryView* view, + BNHighLevelILFunction* func, size_t* count); + BINARYNINJACOREAPI BNPluginCommand* BNGetValidPluginCommandsForHighLevelILInstruction(BNBinaryView* view, + BNHighLevelILFunction* func, size_t instr, size_t* count); BINARYNINJACOREAPI void BNFreePluginCommandList(BNPluginCommand* commands); // Calling conventions @@ -21,6 +21,7 @@ #include "binaryninjaapi.h" #include "lowlevelilinstruction.h" #include "mediumlevelilinstruction.h" +#include "highlevelilinstruction.h" using namespace BinaryNinja; using namespace std; @@ -142,6 +143,27 @@ void PluginCommand::MediumLevelILInstructionPluginCommandActionCallback(void* ct } +void PluginCommand::HighLevelILFunctionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNHighLevelILFunction* func) +{ + RegisteredHighLevelILFunctionCommand* cmd = (RegisteredHighLevelILFunctionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<HighLevelILFunction> funcObject = new HighLevelILFunction(BNNewHighLevelILFunctionReference(func)); + cmd->action(viewObject, funcObject); +} + + +void PluginCommand::HighLevelILInstructionPluginCommandActionCallback(void* ctxt, BNBinaryView* view, + BNHighLevelILFunction* func, size_t instr) +{ + RegisteredHighLevelILInstructionCommand* cmd = (RegisteredHighLevelILInstructionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<HighLevelILFunction> funcObject = new HighLevelILFunction(BNNewHighLevelILFunctionReference(func)); + HighLevelILInstruction instrObject = funcObject->GetInstruction(instr); + cmd->action(viewObject, instrObject); +} + + bool PluginCommand::DefaultPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view) { RegisteredDefaultCommand* cmd = (RegisteredDefaultCommand*)ctxt; @@ -217,6 +239,27 @@ bool PluginCommand::MediumLevelILInstructionPluginCommandIsValidCallback(void* c } +bool PluginCommand::HighLevelILFunctionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNHighLevelILFunction* func) +{ + RegisteredHighLevelILFunctionCommand* cmd = (RegisteredHighLevelILFunctionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<HighLevelILFunction> funcObject = new HighLevelILFunction(BNNewHighLevelILFunctionReference(func)); + return cmd->isValid(viewObject, funcObject); +} + + +bool PluginCommand::HighLevelILInstructionPluginCommandIsValidCallback(void* ctxt, BNBinaryView* view, + BNHighLevelILFunction* func, size_t instr) +{ + RegisteredHighLevelILInstructionCommand* cmd = (RegisteredHighLevelILInstructionCommand*)ctxt; + Ref<BinaryView> viewObject = new BinaryView(BNNewViewReference(view)); + Ref<HighLevelILFunction> funcObject = new HighLevelILFunction(BNNewHighLevelILFunctionReference(func)); + HighLevelILInstruction instrObject = funcObject->GetInstruction(instr); + return cmd->isValid(viewObject, instrObject); +} + + void PluginCommand::Register(const string& name, const string& description, const function<void(BinaryView* view)>& action) { @@ -376,6 +419,48 @@ void PluginCommand::RegisterForMediumLevelILInstruction(const string& name, cons } +void PluginCommand::RegisterForHighLevelILFunction(const string& name, const string& description, + const function<void(BinaryView* view, HighLevelILFunction* func)>& action) +{ + RegisterForHighLevelILFunction(name, description, action, + [](BinaryView*, HighLevelILFunction*) { return true; }); +} + + +void PluginCommand::RegisterForHighLevelILFunction(const string& name, const string& description, + const function<void(BinaryView* view, HighLevelILFunction* func)>& action, + const function<bool(BinaryView* view, HighLevelILFunction* func)>& isValid) +{ + RegisteredHighLevelILFunctionCommand* cmd = new RegisteredHighLevelILFunctionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForHighLevelILFunction(name.c_str(), description.c_str(), + HighLevelILFunctionPluginCommandActionCallback, + HighLevelILFunctionPluginCommandIsValidCallback, cmd); +} + + +void PluginCommand::RegisterForHighLevelILInstruction(const string& name, const string& description, + const function<void(BinaryView* view, const HighLevelILInstruction& instr)>& action) +{ + RegisterForHighLevelILInstruction(name, description, action, + [](BinaryView*, const HighLevelILInstruction&) { return true; }); +} + + +void PluginCommand::RegisterForHighLevelILInstruction(const string& name, const string& description, + const function<void(BinaryView* view, const HighLevelILInstruction& instr)>& action, + const function<bool(BinaryView* view, const HighLevelILInstruction& instr)>& isValid) +{ + RegisteredHighLevelILInstructionCommand* cmd = new RegisteredHighLevelILInstructionCommand; + cmd->action = action; + cmd->isValid = isValid; + BNRegisterPluginCommandForHighLevelILInstruction(name.c_str(), description.c_str(), + HighLevelILInstructionPluginCommandActionCallback, + HighLevelILInstructionPluginCommandIsValidCallback, cmd); +} + + vector<PluginCommand> PluginCommand::GetList() { vector<PluginCommand> result; @@ -461,6 +546,22 @@ bool PluginCommand::IsValid(const PluginCommandContext& ctxt) const return true; return m_command.mediumLevelILInstructionIsValid(m_command.context, ctxt.binaryView->GetObject(), ctxt.mediumLevelILFunction->GetObject(), ctxt.instrIndex); + case HighLevelILFunctionPluginCommand: + if (!ctxt.highLevelILFunction) + return false; + if (!m_command.highLevelILFunctionIsValid) + return true; + return m_command.highLevelILFunctionIsValid(m_command.context, ctxt.binaryView->GetObject(), + ctxt.highLevelILFunction->GetObject()); + case HighLevelILInstructionPluginCommand: + if (!ctxt.highLevelILFunction) + return false; + if (ctxt.instrIndex == BN_INVALID_EXPR) + return false; + if (!m_command.highLevelILInstructionIsValid) + return true; + return m_command.highLevelILInstructionIsValid(m_command.context, ctxt.binaryView->GetObject(), + ctxt.highLevelILFunction->GetObject(), ctxt.instrIndex); default: return false; } @@ -502,6 +603,14 @@ void PluginCommand::Execute(const PluginCommandContext& ctxt) const m_command.mediumLevelILInstructionCommand(m_command.context, ctxt.binaryView->GetObject(), ctxt.mediumLevelILFunction->GetObject(), ctxt.instrIndex); break; + case HighLevelILFunctionPluginCommand: + m_command.highLevelILFunctionCommand(m_command.context, ctxt.binaryView->GetObject(), + ctxt.highLevelILFunction->GetObject()); + break; + case HighLevelILInstructionPluginCommand: + m_command.highLevelILInstructionCommand(m_command.context, ctxt.binaryView->GetObject(), + ctxt.highLevelILFunction->GetObject(), ctxt.instrIndex); + break; default: break; } diff --git a/python/basicblock.py b/python/basicblock.py index 413199a7..758b9b5f 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -483,6 +483,11 @@ class BasicBlock: """Whether the basic block contains Medium Level IL""" return core.BNIsMediumLevelILBasicBlock(self.handle) + @property + def is_high_level_il(self) -> bool: + """Whether the basic block contains High Level IL""" + return core.BNIsHighLevelILBasicBlock(self.handle) + @staticmethod def get_iterated_dominance_frontier(blocks:List['BasicBlock']) -> List['BasicBlock']: if len(blocks) == 0: diff --git a/python/flowgraph.py b/python/flowgraph.py index 1d3d9504..725af442 100644 --- a/python/flowgraph.py +++ b/python/flowgraph.py @@ -168,6 +168,9 @@ class FlowGraphNode: elif core.BNIsMediumLevelILBasicBlock(block): mlil_func = mediumlevelil.MediumLevelILFunction(func.arch, core.BNGetBasicBlockMediumLevelILFunction(block), func) block = mediumlevelil.MediumLevelILBasicBlock(block, mlil_func, view) + elif core.BNIsHighLevelILBasicBlock(block): + hlil_func = highlevelil.HighLevelILFunction(func.arch, core.BNGetBasicBlockHighLevelILFunction(block), func) + block = highlevelil.HighLevelILBasicBlock(block, hlil_func, view) else: block = basicblock.BasicBlock(block, view) return block diff --git a/python/plugin.py b/python/plugin.py index d4e3f988..beba9781 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -32,6 +32,7 @@ from . import function from .log import log_error from . import lowlevelil from . import mediumlevelil +from . import highlevelil class PluginCommandContext: @@ -191,6 +192,28 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): log_error(traceback.format_exc()) @staticmethod + def _high_level_il_function_action(view, func, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetHighLevelILOwnerFunction(func)) + func_obj = highlevelil.HighLevelILFunction(owner.arch, core.BNNewHighLevelILFunctionReference(func), owner) + action(view_obj, func_obj) + except: + log_error(traceback.format_exc()) + + @staticmethod + def _high_level_il_instruction_action(view, func, instr, action): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetHighLevelILOwnerFunction(func)) + func_obj = highlevelil.HighLevelILFunction(owner.arch, core.BNNewHighLevelILFunctionReference(func), owner) + action(view_obj, func_obj[instr]) + except: + log_error(traceback.format_exc()) + + @staticmethod def _default_is_valid(view, is_valid): try: if is_valid is None: @@ -295,6 +318,34 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): log_error(traceback.format_exc()) return False + @staticmethod + def _high_level_il_function_is_valid(view, func, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetHighLevelILOwnerFunction(func)) + func_obj = highlevelil.HighLevelILFunction(owner.arch, core.BNNewHighLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj) + except: + log_error(traceback.format_exc()) + return False + + @staticmethod + def _high_level_il_instruction_is_valid(view, func, instr, is_valid): + try: + if is_valid is None: + return True + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + owner = function.Function(view_obj, core.BNGetHighLevelILOwnerFunction(func)) + func_obj = highlevelil.HighLevelILFunction(owner.arch, core.BNNewHighLevelILFunctionReference(func), owner) + return is_valid(view_obj, func_obj[instr]) + except: + log_error(traceback.format_exc()) + return False + @classmethod def register(cls, name, description, action, is_valid = None): r""" @@ -448,6 +499,44 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): core.BNRegisterPluginCommandForMediumLevelILInstruction(name, description, action_obj, is_valid_obj, None) @classmethod + def register_for_high_level_il_function(cls, name, description, action, is_valid = None): + r""" + ``register_for_high_level_il_function`` Register a plugin to be called with a high level IL function argument + + :param str name: name of the plugin (use 'Folder\\Name' to have the menu item nested in a folder) + :param str description: description of the plugin + :param callback action: function to call with the :class:`~binaryview.BinaryView` and a :class:`~highlevelil.HighLevelILFunction` as arguments + :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and :class:`~highlevelil.HighLevelILFunction` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_high_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + binaryninja._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNHighLevelILFunction))(lambda ctxt, view, func: cls._high_level_il_function_action(view, func, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNHighLevelILFunction))(lambda ctxt, view, func: cls._high_level_il_function_is_valid(view, func, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForHighLevelILFunction(name, description, action_obj, is_valid_obj, None) + + @classmethod + def register_for_high_level_il_instruction(cls, name, description, action, is_valid = None): + r""" + ``register_for_high_level_il_instruction`` Register a plugin to be called with a high level IL instruction argument + + :param str name: name of the plugin (use 'Folder\\Name' to have the menu item nested in a folder) + :param str description: description of the plugin + :param callback action: function to call with the :class:`~binaryview.BinaryView` and a :class:`~highlevelil.HighLevelILInstruction` as arguments + :param callback is_valid: optional argument of a function passed a :class:`~binaryview.BinaryView` and :class:`~highlevelil.HighLevelILInstruction` to determine whether the plugin should be enabled for that view + :rtype: None + + .. warning:: Calling ``register_for_high_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. + """ + binaryninja._init_plugins() + action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNHighLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._high_level_il_instruction_action(view, func, instr, action)) + is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNHighLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._high_level_il_instruction_is_valid(view, func, instr, is_valid)) + cls._registered_commands.append((action_obj, is_valid_obj)) + core.BNRegisterPluginCommandForHighLevelILInstruction(name, description, action_obj, is_valid_obj, None) + + @classmethod def get_valid_list(cls, context): """Dict of registered plugins""" commands = list(cls) @@ -510,6 +599,21 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): return True return self._command.mediumLevelILInstructionIsValid(self._command.context, context.view.handle, context.instruction.function.handle, context.instruction.instr_index) + elif self._command.type == PluginCommandType.HighLevelILFunctionPluginCommand: + if context.function is None: + return False + if not self._command.highLevelILFunctionIsValid: + return True + return self._command.highLevelILFunctionIsValid(self._command.context, context.view.handle, context.function.handle) + elif self._command.type == PluginCommandType.HighLevelILInstructionPluginCommand: + if context.instruction is None: + return False + if not isinstance(context.instruction, highlevelil.HighLevelILInstruction): + return False + if not self._command.highLevelILInstructionIsValid: + return True + return self._command.highLevelILInstructionIsValid(self._command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) return False def execute(self, context): @@ -543,6 +647,11 @@ class PluginCommand(metaclass=_PluginCommandMetaClass): elif self._command.type == PluginCommandType.MediumLevelILInstructionPluginCommand: self._command.mediumLevelILInstructionCommand(self._command.context, context.view.handle, context.instruction.function.handle, context.instruction.instr_index) + elif self._command.type == PluginCommandType.HighLevelILFunctionPluginCommand: + self._command.highLevelILFunctionCommand(self._command.context, context.view.handle, context.function.handle) + elif self._command.type == PluginCommandType.HighLevelILInstructionPluginCommand: + self._command.highLevelILInstructionCommand(self._command.context, context.view.handle, + context.instruction.function.handle, context.instruction.instr_index) def __repr__(self): return "<PluginCommand: %s>" % self._name diff --git a/ui/action.h b/ui/action.h index a9c70937..19f3d317 100644 --- a/ui/action.h +++ b/ui/action.h @@ -58,6 +58,7 @@ struct BINARYNINJAUIAPI UIActionContext FunctionRef function; LowLevelILFunctionRef lowLevelILFunction; MediumLevelILFunctionRef mediumLevelILFunction; + HighLevelILFunctionRef highLevelILFunction; LinearViewCursorPosition* cursorPosition; UIActionContext(); diff --git a/ui/flowgraphwidget.h b/ui/flowgraphwidget.h index 0ba5c823..6a77b829 100644 --- a/ui/flowgraphwidget.h +++ b/ui/flowgraphwidget.h @@ -251,6 +251,7 @@ public: virtual LowLevelILFunctionRef getCurrentLowLevelILFunction() override; virtual MediumLevelILFunctionRef getCurrentMediumLevelILFunction() override; + virtual HighLevelILFunctionRef getCurrentHighLevelILFunction() override; virtual size_t getCurrentILInstructionIndex() override; void scrollToCursor(); diff --git a/ui/linearview.h b/ui/linearview.h index 42395b20..d7a4983e 100644 --- a/ui/linearview.h +++ b/ui/linearview.h @@ -311,6 +311,7 @@ public: virtual FunctionRef getCurrentFunction() override; virtual LowLevelILFunctionRef getCurrentLowLevelILFunction() override; virtual MediumLevelILFunctionRef getCurrentMediumLevelILFunction() override; + virtual HighLevelILFunctionRef getCurrentHighLevelILFunction() override; virtual BasicBlockRef getCurrentBasicBlock() override; virtual ArchitectureRef getCurrentArchitecture() override; virtual size_t getCurrentILInstructionIndex() override; diff --git a/ui/viewframe.h b/ui/viewframe.h index 1445c780..6681582f 100644 --- a/ui/viewframe.h +++ b/ui/viewframe.h @@ -206,6 +206,7 @@ public: virtual LowLevelILFunctionRef getCurrentLowLevelILFunction() { return nullptr; } virtual MediumLevelILFunctionRef getCurrentMediumLevelILFunction() { return nullptr; } + virtual HighLevelILFunctionRef getCurrentHighLevelILFunction() { return nullptr; } virtual BNFunctionGraphType getILViewType() { return InvalidILViewType; } virtual void setILViewType(BNFunctionGraphType ilViewType) { } virtual size_t getCurrentILInstructionIndex() { return BN_INVALID_EXPR; } diff --git a/workflow.cpp b/workflow.cpp index 70cd1ced..1d8c67a1 100644 --- a/workflow.cpp +++ b/workflow.cpp @@ -48,6 +48,15 @@ Ref<MediumLevelILFunction> AnalysisContext::GetMediumLevelILFunction() } +Ref<HighLevelILFunction> AnalysisContext::GetHighLevelILFunction() +{ + BNHighLevelILFunction* func = BNAnalysisContextGetHighLevelILFunction(m_object); + if (!func) + return nullptr; + return new HighLevelILFunction(func); +} + + void AnalysisContext::SetBasicBlockList(vector<Ref<BasicBlock>> basicBlocks) { BNBasicBlock** blocks = new BNBasicBlock*[basicBlocks.size()]; |
