Skip to content

Commit 62cb5ab

Browse files
committed
Firmware Ninja reference tree API
1 parent 9463e0f commit 62cb5ab

File tree

4 files changed

+491
-72
lines changed

4 files changed

+491
-72
lines changed

binaryninjaapi.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18397,6 +18397,59 @@ namespace BinaryNinja {
1839718397
size_t unique;
1839818398
};
1839918399

18400+
18401+
/*! FirmwareNinjaReferenceNode is a class used to build reference trees to memory regions, functions, and data
18402+
variables. This class is only available in the Ultimate Edition of Binary Ninja.
18403+
18404+
\ingroup firmwareninja
18405+
*/
18406+
class FirmwareNinjaReferenceNode : public CoreRefCountObject<BNFirmwareNinjaReferenceNode, BNNewFirmwareNinjaReferenceNodeReference, BNFreeFirmwareNinjaReferenceNode>
18407+
{
18408+
BNFirmwareNinjaReferenceNode* m_object;
18409+
public:
18410+
FirmwareNinjaReferenceNode(BNFirmwareNinjaReferenceNode* node);
18411+
~FirmwareNinjaReferenceNode();
18412+
18413+
/*! Determine if the reference tree node is for a function
18414+
18415+
\return true if the reference tree node is for a function, false otherwise
18416+
*/
18417+
bool IsFunction();
18418+
18419+
/*! Determine if the reference tree node is for a data variable
18420+
18421+
\return true if the reference tree node is for a data variable, false otherwise
18422+
*/
18423+
bool IsDataVariable();
18424+
18425+
/*! Determine if the reference tree node contains child nodes
18426+
18427+
\return true if the reference tree node contains child nodes, false otherwise
18428+
*/
18429+
bool HasChildren();
18430+
18431+
/*! Query the function contained in the reference tree node
18432+
18433+
\param function Output function object
18434+
\return true if the function was queried successfully, false otherwise
18435+
*/
18436+
bool GetFunction(Ref<Function>& function);
18437+
18438+
/*! Query the data variable contained in the reference tree node
18439+
18440+
\param function Output data variable object
18441+
\return true if the data variable was queried successfully, false otherwise
18442+
*/
18443+
bool GetDataVariable(DataVariable& variable);
18444+
18445+
/*! Query the child nodes contained in the reference tree node
18446+
18447+
\return Vector of child reference tree nodes
18448+
*/
18449+
std::vector<Ref<FirmwareNinjaReferenceNode>> GetChildren();
18450+
};
18451+
18452+
1840018453
/*! FirmwareNinja is a class containing features specific to embedded firmware analysis. This class is only
1840118454
available in the Ultimate Edition of Binary Ninja.
1840218455

@@ -18485,6 +18538,47 @@ namespace BinaryNinja {
1848518538
*/
1848618539
std::vector<FirmwareNinjaDeviceAccesses> GetBoardDeviceAccesses(
1848718540
const std::vector<FirmwareNinjaFunctionMemoryAccesses>& fma);
18541+
18542+
18543+
/*! Returns a tree of reference nodes that reference the memory region represented by the given device
18544+
18545+
\param device Firmware Ninja device
18546+
\param fma Vector of Firmware Ninja function memory accesses information
18547+
\param value (Optional) only include components that originate with a write of this value to the device
18548+
\return Root reference node of tree
18549+
*/
18550+
Ref<FirmwareNinjaReferenceNode> GetReferenceTree(
18551+
FirmwareNinjaDevice& device,
18552+
const std::vector<FirmwareNinjaFunctionMemoryAccesses>& fma,
18553+
uint64_t* value = nullptr
18554+
);
18555+
18556+
/*! Returns a tree of reference nodes that reference the memory region represented by the given section
18557+
18558+
\param device Firmware Ninja device
18559+
\param fma Vector of Firmware Ninja function memory accesses information
18560+
\param value (Optional) only include components that originate with a write of this value to the device
18561+
\return Root reference node of tree
18562+
*/
18563+
Ref<FirmwareNinjaReferenceNode> GetReferenceTree(
18564+
Section& section,
18565+
const std::vector<FirmwareNinjaFunctionMemoryAccesses>& fma,
18566+
uint64_t* value = nullptr
18567+
);
18568+
18569+
18570+
/*! Returns a tree of reference nodes that reference the given address
18571+
18572+
\param device Firmware Ninja device
18573+
\param fma Vector of Firmware Ninja function memory accesses information
18574+
\param value (Optional) only include components that originate with a write of this value to the device
18575+
\return Root reference node of tree
18576+
*/
18577+
Ref<FirmwareNinjaReferenceNode> GetReferenceTree(
18578+
uint64_t address,
18579+
const std::vector<FirmwareNinjaFunctionMemoryAccesses>& fma,
18580+
uint64_t* value = nullptr
18581+
);
1848818582
};
1848918583

1849018584

binaryninjacore.h

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
// Current ABI version for linking to the core. This is incremented any time
3838
// there are changes to the API that affect linking, including new functions,
3939
// new types, or modifications to existing functions or types.
40-
#define BN_CURRENT_CORE_ABI_VERSION 87
40+
#define BN_CURRENT_CORE_ABI_VERSION 88
4141

4242
// Minimum ABI version that is supported for loading of plugins. Plugins that
4343
// are linked to an ABI version less than this will not be able to load and
@@ -301,6 +301,7 @@ extern "C"
301301
typedef struct BNUndoEntry BNUndoEntry;
302302
typedef struct BNDemangler BNDemangler;
303303
typedef struct BNFirmwareNinja BNFirmwareNinja;
304+
typedef struct BNFirmwareNinjaReferenceNode BNFirmwareNinjaReferenceNode;
304305

305306
//! Console log levels
306307
typedef enum BNLogLevel
@@ -3537,7 +3538,6 @@ extern "C"
35373538
size_t unique;
35383539
} BNFirmwareNinjaDeviceAccesses;
35393540

3540-
35413541
BINARYNINJACOREAPI char* BNAllocString(const char* contents);
35423542
BINARYNINJACOREAPI char* BNAllocStringWithLength(const char* contents, size_t len);
35433543
BINARYNINJACOREAPI void BNFreeString(char* str);
@@ -8038,12 +8038,24 @@ extern "C"
80388038
BINARYNINJACOREAPI int BNFirmwareNinjaQueryBoardDevices(BNFirmwareNinja* fn, BNArchitecture* arch, const char* board, BNFirmwareNinjaDevice** devices);
80398039
BINARYNINJACOREAPI int BNFirmwareNinjaFindSectionsWithEntropy(BNFirmwareNinja* fn, BNFirmwareNinjaSection** sections, float highCodeEntropyThreshold, float lowCodeEntropyThreshold, size_t blockSize, BNFirmwareNinjaSectionAnalysisMode mode);
80408040
BINARYNINJACOREAPI void BNFirmwareNinjaFreeSections(BNFirmwareNinjaSection *sections, int size);
8041-
BINARYNINJACOREAPI int BNFirmwareNinjaGetFunctionMemoryAccesses(BNFirmwareNinja* fn, BNFirmwareNinjaFunctionMemoryAccesses*** mmio, BNProgressFunction progress, void* progressContext);
8042-
BINARYNINJACOREAPI void BNFirmwareNinjaFreeFunctionMemoryAccesses(BNFirmwareNinjaFunctionMemoryAccesses **mmio, int size);
8043-
BINARYNINJACOREAPI void BNFirmwareNinjaStoreFunctionMemoryAccessesToMetadata(BNFirmwareNinja* fn, BNFirmwareNinjaFunctionMemoryAccesses** mmio, int size);
8044-
BINARYNINJACOREAPI int BNFirmwareNinjaQueryFunctionMemoryAccessesFromMetadata(BNFirmwareNinja* fn, BNFirmwareNinjaFunctionMemoryAccesses*** mmio);
8045-
BINARYNINJACOREAPI int BNFirmwareNinjaGetBoardDeviceAccesses(BNFirmwareNinja* fn, BNFirmwareNinjaFunctionMemoryAccesses** mmio, int size, BNFirmwareNinjaDeviceAccesses** accesses, BNArchitecture* arch);
8041+
BINARYNINJACOREAPI int BNFirmwareNinjaGetFunctionMemoryAccesses(BNFirmwareNinja* fn, BNFirmwareNinjaFunctionMemoryAccesses*** fma, BNProgressFunction progress, void* progressContext);
8042+
BINARYNINJACOREAPI void BNFirmwareNinjaFreeFunctionMemoryAccesses(BNFirmwareNinjaFunctionMemoryAccesses **fma, int size);
8043+
BINARYNINJACOREAPI void BNFirmwareNinjaStoreFunctionMemoryAccessesToMetadata(BNFirmwareNinja* fn, BNFirmwareNinjaFunctionMemoryAccesses** fma, int size);
8044+
BINARYNINJACOREAPI int BNFirmwareNinjaQueryFunctionMemoryAccessesFromMetadata(BNFirmwareNinja* fn, BNFirmwareNinjaFunctionMemoryAccesses*** fma);
8045+
BINARYNINJACOREAPI int BNFirmwareNinjaGetBoardDeviceAccesses(BNFirmwareNinja* fn, BNFirmwareNinjaFunctionMemoryAccesses** fma, int size, BNFirmwareNinjaDeviceAccesses** accesses, BNArchitecture* arch);
80468046
BINARYNINJACOREAPI void BNFirmwareNinjaFreeBoardDeviceAccesses(BNFirmwareNinjaDeviceAccesses *accesses, int size);
8047+
BINARYNINJACOREAPI BNFirmwareNinjaReferenceNode* BNFirmwareNinjaGetMemoryRegionReferenceTree(BNFirmwareNinja* fn, uint64_t start, uint64_t end, BNFirmwareNinjaFunctionMemoryAccesses** fma, int size, uint64_t* value);
8048+
BINARYNINJACOREAPI BNFirmwareNinjaReferenceNode* BNFirmwareNinjaGetAddressReferenceTree(BNFirmwareNinja* fn, uint64_t address, BNFirmwareNinjaFunctionMemoryAccesses** fma, int size, uint64_t* value);
8049+
8050+
BINARYNINJACOREAPI bool BNFirmwareNinjaReferenceNodeIsFunction(BNFirmwareNinjaReferenceNode* node);
8051+
BINARYNINJACOREAPI bool BNFirmwareNinjaReferenceNodeIsDataVariable(BNFirmwareNinjaReferenceNode* node);
8052+
BINARYNINJACOREAPI bool BNFirmwareNinjaReferenceNodeHasChildren(BNFirmwareNinjaReferenceNode* node);
8053+
BINARYNINJACOREAPI BNFunction* BNFirmwareNinjaReferenceNodeGetFunction(BNFirmwareNinjaReferenceNode* node);
8054+
BINARYNINJACOREAPI BNDataVariable* BNFirmwareNinjaReferenceNodeGetDataVariable(BNFirmwareNinjaReferenceNode* node);
8055+
BINARYNINJACOREAPI BNFirmwareNinjaReferenceNode** BNFirmwareNinjaReferenceNodeGetChildren(BNFirmwareNinjaReferenceNode* parent, size_t* count);
8056+
BINARYNINJACOREAPI void BNFreeFirmwareNinjaReferenceNode(BNFirmwareNinjaReferenceNode* node);
8057+
BINARYNINJACOREAPI BNFirmwareNinjaReferenceNode* BNNewFirmwareNinjaReferenceNodeReference(BNFirmwareNinjaReferenceNode* node);
8058+
BINARYNINJACOREAPI void BNFreeFirmwareNinjaReferenceNodes(BNFirmwareNinjaReferenceNode** nodes, size_t count);
80478059
#ifdef __cplusplus
80488060
}
80498061
#endif

firmwareninja.cpp

Lines changed: 134 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,83 @@ static void FreeMemoryInfoArray(BNFirmwareNinjaFunctionMemoryAccesses** fma, siz
5858
}
5959

6060

61+
FirmwareNinjaReferenceNode::FirmwareNinjaReferenceNode(BNFirmwareNinjaReferenceNode* node)
62+
{
63+
m_object = node;
64+
}
65+
66+
67+
FirmwareNinjaReferenceNode::~FirmwareNinjaReferenceNode()
68+
{
69+
BNFreeFirmwareNinjaReferenceNode(m_object);
70+
}
71+
72+
73+
bool FirmwareNinjaReferenceNode::IsFunction()
74+
{
75+
return BNFirmwareNinjaReferenceNodeIsFunction(m_object);
76+
}
77+
78+
79+
bool FirmwareNinjaReferenceNode::IsDataVariable()
80+
{
81+
return BNFirmwareNinjaReferenceNodeIsDataVariable(m_object);
82+
}
83+
84+
85+
bool FirmwareNinjaReferenceNode::HasChildren()
86+
{
87+
return BNFirmwareNinjaReferenceNodeHasChildren(m_object);
88+
}
89+
90+
91+
bool FirmwareNinjaReferenceNode::GetFunction(Ref<Function>& function)
92+
{
93+
auto bnFunction = BNFirmwareNinjaReferenceNodeGetFunction(m_object);
94+
if (!bnFunction)
95+
return false;
96+
97+
function = new Function(BNNewFunctionReference(bnFunction));
98+
return true;
99+
}
100+
101+
102+
bool FirmwareNinjaReferenceNode::GetDataVariable(DataVariable& variable)
103+
{
104+
auto bnVariable = BNFirmwareNinjaReferenceNodeGetDataVariable(m_object);
105+
if (!bnVariable)
106+
return false;
107+
108+
variable.address = bnVariable->address;
109+
variable.type = Confidence(new Type(BNNewTypeReference(bnVariable->type)), bnVariable->typeConfidence);
110+
variable.autoDiscovered = bnVariable->autoDiscovered;
111+
BNFreeDataVariable(bnVariable);
112+
return true;
113+
}
114+
115+
116+
std::vector<Ref<FirmwareNinjaReferenceNode>> FirmwareNinjaReferenceNode::GetChildren()
117+
{
118+
std::vector<Ref<FirmwareNinjaReferenceNode>> result;
119+
size_t count = 0;
120+
auto bnChildren = BNFirmwareNinjaReferenceNodeGetChildren(m_object, &count);
121+
result.reserve(count);
122+
for (size_t i = 0; i < count; ++i)
123+
{
124+
result.push_back(new FirmwareNinjaReferenceNode(
125+
BNNewFirmwareNinjaReferenceNodeReference(bnChildren[i])));
126+
}
127+
128+
if (count)
129+
BNFreeFirmwareNinjaReferenceNodes(bnChildren, count);
130+
return result;
131+
}
132+
133+
61134
FirmwareNinja::FirmwareNinja(Ref<BinaryView> view)
62135
{
63136
m_view = view;
64-
m_object = BNCreateFirmwareNinja(view->GetObject());
137+
m_object = BNCreateFirmwareNinja(view->GetObject());
65138
}
66139

67140

@@ -218,6 +291,9 @@ std::vector<FirmwareNinjaFunctionMemoryAccesses> FirmwareNinja::GetFunctionMemor
218291

219292
void FirmwareNinja::StoreFunctionMemoryAccesses(const std::vector<FirmwareNinjaFunctionMemoryAccesses>& fma)
220293
{
294+
if (fma.empty())
295+
return;
296+
221297
BNFirmwareNinjaFunctionMemoryAccesses** fmaArray = MemoryInfoVectorToArray(fma);
222298
BNFirmwareNinjaStoreFunctionMemoryAccessesToMetadata(m_object, fmaArray, fma.size());
223299
FreeMemoryInfoArray(fmaArray, fma.size());
@@ -262,6 +338,9 @@ std::vector<FirmwareNinjaDeviceAccesses> FirmwareNinja::GetBoardDeviceAccesses(
262338
const std::vector<FirmwareNinjaFunctionMemoryAccesses>& fma)
263339
{
264340
std::vector<FirmwareNinjaDeviceAccesses> result;
341+
if (fma.empty())
342+
return result;
343+
265344
auto platform = m_view->GetDefaultPlatform();
266345
if (!platform)
267346
return result;
@@ -273,11 +352,9 @@ std::vector<FirmwareNinjaDeviceAccesses> FirmwareNinja::GetBoardDeviceAccesses(
273352
BNFirmwareNinjaFunctionMemoryAccesses** fmaArray = MemoryInfoVectorToArray(fma);
274353
BNFirmwareNinjaDeviceAccesses* accesses;
275354
int count = BNFirmwareNinjaGetBoardDeviceAccesses(m_object, fmaArray, fma.size(), &accesses, arch->GetObject());
355+
FreeMemoryInfoArray(fmaArray, fma.size());
276356
if (count <= 0)
277-
{
278-
FreeMemoryInfoArray(fmaArray, fma.size());
279357
return result;
280-
}
281358

282359
result.reserve(count);
283360
for (size_t i = 0; i < count; i++)
@@ -290,3 +367,56 @@ std::vector<FirmwareNinjaDeviceAccesses> FirmwareNinja::GetBoardDeviceAccesses(
290367

291368
return result;
292369
}
370+
371+
372+
Ref<FirmwareNinjaReferenceNode> FirmwareNinja::GetReferenceTree(
373+
FirmwareNinjaDevice& device, const std::vector<FirmwareNinjaFunctionMemoryAccesses>& fma, uint64_t* value)
374+
{
375+
BNFirmwareNinjaFunctionMemoryAccesses** fmaArray = nullptr;
376+
if (!fma.empty())
377+
fmaArray = MemoryInfoVectorToArray(fma);
378+
379+
auto bnReferenceTree = BNFirmwareNinjaGetMemoryRegionReferenceTree(
380+
m_object, device.start, device.end, fmaArray, fma.size(), value);
381+
382+
FreeMemoryInfoArray(fmaArray, fma.size());
383+
if (!bnReferenceTree)
384+
return nullptr;
385+
386+
return new FirmwareNinjaReferenceNode(bnReferenceTree);
387+
}
388+
389+
390+
Ref<FirmwareNinjaReferenceNode> FirmwareNinja::GetReferenceTree(
391+
Section& section, const std::vector<FirmwareNinjaFunctionMemoryAccesses>& fma, uint64_t* value)
392+
{
393+
BNFirmwareNinjaFunctionMemoryAccesses** fmaArray = nullptr;
394+
if (!fma.empty())
395+
fmaArray = MemoryInfoVectorToArray(fma);
396+
397+
auto bnReferenceTree = BNFirmwareNinjaGetMemoryRegionReferenceTree(
398+
m_object, section.GetStart(), section.GetStart() + section.GetLength(), fmaArray, fma.size(), value);
399+
400+
FreeMemoryInfoArray(fmaArray, fma.size());
401+
if (!bnReferenceTree)
402+
return nullptr;
403+
404+
return new FirmwareNinjaReferenceNode(bnReferenceTree);
405+
}
406+
407+
408+
Ref<FirmwareNinjaReferenceNode> FirmwareNinja::GetReferenceTree(
409+
uint64_t address, const std::vector<FirmwareNinjaFunctionMemoryAccesses>& fma, uint64_t* value)
410+
{
411+
BNFirmwareNinjaFunctionMemoryAccesses** fmaArray = nullptr;
412+
if (!fma.empty())
413+
fmaArray = MemoryInfoVectorToArray(fma);
414+
415+
auto bnReferenceTree = BNFirmwareNinjaGetAddressReferenceTree(m_object, address, fmaArray, fma.size(), value);
416+
417+
FreeMemoryInfoArray(fmaArray, fma.size());
418+
if (!bnReferenceTree)
419+
return nullptr;
420+
421+
return new FirmwareNinjaReferenceNode(bnReferenceTree);
422+
}

0 commit comments

Comments
 (0)