diff options
| author | Brian Potchik <brian@vector35.com> | 2025-01-22 10:48:44 -0500 |
|---|---|---|
| committer | Brian Potchik <brian@vector35.com> | 2025-01-22 10:48:44 -0500 |
| commit | 8ba7106948272275534309d10a5a444f26df01ee (patch) | |
| tree | 557da11f907b4f05d024c0e5d63a5580bd124130 | |
| parent | f1eccb70c2f23fc6665733d8c911b21eb36cbcf5 (diff) | |
Support eligibility callbacks through the API for Workflow actions.
| -rw-r--r-- | activity.cpp | 25 | ||||
| -rw-r--r-- | binaryninjaapi.h | 8 | ||||
| -rw-r--r-- | binaryninjacore.h | 3 | ||||
| -rw-r--r-- | python/workflow.py | 11 |
4 files changed, 35 insertions, 12 deletions
diff --git a/activity.cpp b/activity.cpp index fcc7386a..0bb5858f 100644 --- a/activity.cpp +++ b/activity.cpp @@ -5,10 +5,14 @@ using namespace BinaryNinja; using namespace std; -Activity::Activity(const string& configuration, const std::function<void(Ref<AnalysisContext> analysisContext)>& action) : m_action(action) +Activity::Activity(const string& configuration, const std::function<void(Ref<AnalysisContext> analysisContext)>& action, + const std::function<bool(Ref<Activity>, Ref<AnalysisContext>)>& eligibility) : m_action(action), m_eligibility(eligibility) { // LogError("API-Side Activity Constructed!"); - m_object = BNCreateActivity(configuration.c_str(), this, Run); + if (eligibility) + m_object = BNCreateActivityWithEligibility(configuration.c_str(), this, RunAction, CheckEligibility); + else + m_object = BNCreateActivity(configuration.c_str(), this, RunAction); } @@ -25,12 +29,21 @@ Activity::~Activity() } -void Activity::Run(void* ctxt, BNAnalysisContext* analysisContext) +void Activity::RunAction(void* ctxt, BNAnalysisContext* analysisContext) { - // LogError("API-Side Activity Run!"); - Activity* activity = (Activity*)ctxt; + // LogError("API-Side Activity RunAction!"); + auto boundActivity = static_cast<Activity*>(ctxt); Ref<AnalysisContext> ac = new AnalysisContext(BNNewAnalysisContextReference(analysisContext)); - activity->m_action(ac); + boundActivity->m_action(ac); +} + + +bool Activity::CheckEligibility(void* ctxt, BNActivity* activity, BNAnalysisContext* analysisContext) +{ + auto boundActivity = static_cast<Activity*>(ctxt); + Ref<Activity> act = new Activity(BNNewActivityReference(activity)); + Ref<AnalysisContext> ac = new AnalysisContext(BNNewAnalysisContextReference(analysisContext)); + return boundActivity->m_eligibility(act, ac); } diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 2a2e5e9b..f8d7504a 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -9943,15 +9943,19 @@ namespace BinaryNinja { { protected: std::function<void(Ref<AnalysisContext> analysisContext)> m_action; + std::function<bool(Ref<Activity>, Ref<AnalysisContext>)> m_eligibility; - static void Run(void* ctxt, BNAnalysisContext* analysisContext); + static void RunAction(void* ctxt, BNAnalysisContext* analysisContext); + static bool CheckEligibility(void* ctxt, BNActivity* activity, BNAnalysisContext* analysisContext); public: /*! \param configuration a JSON representation of the activity configuration \param action Workflow action, a function taking a Ref<AnalysisContext> as an argument. + \param eligibility A function that determines whether the activity is eligible to run */ - Activity(const std::string& configuration, const std::function<void(Ref<AnalysisContext>)>& action); + Activity(const std::string& configuration, const std::function<void(Ref<AnalysisContext>)>& action, + const std::function<bool(Ref<Activity>, Ref<AnalysisContext>)>& eligibility = nullptr); Activity(BNActivity* activity); virtual ~Activity(); diff --git a/binaryninjacore.h b/binaryninjacore.h index b13a7a7a..bc785484 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,7 +37,7 @@ // Current ABI version for linking to the core. This is incremented any time // there are changes to the API that affect linking, including new functions, // new types, or modifications to existing functions or types. -#define BN_CURRENT_CORE_ABI_VERSION 88 +#define BN_CURRENT_CORE_ABI_VERSION 89 // Minimum ABI version that is supported for loading of plugins. Plugins that // are linked to an ABI version less than this will not be able to load and @@ -5400,6 +5400,7 @@ extern "C" // Activity BINARYNINJACOREAPI BNActivity* BNCreateActivity(const char* configuration, void* ctxt, void (*action)(void*, BNAnalysisContext*)); + BINARYNINJACOREAPI BNActivity* BNCreateActivityWithEligibility(const char* configuration, void* ctxt, void (*action)(void*, BNAnalysisContext*), bool (*eligibilityHandler)(void*, BNActivity*, BNAnalysisContext*)); BINARYNINJACOREAPI BNActivity* BNNewActivityReference(BNActivity* activity); BINARYNINJACOREAPI void BNFreeActivity(BNActivity* activity); diff --git a/python/workflow.py b/python/workflow.py index 8e97ee59..f1cbe99c 100644 --- a/python/workflow.py +++ b/python/workflow.py @@ -152,12 +152,17 @@ class Activity(object): """ _action_callbacks = {} + _eligibility_callbacks = {} - def __init__(self, configuration: str = "", handle: Optional[core.BNActivityHandle] = None, action: Optional[Callable[[Any], None]] = None): + def __init__(self, configuration: str = "", handle: Optional[core.BNActivityHandle] = None, action: Optional[Callable[[Any], None]] = None, eligibility: Optional[Callable[[Any], bool]] = None): if handle is None: - #cls._notify(ac, callback) action_callback = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNAnalysisContext))(lambda ctxt, ac: self._action(ac)) - _handle = core.BNCreateActivity(configuration, None, action_callback) + if eligibility: + eligibility_callback = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNActivity), ctypes.POINTER(core.BNAnalysisContext))(lambda ctxt, act, ac: eligibility(act, ac)) + _handle = core.BNCreateActivityWithEligibility(configuration, None, action_callback, eligibility_callback) + self.__class__._eligibility_callbacks[len(self.__class__._eligibility_callbacks)] = eligibility_callback + else: + _handle = core.BNCreateActivity(configuration, None, action_callback) self.action = action self.__class__._action_callbacks[len(self.__class__._action_callbacks)] = action_callback else: |
