summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZichuan Li <lizic@iu.edu>2024-05-21 17:56:03 -0400
committerZichuan Li <34680029+river-li@users.noreply.github.com>2024-05-28 12:22:23 -0400
commit9537f33da6b8de883a45c4b7758f0dc5c1438ed7 (patch)
tree08e9844aab5b9e830d9b30303b59fd0f022bea5a
parent2a6cef7eac64dc3df4a17ba3dc73fb5e1046fc29 (diff)
Solved issue #1180 by adding new APIs
1. Add two new APIs for multiple entry functions `GetAllAnalysisEntryFunctions` and `AddToEntryFunctions` 2. Add Python APIs `entry_functions` and `add_to_entry_functions`. `entry_functions` resturns a list of functions, which supports parsing functions in `init_array`, `fini_array` and TLS callbacks. 3. Modify bin-info, it now prints all entry functions
-rw-r--r--binaryninjaapi.h11
-rw-r--r--binaryninjacore.h2
-rw-r--r--binaryview.cpp21
-rw-r--r--examples/bin-info/src/bin-info.cpp7
-rw-r--r--python/binaryview.py48
-rw-r--r--rust/src/binaryview.rs9
-rw-r--r--view/elf/elfview.cpp10
-rw-r--r--view/pe/peview.cpp2
8 files changed, 108 insertions, 2 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 55b8ef55..114b6e85 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -4946,6 +4946,12 @@ namespace BinaryNinja {
*/
void AddEntryPointForAnalysis(Platform* platform, uint64_t start);
+ /*! adds an function to all entry function list
+
+ \param func Function to add
+ */
+ void AddToEntryFunctions(Function* func);
+
/*! removes a function from the list of functions
\param func Function to be removed
@@ -5089,6 +5095,11 @@ namespace BinaryNinja {
*/
Ref<Function> GetAnalysisEntryPoint();
+ /*! Get all entry functions (including user-defined ones)
+
+ \return vector of Functions
+ */
+ std::vector<Ref<Function>> GetAllEntryFunctions();
/*! Get most recently used Basic Block containing a virtual address
diff --git a/binaryninjacore.h b/binaryninjacore.h
index 35e69541..a7b968e6 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -4222,6 +4222,8 @@ extern "C"
BINARYNINJACOREAPI BNFunction** BNGetAnalysisFunctionsContainingAddress(
BNBinaryView* view, uint64_t addr, size_t* count);
BINARYNINJACOREAPI BNFunction* BNGetAnalysisEntryPoint(BNBinaryView* view);
+ BINARYNINJACOREAPI BNFunction** BNGetAllEntryFunctions(BNBinaryView* view, size_t* count);
+ BINARYNINJACOREAPI void BNAddToEntryFunctions(BNBinaryView* view, BNFunction* func);
BINARYNINJACOREAPI char* BNGetGlobalCommentForAddress(BNBinaryView* view, uint64_t addr);
BINARYNINJACOREAPI uint64_t* BNGetGlobalCommentedAddresses(BNBinaryView* view, size_t* count);
diff --git a/binaryview.cpp b/binaryview.cpp
index b5c34177..929d0fe9 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -1985,6 +1985,12 @@ void BinaryView::AddEntryPointForAnalysis(Platform* platform, uint64_t addr)
}
+void BinaryView::AddToEntryFunctions(Function* func)
+{
+ BNAddToEntryFunctions(m_object, func->GetObject());
+}
+
+
void BinaryView::RemoveAnalysisFunction(Function* func, bool updateRefs)
{
BNRemoveAnalysisFunction(m_object, func->GetObject(), updateRefs);
@@ -2208,6 +2214,21 @@ Ref<Function> BinaryView::GetAnalysisEntryPoint()
}
+vector<Ref<Function>> BinaryView::GetAllEntryFunctions()
+{
+ size_t count;
+ BNFunction** funcs = BNGetAllEntryFunctions(m_object, &count);
+ if (count == 0)
+ return {};
+
+ vector<Ref<Function>> result;
+ for (size_t i = 0; i < count; i++)
+ result.push_back(new Function(BNNewFunctionReference(funcs[i])));
+ BNFreeFunctionList(funcs, count);
+ return result;
+}
+
+
Ref<BasicBlock> BinaryView::GetRecentBasicBlockForAddress(uint64_t addr)
{
BNBasicBlock* block = BNGetRecentBasicBlockForAddress(m_object, addr);
diff --git a/examples/bin-info/src/bin-info.cpp b/examples/bin-info/src/bin-info.cpp
index b952694d..8e920156 100644
--- a/examples/bin-info/src/bin-info.cpp
+++ b/examples/bin-info/src/bin-info.cpp
@@ -58,6 +58,13 @@ int main(int argc, char* argv[])
cout << "PLATFORM: " << bv->GetDefaultPlatform()->GetName() << endl;
cout << endl;
+ cout << "------ALL ENTRY FUNCTIONS---------" << endl;
+ for (auto func : bv->GetAllEntryFunctions())
+ {
+ cout << hex << func->GetStart() << " " << func->GetSymbol()->GetFullName() << endl;
+ }
+ cout << endl;
+
cout << "---------- 10 Functions ----------" << endl;
int x = 0;
for (auto func : bv->GetAnalysisFunctionList())
diff --git a/python/binaryview.py b/python/binaryview.py
index 0df5a2b1..154b4f8e 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -3035,6 +3035,39 @@ class BinaryView:
return _function.Function(self, func)
@property
+ def entry_functions(self) -> FunctionList:
+ """A List of entry functions (read-only)
+ This list contains vanilla entry function, and functions like init_array, fini_arry, and TLS callbacks etc.
+ User-added entry functions(via `add_entry_point`) are also included.
+
+ We see `entry_functions` as good starting points for analysis, these functions normally don't have internal references.
+ However, note that exported functions in a dll/so file are not included.
+
+ Note the difference with `entry_function`
+
+ :Example:
+
+ >>> bv.entry_function
+ <func: x86@0x4014c8>
+ >>> bv.entry_functions
+ [<func: x86@0x4014c8>, <func: x86@0x401618>]
+
+ :return: a list of functions, containing the vanilla entry and other platform-specific entry functions
+ :rtype: list(Function)
+ """
+ count = ctypes.c_ulonglong(0)
+ funcs = core.BNGetAllEntryFunctions(self.handle, count)
+
+ assert funcs is not None, "core.BNGetAllEntryFunctions returned None"
+ result = []
+ try:
+ for i in range(0, count.value):
+ result.append(_function.Function(self, core.BNNewFunctionReference(funcs[i])))
+ return result
+ finally:
+ core.BNFreeFunctionList(funcs, count.value)
+
+ @property
def symbols(self) -> SymbolMapping:
"""
Dict of symbols (read-only)
@@ -4406,6 +4439,21 @@ class BinaryView:
raise ValueError("Provided platform is not of type `Platform`")
core.BNAddEntryPointForAnalysis(self.handle, plat.handle, addr)
+ def add_to_entry_functions(self, func: '_function.Function') -> None:
+ """
+ ``add_to_entry_functions`` adds a function to the `entry_functions` list.
+
+ :param Function func: a Function object
+ :rtype: None
+ :Example:
+ >>> bv.entry_functions
+ [<func: x86@0x4014c8>, <func: x86@0x401618>]
+ >>> bv.add_to_entry_functions(bv.get_function_at(0x4014da))
+ >>> bv.entry_functions
+ [<func: x86@0x4014c8>, <func: x86@0x401618>, <func: x86@0x4014da>]
+ """
+ core.BNAddToEntryFunctions(self.handle, func.handle)
+
def remove_function(self, func: '_function.Function', update_refs = False) -> None:
"""
``remove_function`` removes the function ``func`` from the list of functions
diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs
index aed2a454..25b3fbb2 100644
--- a/rust/src/binaryview.rs
+++ b/rust/src/binaryview.rs
@@ -942,6 +942,15 @@ pub trait BinaryViewExt: BinaryViewBase {
}
}
+ fn entry_point_functions(&self) -> Array<Function> {
+ unsafe {
+ let mut count = 0;
+ let functions = BNGetAllEntryFunctions(self.as_ref().handle, &mut count);
+
+ Array::new(functions, count, ())
+ }
+ }
+
fn functions(&self) -> Array<Function> {
unsafe {
let mut count = 0;
diff --git a/view/elf/elfview.cpp b/view/elf/elfview.cpp
index f938e978..a01d043b 100644
--- a/view/elf/elfview.cpp
+++ b/view/elf/elfview.cpp
@@ -1539,9 +1539,15 @@ bool ElfView::Init()
entry += imageBaseAdjustment;
Ref<Architecture> entryArch = entryPointArch->GetAssociatedArchitectureByAddress(entry);
if (entryArch != entryPointArch)
- AddFunctionForAnalysis(platform->GetRelatedPlatform(entryArch), entry);
+ {
+ auto func = AddFunctionForAnalysis(platform->GetRelatedPlatform(entryArch), entry);
+ AddToEntryFunctions(func);
+ }
else
- AddFunctionForAnalysis(platform, entry);
+ {
+ auto func = AddFunctionForAnalysis(platform, entry);
+ AddToEntryFunctions(func);
+ }
m_logger->LogDebug("Adding function start: %#" PRIx64 "\n", entry);
// name functions in .init_array, .fini_array, .ctors and .dtors
diff --git a/view/pe/peview.cpp b/view/pe/peview.cpp
index 89740413..bdf8175d 100644
--- a/view/pe/peview.cpp
+++ b/view/pe/peview.cpp
@@ -1920,6 +1920,8 @@ bool PEView::Init()
m_logger->LogInfo("Found TLS entrypoint %s: 0x%" PRIx64, name, address);
Ref<Platform> assPlatform = platform->GetAssociatedPlatformByAddress(address);
AddPESymbol(FunctionSymbol, "", name, address - m_imageBase);
+ auto func = AddFunctionForAnalysis(platform, address);
+ AddToEntryFunctions(func);
}
else
m_logger->LogInfo("Found TLS entrypoint %s: 0x%" PRIx64 " however it is not backed by file!",