From 56d270363e63b45c2032f4e73d02f9e2a92c76c2 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 30 May 2016 04:20:27 -0400 Subject: Add APIs for querying stack variable values and parameters by index --- python/__init__.py | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 821e3f41..6776ef09 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -2292,7 +2292,7 @@ class Function(object): def get_reg_value_at_low_level_il_instruction(self, i, reg): if isinstance(reg, str): reg = self.arch.regs[reg].index - value = core.BNGetRegisterValueAtInstruction(self.handle, self.arch.handle, i, reg) + value = core.BNGetRegisterValueAtLowLevelILInstruction(self.handle, i, reg) result = RegisterValue(self.arch, value) core.BNFreeRegisterValue(value) return result @@ -2300,7 +2300,55 @@ class Function(object): def get_reg_value_after_low_level_il_instruction(self, i, reg): if isinstance(reg, str): reg = self.arch.regs[reg].index - value = core.BNGetRegisterValueAfterInstruction(self.handle, self.arch.handle, i, reg) + value = core.BNGetRegisterValueAfterLowLevelILInstruction(self.handle, i, reg) + result = RegisterValue(self.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_stack_contents_at(self, arch, addr, offset, size): + if isinstance(reg, str): + reg = arch.regs[reg].index + value = core.BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size) + result = RegisterValue(arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_stack_contents_after(self, arch, addr, offset, size): + if isinstance(reg, str): + reg = arch.regs[reg].index + value = core.BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, reg) + result = RegisterValue(arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_stack_contents_at_low_level_il_instruction(self, i, offset, size): + if isinstance(reg, str): + reg = self.arch.regs[reg].index + value = core.BNGetStackContentsAtLowLevelILInstruction(self.handle, i, offset, size) + result = RegisterValue(self.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_stack_contents_after_low_level_il_instruction(self, i, offset, size): + if isinstance(reg, str): + reg = self.arch.regs[reg].index + value = core.BNGetStackContentsAfterInstruction(self.handle, i, offset, size) + result = RegisterValue(self.arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_parameter_at(self, arch, addr, func_type, i): + if func_type is not None: + func_type = func_type.handle + value = core.BNGetParameterValueAtInstruction(self.handle, arch.handle, addr, func_type, i) + result = RegisterValue(arch, value) + core.BNFreeRegisterValue(value) + return result + + def get_parameter_at_low_level_il_instruction(self, instr, func_type, i): + if func_type is not None: + func_type = func_type.handle + value = core.BNGetParameterValueAtLowLevelILInstruction(self.handle, instr, func_type, i) result = RegisterValue(self.arch, value) core.BNFreeRegisterValue(value) return result -- cgit v1.3.1 From 4dc7c3041e7c95e373b55dbb27b1861e82976fc0 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Mon, 30 May 2016 22:40:24 -0400 Subject: Add IL instruction to promote bool to int, used for MIPS jump tables --- binaryninjaapi.h | 1 + binaryninjacore.h | 1 + lowlevelil.cpp | 6 ++++++ python/__init__.py | 1 + 4 files changed, 9 insertions(+) (limited to 'python/__init__.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 7ece4c4d..72240975 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1545,6 +1545,7 @@ namespace BinaryNinja ExprId CompareSignedGreaterThan(size_t size, ExprId a, ExprId b); ExprId CompareUnsignedGreaterThan(size_t size, ExprId a, ExprId b); ExprId TestBit(size_t size, ExprId a, ExprId b); + ExprId BoolToInt(size_t size, ExprId a); ExprId SystemCall(); ExprId Breakpoint(); ExprId Trap(uint32_t num); diff --git a/binaryninjacore.h b/binaryninjacore.h index 41388a98..cbbfcfa8 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -245,6 +245,7 @@ extern "C" LLIL_CMP_SGT, LLIL_CMP_UGT, LLIL_TEST_BIT, + LLIL_BOOL_TO_INT, LLIL_SYSCALL, LLIL_BP, LLIL_TRAP, diff --git a/lowlevelil.cpp b/lowlevelil.cpp index d86bb523..550accc2 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -428,6 +428,12 @@ ExprId LowLevelILFunction::TestBit(size_t size, ExprId a, ExprId b) } +ExprId LowLevelILFunction::BoolToInt(size_t size, ExprId a) +{ + return AddExpr(LLIL_BOOL_TO_INT, size, 0, a); +} + + ExprId LowLevelILFunction::SystemCall() { return AddExpr(LLIL_SYSCALL, 0, 0); diff --git a/python/__init__.py b/python/__init__.py index 6776ef09..75d114cd 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -3987,6 +3987,7 @@ class LowLevelILInstruction(object): core.LLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], core.LLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], core.LLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], + core.LLIL_BOOL_TO_INT: [("src", "expr")], core.LLIL_SYSCALL: [], core.LLIL_BP: [], core.LLIL_TRAP: [("value", "int")], -- cgit v1.3.1 From 51b6c971f9c014e2fcd734a5230e09ddc5d70753 Mon Sep 17 00:00:00 2001 From: Ryan Stortz Date: Thu, 2 Jun 2016 21:13:09 -0400 Subject: get_stack_contents_at* referenced an undefined variable --- python/__init__.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'python/__init__.py') diff --git a/python/__init__.py b/python/__init__.py index 75d114cd..8024cae8 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -2306,32 +2306,24 @@ class Function(object): return result def get_stack_contents_at(self, arch, addr, offset, size): - if isinstance(reg, str): - reg = arch.regs[reg].index value = core.BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size) result = RegisterValue(arch, value) core.BNFreeRegisterValue(value) return result def get_stack_contents_after(self, arch, addr, offset, size): - if isinstance(reg, str): - reg = arch.regs[reg].index - value = core.BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, reg) + value = core.BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, offset, size) result = RegisterValue(arch, value) core.BNFreeRegisterValue(value) return result def get_stack_contents_at_low_level_il_instruction(self, i, offset, size): - if isinstance(reg, str): - reg = self.arch.regs[reg].index value = core.BNGetStackContentsAtLowLevelILInstruction(self.handle, i, offset, size) result = RegisterValue(self.arch, value) core.BNFreeRegisterValue(value) return result def get_stack_contents_after_low_level_il_instruction(self, i, offset, size): - if isinstance(reg, str): - reg = self.arch.regs[reg].index value = core.BNGetStackContentsAfterInstruction(self.handle, i, offset, size) result = RegisterValue(self.arch, value) core.BNFreeRegisterValue(value) -- cgit v1.3.1 From 3d7bb5ada00ac4650a916cdb59d3418e5db7f3eb Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Wed, 29 Jun 2016 16:41:36 -0400 Subject: Add analysis completion event and wait API --- binaryninjaapi.h | 16 ++++++++++++++++ binaryninjacore.h | 7 +++++++ binaryview.cpp | 30 ++++++++++++++++++++++++++++++ python/__init__.py | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) (limited to 'python/__init__.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 72240975..f7d260a1 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -571,6 +571,20 @@ namespace BinaryNinja uint64_t addr; }; + class AnalysisCompletionEvent: public CoreRefCountObject + { + protected: + std::function m_callback; + std::recursive_mutex m_mutex; + + static void CompletionCallback(void* ctxt); + + public: + AnalysisCompletionEvent(BinaryView* view, const std::function& callback); + void Cancel(); + }; + class BinaryView: public CoreRefCountObject { protected: @@ -740,6 +754,8 @@ namespace BinaryNinja std::vector GetStrings(); std::vector GetStrings(uint64_t start, uint64_t len); + + Ref AddAnalysisCompletionEvent(const std::function& callback); }; class BinaryData: public BinaryView diff --git a/binaryninjacore.h b/binaryninjacore.h index cbbfcfa8..20f1b204 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -95,6 +95,7 @@ extern "C" struct BNEnumeration; struct BNCallingConvention; struct BNPlatform; + struct BNAnalysisCompletionEvent; enum BNLogLevel { @@ -1203,6 +1204,12 @@ extern "C" uint64_t addr, size_t* count); BINARYNINJACOREAPI void BNFreeInstructionTextLines(BNInstructionTextLine* lines, size_t count); + BINARYNINJACOREAPI BNAnalysisCompletionEvent* BNAddAnalysisCompletionEvent(BNBinaryView* view, void* ctxt, + void (*callback)(void* ctxt)); + BINARYNINJACOREAPI BNAnalysisCompletionEvent* BNNewAnalysisCompletionEventReference(BNAnalysisCompletionEvent* event); + BINARYNINJACOREAPI void BNFreeAnalysisCompletionEvent(BNAnalysisCompletionEvent* event); + BINARYNINJACOREAPI void BNCancelAnalysisCompletionEvent(BNAnalysisCompletionEvent* event); + // Function graph BINARYNINJACOREAPI BNFunctionGraph* BNCreateFunctionGraph(BNFunction* func); BINARYNINJACOREAPI BNFunctionGraph* BNNewFunctionGraphReference(BNFunctionGraph* graph); diff --git a/binaryview.cpp b/binaryview.cpp index 21a502ba..9a9461a4 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -180,6 +180,30 @@ Ref Symbol::ImportedFunctionFromImportAddressSymbol(Symbol* sym, uint64_ } +AnalysisCompletionEvent::AnalysisCompletionEvent(BinaryView* view, const std::function& callback): + m_callback(callback) +{ + m_object = BNAddAnalysisCompletionEvent(view->GetObject(), this, CompletionCallback); +} + + +void AnalysisCompletionEvent::CompletionCallback(void* ctxt) +{ + AnalysisCompletionEvent* event = (AnalysisCompletionEvent*)ctxt; + + unique_lock lock(event->m_mutex); + event->m_callback(); + event->m_callback = []() {}; +} + + +void AnalysisCompletionEvent::Cancel() +{ + unique_lock lock(m_mutex); + m_callback = []() {}; +} + + BinaryView::BinaryView(const std::string& typeName, FileMetadata* file) { BNCustomBinaryView view; @@ -1064,6 +1088,12 @@ vector BinaryView::GetStrings(uint64_t start, uint64_t len) } +Ref BinaryView::AddAnalysisCompletionEvent(const function& callback) +{ + return new AnalysisCompletionEvent(this, callback); +} + + BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject())) { } diff --git a/python/__init__.py b/python/__init__.py index 8024cae8..3d2123b3 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -627,6 +627,29 @@ class BinaryViewType(object): except AttributeError: raise AttributeError, "attribute '%s' is read only" % name +class AnalysisCompletionEvent(object): + def __init__(self, view, callback): + self.view = view + self.callback = callback + self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._notify) + self.handle = core.BNAddAnalysisCompletionEvent(self.view.handle, None, self._cb) + + def __del__(self): + core.BNFreeAnalysisCompletionEvent(self.handle) + + def _notify(self, ctxt): + try: + self.callback() + except: + log_error(traceback.format_exc()) + + def _empty_callback(self): + pass + + def cancel(self): + self.callback = self._empty_callback + core.BNCancelAnalysisCompletionEvent(self.handle) + class BinaryView(object): name = None """Binary View name""" @@ -1252,6 +1275,29 @@ class BinaryView(object): def update_analysis(self): core.BNUpdateAnalysis(self.handle) + def update_analysis_and_wait(self): + class WaitEvent: + def __init__(self): + self.cond = threading.Condition() + self.done = False + + def complete(self): + self.cond.acquire() + self.done = True + self.cond.notify() + self.cond.release() + + def wait(self): + self.cond.acquire() + while not self.done: + self.cond.wait() + self.cond.release() + + wait = WaitEvent() + event = AnalysisCompletionEvent(self, lambda: wait.complete()) + core.BNUpdateAnalysis(self.handle) + wait.wait() + def abort_analysis(self): core.BNAbortAnalysis(self.handle) @@ -1428,6 +1474,9 @@ class BinaryView(object): core.BNFreeStringList(strings) return result + def add_analysis_completion_event(self, callback): + return AnalysisCompletionEvent(self, callback) + def __setattr__(self, name, value): try: object.__setattr__(self,name,value) -- cgit v1.3.1 From a7eaa72caa4a5e3e7cd7ea7c32236c93b06d1442 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Thu, 30 Jun 2016 17:15:19 -0400 Subject: Add API for analysis progress --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 15 +++++++++++++++ binaryview.cpp | 6 ++++++ python/__init__.py | 22 ++++++++++++++++++++++ 4 files changed, 45 insertions(+) (limited to 'python/__init__.py') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index f0ad784f..3f0b1f4b 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -809,6 +809,8 @@ namespace BinaryNinja std::vector GetStrings(uint64_t start, uint64_t len); Ref AddAnalysisCompletionEvent(const std::function& callback); + + BNAnalysisProgress GetAnalysisProgress(); }; class BinaryData: public BinaryView diff --git a/binaryninjacore.h b/binaryninjacore.h index 6a1e6a63..048255b1 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -735,6 +735,19 @@ extern "C" uint64_t address; }; + enum BNAnalysisState + { + IdleState, + DisassembleState, + AnalyzeState + }; + + struct BNAnalysisProgress + { + BNAnalysisState state; + size_t count, total; + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); @@ -1211,6 +1224,8 @@ extern "C" BINARYNINJACOREAPI void BNFreeAnalysisCompletionEvent(BNAnalysisCompletionEvent* event); BINARYNINJACOREAPI void BNCancelAnalysisCompletionEvent(BNAnalysisCompletionEvent* event); + BINARYNINJACOREAPI BNAnalysisProgress BNGetAnalysisProgress(BNBinaryView* view); + // Function graph BINARYNINJACOREAPI BNFunctionGraph* BNCreateFunctionGraph(BNFunction* func); BINARYNINJACOREAPI BNFunctionGraph* BNNewFunctionGraphReference(BNFunctionGraph* graph); diff --git a/binaryview.cpp b/binaryview.cpp index 9a9461a4..a3abc02a 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1094,6 +1094,12 @@ Ref BinaryView::AddAnalysisCompletionEvent(const functi } +BNAnalysisProgress BinaryView::GetAnalysisProgress() +{ + return BNGetAnalysisProgress(m_object); +} + + BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject())) { } diff --git a/python/__init__.py b/python/__init__.py index 3d2123b3..e07bd7c5 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -650,6 +650,22 @@ class AnalysisCompletionEvent(object): self.callback = self._empty_callback core.BNCancelAnalysisCompletionEvent(self.handle) +class AnalysisProgress(object): + def __init__(self, state, count, total): + self.state = state + self.count = count + self.total = total + + def __str__(self): + if self.state == core.DisassembleState: + return "Disassembling (%d/%d)" % (self.count, self.total) + if self.state == core.AnalyzeState: + return "Analyzing (%d/%d)" % (self.count, self.total) + return "Idle" + + def __repr__(self): + return "" % str(self) + class BinaryView(object): name = None """Binary View name""" @@ -928,6 +944,12 @@ class BinaryView(object): def saved(self, value): self.file.saved = value + @property + def analysis_progress(self): + """Status of current analysis (read-only)""" + result = core.BNGetAnalysisProgress(self.handle) + return AnalysisProgress(result.state, result.count, result.total) + def __len__(self): return int(core.BNGetViewLength(self.handle)) -- cgit v1.3.1