summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Potchik <brian@vector35.com>2025-01-22 10:48:44 -0500
committerBrian Potchik <brian@vector35.com>2025-01-22 10:48:44 -0500
commit8ba7106948272275534309d10a5a444f26df01ee (patch)
tree557da11f907b4f05d024c0e5d63a5580bd124130
parentf1eccb70c2f23fc6665733d8c911b21eb36cbcf5 (diff)
Support eligibility callbacks through the API for Workflow actions.
-rw-r--r--activity.cpp25
-rw-r--r--binaryninjaapi.h8
-rw-r--r--binaryninjacore.h3
-rw-r--r--python/workflow.py11
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: