diff options
| author | Rusty Wagner <rusty@vector35.com> | 2016-04-24 00:33:26 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2016-04-24 00:33:26 -0400 |
| commit | c382a4610cc0ea7f8b8134b847d29bca7dc25398 (patch) | |
| tree | 8dc2347b36c85b431164f435b78305a3c276230c | |
| parent | 12217ad7a1d821c4d232e04da2c9ac4b4e365bf6 (diff) | |
Create API for adding known indirect branch targets
| -rw-r--r-- | binaryninjaapi.h | 31 | ||||
| -rw-r--r-- | binaryninjacore.h | 36 | ||||
| -rw-r--r-- | function.cpp | 70 | ||||
| -rw-r--r-- | lowlevelil.cpp | 53 | ||||
| -rw-r--r-- | python/__init__.py | 74 |
5 files changed, 263 insertions, 1 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 8da02369..4ba49cdd 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1272,6 +1272,24 @@ namespace BinaryNinja int64_t referencedOffset; }; + struct IndirectBranchInfo + { + Ref<Architecture> sourceArch; + uint64_t sourceAddr; + Ref<Architecture> destArch; + uint64_t destAddr; + bool autoDefined; + }; + + struct ArchAndAddr + { + Ref<Architecture> arch; + uint64_t address; + + ArchAndAddr(): arch(nullptr), address(0) {} + ArchAndAddr(Architecture* a, uint64_t addr): arch(a), address(addr) {} + }; + class FunctionGraph; class Function: public CoreRefCountObject<BNFunction, BNNewFunctionReference, BNFreeFunction> @@ -1318,6 +1336,12 @@ namespace BinaryNinja void DeleteAutoStackVariable(int64_t offset); void DeleteUserStackVariable(int64_t offset); bool GetStackVariableAtFrameOffset(int64_t offset, StackVariable& var); + + void SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector<ArchAndAddr>& branches); + void SetUserIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector<ArchAndAddr>& branches); + + std::vector<IndirectBranchInfo> GetIndirectBranches(); + std::vector<IndirectBranchInfo> GetIndirectBranchesAt(Architecture* arch, uint64_t addr); }; struct FunctionGraphTextLine @@ -1404,6 +1428,9 @@ namespace BinaryNinja uint64_t GetCurrentAddress() const; void SetCurrentAddress(uint64_t addr); + void ClearIndirectBranches(); + void SetIndirectBranches(const std::vector<ArchAndAddr>& branches); + ExprId AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0); ExprId AddInstruction(ExprId expr); @@ -1476,6 +1503,10 @@ namespace BinaryNinja ExprId If(ExprId operand, BNLowLevelILLabel& t, BNLowLevelILLabel& f); void MarkLabel(BNLowLevelILLabel& label); + std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand); + ExprId AddLabelList(const std::vector<BNLowLevelILLabel*>& labels); + ExprId AddOperandList(const std::vector<ExprId> operands); + ExprId Operand(uint32_t n, ExprId expr); BNLowLevelILInstruction operator[](size_t i) const; diff --git a/binaryninjacore.h b/binaryninjacore.h index ba662049..aa8caa92 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -139,6 +139,7 @@ extern "C" CallDestination = 3, FunctionReturn = 4, SystemCall = 5, + IndirectBranch = 6, UnresolvedBranch = 127 }; @@ -226,6 +227,7 @@ extern "C" LLIL_SX, LLIL_ZX, LLIL_JUMP, + LLIL_JUMP_TO, LLIL_CALL, LLIL_RET, LLIL_NORET, @@ -667,6 +669,21 @@ extern "C" int64_t referencedOffset; }; + struct BNIndirectBranchInfo + { + BNArchitecture* sourceArch; + uint64_t sourceAddr; + BNArchitecture* destArch; + uint64_t destAddr; + bool autoDefined; + }; + + struct BNArchitectureAndAddress + { + BNArchitecture* arch; + uint64_t address; + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); @@ -1091,6 +1108,16 @@ extern "C" BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(BNFunction* func, int64_t offset, BNStackVariable* var); BINARYNINJACOREAPI void BNFreeStackVariable(BNStackVariable* var); + BINARYNINJACOREAPI void BNSetAutoIndirectBranches(BNFunction* func, BNArchitecture* sourceArch, uint64_t source, + BNArchitectureAndAddress* branches, size_t count); + BINARYNINJACOREAPI void BNSetUserIndirectBranches(BNFunction* func, BNArchitecture* sourceArch, uint64_t source, + BNArchitectureAndAddress* branches, size_t count); + + BINARYNINJACOREAPI BNIndirectBranchInfo* BNGetIndirectBranches(BNFunction* func, size_t* count); + BINARYNINJACOREAPI BNIndirectBranchInfo* BNGetIndirectBranchesAt(BNFunction* func, BNArchitecture* arch, + uint64_t addr, size_t* count); + BINARYNINJACOREAPI void BNFreeIndirectBranchList(BNIndirectBranchInfo* branches); + // Function graph BINARYNINJACOREAPI BNFunctionGraph* BNCreateFunctionGraph(BNFunction* func); BINARYNINJACOREAPI BNFunctionGraph* BNNewFunctionGraphReference(BNFunctionGraph* graph); @@ -1174,6 +1201,9 @@ extern "C" BINARYNINJACOREAPI void BNFreeLowLevelILFunction(BNLowLevelILFunction* func); BINARYNINJACOREAPI uint64_t BNLowLevelILGetCurrentAddress(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func, uint64_t addr); + BINARYNINJACOREAPI void BNLowLevelILClearIndirectBranches(BNLowLevelILFunction* func); + BINARYNINJACOREAPI void BNLowLevelILSetIndirectBranches(BNLowLevelILFunction* func, BNArchitectureAndAddress* branches, + size_t count); BINARYNINJACOREAPI size_t BNLowLevelILAddExpr(BNLowLevelILFunction* func, BNLowLevelILOperation operation, size_t size, uint32_t flags, uint64_t a, uint64_t b, uint64_t c, uint64_t d); BINARYNINJACOREAPI void BNLowLevelILSetExprSourceOperand(BNLowLevelILFunction* func, size_t expr, uint32_t operand); @@ -1184,6 +1214,12 @@ extern "C" BINARYNINJACOREAPI void BNLowLevelILMarkLabel(BNLowLevelILFunction* func, BNLowLevelILLabel* label); BINARYNINJACOREAPI void BNFinalizeLowLevelILFunction(BNLowLevelILFunction* func); + BINARYNINJACOREAPI size_t BNLowLevelILAddLabelList(BNLowLevelILFunction* func, BNLowLevelILLabel** labels, size_t count); + BINARYNINJACOREAPI size_t BNLowLevelILAddOperandList(BNLowLevelILFunction* func, uint64_t* operands, size_t count); + BINARYNINJACOREAPI uint64_t* BNLowLevelILGetOperandList(BNLowLevelILFunction* func, size_t expr, size_t operand, + size_t* count); + BINARYNINJACOREAPI void BNLowLevelILFreeOperandList(uint64_t* operands); + BINARYNINJACOREAPI BNLowLevelILInstruction BNGetLowLevelILByIndex(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILIndexForInstruction(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionCount(BNLowLevelILFunction* func); diff --git a/function.cpp b/function.cpp index 12f99d1f..8631eb0b 100644 --- a/function.cpp +++ b/function.cpp @@ -313,3 +313,73 @@ bool Function::GetStackVariableAtFrameOffset(int64_t offset, StackVariable& resu BNFreeStackVariable(&var); return true; } + + +void Function::SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector<ArchAndAddr>& branches) +{ + BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; + for (size_t i = 0; i < branches.size(); i++) + { + branchList[i].arch = branches[i].arch->GetObject(); + branchList[i].address = branches[i].address; + } + BNSetAutoIndirectBranches(m_object, sourceArch->GetObject(), source, branchList, branches.size()); + delete[] branchList; +} + + +void Function::SetUserIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector<ArchAndAddr>& branches) +{ + BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; + for (size_t i = 0; i < branches.size(); i++) + { + branchList[i].arch = branches[i].arch->GetObject(); + branchList[i].address = branches[i].address; + } + BNSetUserIndirectBranches(m_object, sourceArch->GetObject(), source, branchList, branches.size()); + delete[] branchList; +} + + +vector<IndirectBranchInfo> Function::GetIndirectBranches() +{ + size_t count; + BNIndirectBranchInfo* branches = BNGetIndirectBranches(m_object, &count); + + vector<IndirectBranchInfo> result; + for (size_t i = 0; i < count; i++) + { + IndirectBranchInfo b; + b.sourceArch = new CoreArchitecture(branches[i].sourceArch); + b.sourceAddr = branches[i].sourceAddr; + b.destArch = new CoreArchitecture(branches[i].destArch); + b.destAddr = branches[i].destAddr; + b.autoDefined = branches[i].autoDefined; + result.push_back(b); + } + + BNFreeIndirectBranchList(branches); + return result; +} + + +vector<IndirectBranchInfo> Function::GetIndirectBranchesAt(Architecture* arch, uint64_t addr) +{ + size_t count; + BNIndirectBranchInfo* branches = BNGetIndirectBranchesAt(m_object, arch->GetObject(), addr, &count); + + vector<IndirectBranchInfo> result; + for (size_t i = 0; i < count; i++) + { + IndirectBranchInfo b; + b.sourceArch = new CoreArchitecture(branches[i].sourceArch); + b.sourceAddr = branches[i].sourceAddr; + b.destArch = new CoreArchitecture(branches[i].destArch); + b.destAddr = branches[i].destAddr; + b.autoDefined = branches[i].autoDefined; + result.push_back(b); + } + + BNFreeIndirectBranchList(branches); + return result; +} diff --git a/lowlevelil.cpp b/lowlevelil.cpp index a006a581..a3d591a0 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -54,6 +54,25 @@ void LowLevelILFunction::SetCurrentAddress(uint64_t addr) } +void LowLevelILFunction::ClearIndirectBranches() +{ + BNLowLevelILClearIndirectBranches(m_object); +} + + +void LowLevelILFunction::SetIndirectBranches(const vector<ArchAndAddr>& branches) +{ + BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; + for (size_t i = 0; i < branches.size(); i++) + { + branchList[i].arch = branches[i].arch->GetObject(); + branchList[i].address = branches[i].address; + } + BNLowLevelILSetIndirectBranches(m_object, branchList, branches.size()); + delete[] branchList; +} + + ExprId LowLevelILFunction::AddExpr(BNLowLevelILOperation operation, size_t size, uint32_t flags, ExprId a, ExprId b, ExprId c, ExprId d) { @@ -463,6 +482,40 @@ void LowLevelILFunction::MarkLabel(BNLowLevelILLabel& label) } +vector<uint64_t> LowLevelILFunction::GetOperandList(ExprId i, size_t listOperand) +{ + size_t count; + uint64_t* operands = BNLowLevelILGetOperandList(m_object, i, listOperand, &count); + vector<uint64_t> result; + for (size_t i = 0; i < count; i++) + result.push_back(operands[i]); + BNLowLevelILFreeOperandList(operands); + return result; +} + + +ExprId LowLevelILFunction::AddLabelList(const vector<BNLowLevelILLabel*>& labels) +{ + BNLowLevelILLabel** labelList = new BNLowLevelILLabel*[labels.size()]; + for (size_t i = 0; i < labels.size(); i++) + labelList[i] = labels[i]; + ExprId result = (ExprId)BNLowLevelILAddLabelList(m_object, labelList, labels.size()); + delete[] labelList; + return result; +} + + +ExprId LowLevelILFunction::AddOperandList(const vector<ExprId> operands) +{ + uint64_t* operandList = new uint64_t[operands.size()]; + for (size_t i = 0; i < operands.size(); i++) + operandList[i] = operands[i]; + ExprId result = (ExprId)BNLowLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + ExprId LowLevelILFunction::Operand(uint32_t n, ExprId expr) { BNLowLevelILSetExprSourceOperand(m_object, expr, n); diff --git a/python/__init__.py b/python/__init__.py index a2769738..65477366 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1885,6 +1885,17 @@ class StackVariableReference: return "<operand %d ref to %s%+x>" % (self.source_operand, self.name, self.referenced_offset) return "<operand %d ref to %s>" % (self.source_operand, self.name) +class IndirectBranchInfo: + def __init__(self, source_arch, source_addr, dest_arch, dest_addr, auto_defined): + self.source_arch = source_arch + self.source_addr = source_addr + self.dest_arch = dest_arch + self.dest_addr = dest_addr + self.auto_defined = auto_defined + + def __repr__(self): + return "<branch %s:0x%x -> %s:0x%x>" % (self.source_arch.name, self.source_addr, self.dest_arch.name, self.dest_addr) + class Function: def __init__(self, view, handle): self._view = view @@ -1952,13 +1963,21 @@ class Function: result.sort(key = lambda x: x.offset) core.BNFreeStackLayout(v, count.value) return result + elif name == "indirect_branches": + count = ctypes.c_ulonglong() + branches = core.BNGetIndirectBranches(self.handle, count) + result = [] + for i in xrange(0, count.value): + result.append(IndirectBranchInfo(Architecture(branches[i].sourceArch), branches[i].sourceAddr, Architecture(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) + core.BNFreeIndirectBranchList(branches) + return result raise AttributeError, "no attribute '%s'" % name def __setattr__(self, name, value): if ((name == "view") or (name == "arch") or (name == "start") or (name == "symbol") or (name == "auto") or (name == "can_return") or (name == "basic_blocks") or (name == "comments") or (name == "low_level_il") or (name == "low_level_il_basic_blocks") or (name == "type") or (name == "explicitly_defined_type") or - (name == "stack_layout")): + (name == "stack_layout") or (name == "indirect_branches")): raise AttributeError, "attribute '%s' is read only" % name else: self.__dict__[name] = value @@ -2055,6 +2074,29 @@ class Function: def apply_auto_discovered_type(self, func_type): core.BNApplyAutoDiscoveredFunctionType(self.handle, func_type.handle) + def set_auto_indirect_branches(self, source_arch, source, branches): + branch_list = (core.BNArchitectureAndAddress * len(branches))() + for i in xrange(len(branches)): + branch_list[i].arch = branches[i][0].handle + branch_list[i].address = branches[i][1] + core.BNSetAutoIndirectBranches(self.handle, source_arch.handle, source, branch_list, len(branches)) + + def set_user_indirect_branches(self, source_arch, source, branches): + branch_list = (core.BNArchitectureAndAddress * len(branches))() + for i in xrange(len(branches)): + branch_list[i].arch = branches[i][0].handle + branch_list[i].address = branches[i][1] + core.BNSetUserIndirectBranches(self.handle, source_arch.handle, source, branch_list, len(branches)) + + def get_indirect_branches_at(self, arch, addr): + count = ctypes.c_ulonglong() + branches = core.BNGetIndirectBranchesAt(self.handle, arch.handle, addr, count) + result = [] + for i in xrange(0, count.value): + result.append(IndirectBranchInfo(Architecture(branches[i].sourceArch), branches[i].sourceAddr, Architecture(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) + core.BNFreeIndirectBranchList(branches) + return result + class BasicBlockEdge: def __init__(self, branch_type, target, arch): self.type = core.BNBranchType_names[branch_type] @@ -3289,6 +3331,7 @@ class LowLevelILInstruction: core.LLIL_SX: [("src", "expr")], core.LLIL_ZX: [("src", "expr")], core.LLIL_JUMP: [("dest", "expr")], + core.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], core.LLIL_CALL: [("dest", "expr")], core.LLIL_RET: [("dest", "expr")], core.LLIL_NORET: [], @@ -3346,6 +3389,13 @@ class LowLevelILInstruction: value = func.arch.get_flag_name(instr.operands[i]) elif operand_type == "cond": value = core.BNLowLevelILFlagCondition_names[instr.operands[i]] + elif operand_type == "int_list": + count = ctypes.c_ulonglong() + operands = core.BNLowLevelILGetOperandList(func.handle, self.index, i, count) + value = [] + for i in xrange(count.value): + value.append(operands[i]) + core.BNLowLevelILFreeOperandList(operands) self.operands.append(value) self.__dict__[name] = value @@ -3431,6 +3481,16 @@ class LowLevelILFunction: def __setitem__(self, i): raise IndexError, "instruction modification not implemented" + def clear_indirect_branches(self): + core.BNLowLevelILClearIndirectBranches(self.handle) + + def set_indirect_branches(self, branches): + branch_list = (core.BNArchitectureAndAddress * len(branches))() + for i in xrange(len(branches)): + branch_list[i].arch = branches[i][0].handle + branch_list[i].address = branches[i][1] + core.BNLowLevelILSetIndirectBranches(self.handle, branch_list, len(branches)) + def expr(self, operation, a = 0, b = 0, c = 0, d = 0, size = 0, flags = None): if isinstance(operation, str): operation = BNLowLevelILOperation_by_name[operation] @@ -3651,6 +3711,18 @@ class LowLevelILFunction: def mark_label(self, label): core.BNLowLevelILMarkLabel(self.handle, label.handle) + def add_label_list(self, labels): + label_list = (ctypes.POINTER(BNLowLevelILLabel) * len(labels))() + for i in xrange(len(labels)): + label_list[i] = labels[i].handle + return LowLevelILExpr(core.BNLowLevelILAddLabelList(self.handle, label_list, len(labels))) + + def add_operand_list(self, operands): + operand_list = (ctypes.c_ulonglong * len(operands))() + for i in xrange(len(operands)): + operand_list[i] = operands[i] + return LowLevelILExpr(core.BNLowLevelILAddOperandList(self.handle, operand_list, len(operands))) + def operand(self, n, expr): core.BNLowLevelILSetExprSourceOperand(self.handle, expr.index, n) return expr |
