summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2016-04-24 00:33:26 -0400
committerRusty Wagner <rusty@vector35.com>2016-04-24 00:33:26 -0400
commitc382a4610cc0ea7f8b8134b847d29bca7dc25398 (patch)
tree8dc2347b36c85b431164f435b78305a3c276230c
parent12217ad7a1d821c4d232e04da2c9ac4b4e365bf6 (diff)
Create API for adding known indirect branch targets
-rw-r--r--binaryninjaapi.h31
-rw-r--r--binaryninjacore.h36
-rw-r--r--function.cpp70
-rw-r--r--lowlevelil.cpp53
-rw-r--r--python/__init__.py74
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