diff options
| author | Zichuan Li <lizic@iu.edu> | 2024-05-21 17:56:03 -0400 |
|---|---|---|
| committer | Zichuan Li <34680029+river-li@users.noreply.github.com> | 2024-05-28 12:22:23 -0400 |
| commit | 9537f33da6b8de883a45c4b7758f0dc5c1438ed7 (patch) | |
| tree | 08e9844aab5b9e830d9b30303b59fd0f022bea5a | |
| parent | 2a6cef7eac64dc3df4a17ba3dc73fb5e1046fc29 (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.h | 11 | ||||
| -rw-r--r-- | binaryninjacore.h | 2 | ||||
| -rw-r--r-- | binaryview.cpp | 21 | ||||
| -rw-r--r-- | examples/bin-info/src/bin-info.cpp | 7 | ||||
| -rw-r--r-- | python/binaryview.py | 48 | ||||
| -rw-r--r-- | rust/src/binaryview.rs | 9 | ||||
| -rw-r--r-- | view/elf/elfview.cpp | 10 | ||||
| -rw-r--r-- | view/pe/peview.cpp | 2 |
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!", |
