diff options
| author | Rusty Wagner <rusty@vector35.com> | 2017-04-21 23:29:16 -0400 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2017-04-21 23:29:16 -0400 |
| commit | 87990dd2043a6234003620b6a408e5ae17c4eade (patch) | |
| tree | a77daf0d96f27aa037e76ea2ba868ce968271638 | |
| parent | 93020159006b68c5e0e5b1eafeef11d1df72da1a (diff) | |
| parent | 66c7accacdbc73ed4edb7e9bada54085a3272426 (diff) | |
Merge branch 'mlil' into dev
| -rw-r--r-- | binaryninjaapi.h | 187 | ||||
| -rw-r--r-- | binaryninjacore.h | 441 | ||||
| -rw-r--r-- | function.cpp | 238 | ||||
| -rw-r--r-- | lowlevelil.cpp | 260 | ||||
| -rw-r--r-- | mediumlevelil.cpp | 494 | ||||
| -rw-r--r-- | python/__init__.py | 1 | ||||
| -rw-r--r-- | python/function.py | 292 | ||||
| -rw-r--r-- | python/lowlevelil.py | 308 | ||||
| -rw-r--r-- | python/mediumlevelil.py | 735 |
9 files changed, 2732 insertions, 224 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index bab26345..ab84afc4 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1811,11 +1811,27 @@ namespace BinaryNinja static bool IsBackEdge(BasicBlock* source, BasicBlock* target); }; - struct StackVariable + struct Variable: public BNVariable { + Variable(); + Variable(BNVariableSourceType type, uint32_t index, uint64_t storage); + Variable(const BNVariable& var); + + Variable& operator=(const Variable& var); + + bool operator==(const Variable& var) const; + bool operator!=(const Variable& var) const; + bool operator<(const Variable& var) const; + + uint64_t ToIdentifier() const; + static Variable FromIdentifier(uint64_t id); + }; + + struct VariableNameAndType + { + Variable var; Ref<Type> type; std::string name; - int64_t offset; bool autoDefined; }; @@ -1824,7 +1840,7 @@ namespace BinaryNinja uint32_t sourceOperand; Ref<Type> type; std::string name; - int64_t startingOffset; + Variable var; int64_t referencedOffset; }; @@ -1855,13 +1871,24 @@ namespace BinaryNinja struct RegisterValue { BNRegisterValueType state; - uint32_t reg; // For EntryValue and OffsetFromEntryValue, the original input register - int64_t value; // Offset for OffsetFromEntryValue, StackFrameOffset or RangeValue, value of register for ConstantValue - uint64_t rangeStart, rangeEnd, rangeStep; // Range of register, inclusive + int64_t value; + + static RegisterValue FromAPIObject(BNRegisterValue& value); + }; + + struct PossibleValueSet + { + BNRegisterValueType state; + int64_t value; + std::vector<BNValueRange> ranges; + std::set<int64_t> valueSet; std::vector<LookupTableEntry> table; + + static PossibleValueSet FromAPIObject(BNPossibleValueSet& value); }; class FunctionGraph; + class MediumLevelILFunction; class Function: public CoreRefCountObject<BNFunction, BNNewFunctionReference, BNFreeFunction> { @@ -1893,12 +1920,8 @@ namespace BinaryNinja std::vector<size_t> GetLowLevelILExitsForInstruction(Architecture* arch, uint64_t addr); RegisterValue GetRegisterValueAtInstruction(Architecture* arch, uint64_t addr, uint32_t reg); RegisterValue GetRegisterValueAfterInstruction(Architecture* arch, uint64_t addr, uint32_t reg); - RegisterValue GetRegisterValueAtLowLevelILInstruction(size_t i, uint32_t reg); - RegisterValue GetRegisterValueAfterLowLevelILInstruction(size_t i, uint32_t reg); RegisterValue GetStackContentsAtInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size); RegisterValue GetStackContentsAfterInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size); - RegisterValue GetStackContentsAtLowLevelILInstruction(size_t i, int64_t offset, size_t size); - RegisterValue GetStackContentsAfterLowLevelILInstruction(size_t i, int64_t offset, size_t size); RegisterValue GetParameterValueAtInstruction(Architecture* arch, uint64_t addr, Type* functionType, size_t i); RegisterValue GetParameterValueAtLowLevelILInstruction(size_t instr, Type* functionType, size_t i); std::vector<uint32_t> GetRegistersReadByInstruction(Architecture* arch, uint64_t addr); @@ -1913,6 +1936,8 @@ namespace BinaryNinja std::set<uint32_t> GetFlagsReadByLiftedILInstruction(size_t i); std::set<uint32_t> GetFlagsWrittenByLiftedILInstruction(size_t i); + Ref<MediumLevelILFunction> GetMediumLevelIL() const; + Ref<Type> GetType() const; void SetAutoType(Type* type); void SetUserType(Type* type); @@ -1921,12 +1946,22 @@ namespace BinaryNinja Ref<FunctionGraph> CreateFunctionGraph(); - std::map<int64_t, StackVariable> GetStackLayout(); + std::map<int64_t, std::vector<VariableNameAndType>> GetStackLayout(); void CreateAutoStackVariable(int64_t offset, Ref<Type> type, const std::string& name); void CreateUserStackVariable(int64_t offset, Ref<Type> type, const std::string& name); void DeleteAutoStackVariable(int64_t offset); void DeleteUserStackVariable(int64_t offset); - bool GetStackVariableAtFrameOffset(int64_t offset, StackVariable& var); + bool GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, int64_t offset, VariableNameAndType& var); + + std::map<Variable, VariableNameAndType> GetVariables(); + void CreateAutoVariable(const Variable& var, Ref<Type> type, const std::string& name, + bool ignoreDisjointUses = false); + void CreateUserVariable(const Variable& var, Ref<Type> type, const std::string& name, + bool ignoreDisjointUses = false); + void DeleteAutoVariable(const Variable& var); + void DeleteUserVariable(const Variable& var); + Ref<Type> GetVariableType(const Variable& var); + std::string GetVariableName(const Variable& 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); @@ -2058,7 +2093,8 @@ namespace BinaryNinja LowLevelILFunction(BNLowLevelILFunction* func); uint64_t GetCurrentAddress() const; - void SetCurrentAddress(uint64_t addr); + void SetCurrentAddress(Architecture* arch, uint64_t addr); + size_t GetInstructionStart(Architecture* arch, uint64_t addr); void ClearIndirectBranches(); void SetIndirectBranches(const std::vector<ArchAndAddr>& branches); @@ -2145,6 +2181,7 @@ namespace BinaryNinja BNLowLevelILInstruction operator[](size_t i) const; size_t GetIndexForInstruction(size_t i) const; size_t GetInstructionCount() const; + size_t GetExprCount() const; void AddLabelForAddress(Architecture* arch, ExprId addr); BNLowLevelILLabel* GetLabelForAddress(Architecture* arch, ExprId addr); @@ -2159,6 +2196,130 @@ namespace BinaryNinja uint32_t GetTemporaryFlagCount(); std::vector<Ref<BasicBlock>> GetBasicBlocks() const; + + Ref<LowLevelILFunction> GetSSAForm() const; + Ref<LowLevelILFunction> GetNonSSAForm() const; + size_t GetSSAInstructionIndex(size_t instr) const; + size_t GetNonSSAInstructionIndex(size_t instr) const; + size_t GetSSAExprIndex(size_t instr) const; + size_t GetNonSSAExprIndex(size_t instr) const; + + size_t GetSSARegisterDefinition(uint32_t reg, size_t idx) const; + size_t GetSSAFlagDefinition(uint32_t flag, size_t idx) const; + size_t GetSSAMemoryDefinition(size_t idx) const; + std::set<size_t> GetSSARegisterUses(uint32_t reg, size_t idx) const; + std::set<size_t> GetSSAFlagUses(uint32_t flag, size_t idx) const; + std::set<size_t> GetSSAMemoryUses(size_t idx) const; + + RegisterValue GetSSARegisterValue(uint32_t reg, size_t idx); + RegisterValue GetSSAFlagValue(uint32_t flag, size_t idx); + + RegisterValue GetExprValue(size_t expr); + PossibleValueSet GetPossibleExprValues(size_t expr); + + RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); + RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); + PossibleValueSet GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr); + PossibleValueSet GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr); + RegisterValue GetFlagValueAtInstruction(uint32_t flag, size_t instr); + RegisterValue GetFlagValueAfterInstruction(uint32_t flag, size_t instr); + PossibleValueSet GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr); + PossibleValueSet GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr); + RegisterValue GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + RegisterValue GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); + PossibleValueSet GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + PossibleValueSet GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); + + Ref<MediumLevelILFunction> GetMediumLevelIL() const; + Ref<MediumLevelILFunction> GetMappedMediumLevelIL() const; + size_t GetMappedMediumLevelILInstructionIndex(size_t instr) const; + size_t GetMappedMediumLevelILExprIndex(size_t expr) const; + }; + + struct MediumLevelILLabel: public BNMediumLevelILLabel + { + MediumLevelILLabel(); + }; + + class MediumLevelILFunction: public CoreRefCountObject<BNMediumLevelILFunction, + BNNewMediumLevelILFunctionReference, BNFreeMediumLevelILFunction> + { + public: + MediumLevelILFunction(Architecture* arch, Function* func = nullptr); + MediumLevelILFunction(BNMediumLevelILFunction* func); + + uint64_t GetCurrentAddress() const; + void SetCurrentAddress(Architecture* arch, uint64_t addr); + size_t GetInstructionStart(Architecture* arch, uint64_t addr); + + ExprId AddExpr(BNMediumLevelILOperation operation, size_t size, + ExprId a = 0, ExprId b = 0, ExprId c = 0, ExprId d = 0, ExprId e = 0); + ExprId AddInstruction(ExprId expr); + + ExprId Goto(BNMediumLevelILLabel& label); + ExprId If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f); + void MarkLabel(BNMediumLevelILLabel& label); + + std::vector<uint64_t> GetOperandList(ExprId i, size_t listOperand); + ExprId AddLabelList(const std::vector<BNMediumLevelILLabel*>& labels); + ExprId AddOperandList(const std::vector<ExprId> operands); + + BNMediumLevelILInstruction operator[](size_t i) const; + size_t GetIndexForInstruction(size_t i) const; + size_t GetInstructionForExpr(size_t expr) const; + size_t GetInstructionCount() const; + size_t GetExprCount() const; + + void Finalize(); + + bool GetExprText(Architecture* arch, ExprId expr, std::vector<InstructionTextToken>& tokens); + bool GetInstructionText(Function* func, Architecture* arch, size_t i, + std::vector<InstructionTextToken>& tokens); + + std::vector<Ref<BasicBlock>> GetBasicBlocks() const; + + Ref<MediumLevelILFunction> GetSSAForm() const; + Ref<MediumLevelILFunction> GetNonSSAForm() const; + size_t GetSSAInstructionIndex(size_t instr) const; + size_t GetNonSSAInstructionIndex(size_t instr) const; + size_t GetSSAExprIndex(size_t instr) const; + size_t GetNonSSAExprIndex(size_t instr) const; + + size_t GetSSAVarDefinition(const Variable& var, size_t idx) const; + size_t GetSSAMemoryDefinition(size_t idx) const; + std::set<size_t> GetSSAVarUses(const Variable& var, size_t idx) const; + std::set<size_t> GetSSAMemoryUses(size_t idx) const; + + RegisterValue GetSSAVarValue(const Variable& var, size_t idx); + RegisterValue GetExprValue(size_t expr); + PossibleValueSet GetPossibleSSAVarValues(const Variable& var, size_t idx, size_t instr); + PossibleValueSet GetPossibleExprValues(size_t expr); + + size_t GetSSAVarIndexAtInstruction(const Variable& var, size_t instr) const; + size_t GetSSAMemoryIndexAtInstruction(size_t instr) const; + Variable GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const; + Variable GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const; + Variable GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const; + + RegisterValue GetRegisterValueAtInstruction(uint32_t reg, size_t instr); + RegisterValue GetRegisterValueAfterInstruction(uint32_t reg, size_t instr); + PossibleValueSet GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr); + PossibleValueSet GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr); + RegisterValue GetFlagValueAtInstruction(uint32_t flag, size_t instr); + RegisterValue GetFlagValueAfterInstruction(uint32_t flag, size_t instr); + PossibleValueSet GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr); + PossibleValueSet GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr); + RegisterValue GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + RegisterValue GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); + PossibleValueSet GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr); + PossibleValueSet GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr); + + BNILBranchDependence GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const; + std::map<size_t, BNILBranchDependence> GetAllBranchDependenceAtInstruction(size_t instr) const; + + Ref<LowLevelILFunction> GetLowLevelIL() const; + size_t GetLowLevelILInstructionIndex(size_t instr) const; + size_t GetLowLevelILExprIndex(size_t expr) const; }; class FunctionRecognizer diff --git a/binaryninjacore.h b/binaryninjacore.h index 0b2375ef..7e9a034f 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -66,6 +66,8 @@ #define BN_INVALID_OPERAND 0xffffffff +#define BN_INVALID_EXPR ((size_t)-1) + #define BN_DEFAULT_MIN_STRING_LENGTH 4 #define BN_MAX_STRING_LENGTH 128 @@ -87,6 +89,9 @@ #define LLVM_SVCS_RM_PIC 1 #define LLVM_SVCS_RM_DYNAMIC_NO_PIC 2 +#define BN_MAX_VARIABLE_OFFSET 0x7fffffffffLL +#define BN_MAX_VARIABLE_INDEX 0xfffff + #ifdef __cplusplus extern "C" { @@ -116,6 +121,7 @@ extern "C" struct BNSymbol; struct BNTemporaryFile; struct BNLowLevelILFunction; + struct BNMediumLevelILFunction; struct BNType; struct BNStructure; struct BNNamedTypeReference; @@ -211,7 +217,7 @@ extern "C" // not be used directly by the architecture plugins CodeSymbolToken = 64, DataSymbolToken = 65, - StackVariableToken = 66, + LocalVariableToken = 66, ImportToken = 67, AddressDisplayToken = 68 }; @@ -219,7 +225,7 @@ extern "C" enum BNInstructionTextTokenContext { NoTokenContext = 0, - StackVariableTokenContext = 1, + LocalVariableTokenContext = 1, DataVariableTokenContext = 2, FunctionReturnTokenContext = 3, ArgumentTokenContext = 4 @@ -235,8 +241,8 @@ extern "C" FunctionHeaderStartLineType, FunctionHeaderEndLineType, FunctionContinuationLineType, - StackVariableLineType, - StackVariableListEndLineType, + LocalVariableLineType, + LocalVariableListEndLineType, FunctionEndLineType, NoteStartLineType, NoteLineType, @@ -267,17 +273,17 @@ extern "C" enum BNLowLevelILOperation { LLIL_NOP, - LLIL_SET_REG, - LLIL_SET_REG_SPLIT, - LLIL_SET_FLAG, - LLIL_LOAD, - LLIL_STORE, - LLIL_PUSH, - LLIL_POP, - LLIL_REG, + LLIL_SET_REG, // Not valid in SSA form (see LLIL_SET_REG_SSA) + LLIL_SET_REG_SPLIT, // Not valid in SSA form (see LLIL_SET_REG_SPLIT_SSA) + LLIL_SET_FLAG, // Not valid in SSA form (see LLIL_SET_FLAG_SSA) + LLIL_LOAD, // Not valid in SSA form (see LLIL_LOAD_SSA) + LLIL_STORE, // Not valid in SSA form (see LLIL_STORE_SSA) + LLIL_PUSH, // Not valid in SSA form (expanded) + LLIL_POP, // Not valid in SSA form (expanded) + LLIL_REG, // Not valid in SSA form (see LLIL_REG_SSA) LLIL_CONST, - LLIL_FLAG, - LLIL_FLAG_BIT, + LLIL_FLAG, // Not valid in SSA form (see LLIL_FLAG_SSA) + LLIL_FLAG_BIT, // Not valid in SSA form (see LLIL_FLAG_BIT_SSA) LLIL_ADD, LLIL_ADC, LLIL_SUB, @@ -314,7 +320,7 @@ extern "C" LLIL_NORET, LLIL_IF, LLIL_GOTO, - LLIL_FLAG_COND, + LLIL_FLAG_COND, // Valid only in Lifted IL LLIL_CMP_E, LLIL_CMP_NE, LLIL_CMP_SLT, @@ -332,7 +338,28 @@ extern "C" LLIL_TRAP, LLIL_UNDEF, LLIL_UNIMPL, - LLIL_UNIMPL_MEM + LLIL_UNIMPL_MEM, + + // The following instructions are only used in SSA form + LLIL_SET_REG_SSA, + LLIL_SET_REG_SSA_PARTIAL, + LLIL_SET_REG_SPLIT_SSA, + LLIL_REG_SPLIT_DEST_SSA, // Only valid within an LLIL_SET_REG_SPLIT_SSA instruction + LLIL_REG_SSA, + LLIL_REG_SSA_PARTIAL, + LLIL_SET_FLAG_SSA, + LLIL_FLAG_SSA, + LLIL_FLAG_BIT_SSA, + LLIL_CALL_SSA, + LLIL_SYSCALL_SSA, + LLIL_CALL_PARAM_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions + LLIL_CALL_STACK_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions + LLIL_CALL_OUTPUT_SSA, // Only valid within the LLIL_CALL_SSA or LLIL_SYSCALL_SSA instructions + LLIL_LOAD_SSA, + LLIL_STORE_SSA, + LLIL_REG_PHI, + LLIL_FLAG_PHI, + LLIL_MEM_PHI }; enum BNLowLevelILFlagCondition @@ -370,7 +397,12 @@ extern "C" { NormalFunctionGraph = 0, LowLevelILFunctionGraph = 1, - LiftedILFunctionGraph = 2 + LiftedILFunctionGraph = 2, + LowLevelILSSAFormFunctionGraph = 3, + MediumLevelILFunctionGraph = 4, + MediumLevelILSSAFormFunctionGraph = 5, + MappedMediumLevelILFunctionGraph = 6, + MappedMediumLevelILSSAFormFunctionGraph = 7 }; enum BNDisassemblyOption @@ -383,8 +415,7 @@ extern "C" GroupLinearDisassemblyFunctions = 64, // Debugging options - ShowBasicBlockRegisterState = 128, - ShowFlagUsage = 129 + ShowFlagUsage = 128 }; enum BNTypeClass @@ -601,16 +632,18 @@ extern "C" enum BNRegisterValueType { + UndeterminedValue, EntryValue, - OffsetFromEntryValue, ConstantValue, StackFrameOffset, - UndeterminedValue, - OffsetFromUndeterminedValue, + ReturnAddressValue, + + // The following are only valid in BNPossibleValueSet SignedRangeValue, UnsignedRangeValue, LookupTableValue, - ComparisonResultValue + InSetOfValues, + NotInSetOfValues }; enum BNPluginOrigin @@ -644,10 +677,22 @@ extern "C" struct BNRegisterValue { BNRegisterValueType state; - uint32_t reg; // For EntryValue and OffsetFromEntryValue, the original input register - int64_t value; // Offset for OffsetFromEntryValue, StackFrameOffset or RangeValue, value of register for ConstantValue - uint64_t rangeStart, rangeEnd, rangeStep; // Range of register, inclusive - BNLookupTableEntry* table; // Number of entries in rangeEnd + int64_t value; + }; + + struct BNValueRange + { + uint64_t start, end, step; + }; + + struct BNPossibleValueSet + { + BNRegisterValueType state; + int64_t value; + BNValueRange* ranges; + int64_t* valueSet; + BNLookupTableEntry* table; + size_t count; }; struct BNRegisterOrConstant @@ -664,6 +709,129 @@ extern "C" bool autoDiscovered; }; + enum BNMediumLevelILOperation + { + MLIL_NOP, + MLIL_SET_VAR, // Not valid in SSA form (see MLIL_SET_VAR_SSA) + MLIL_SET_VAR_FIELD, // Not valid in SSA form (see MLIL_SET_VAR_FIELD) + MLIL_SET_VAR_SPLIT, // Not valid in SSA form (see MLIL_SET_VAR_SPLIT_SSA) + MLIL_LOAD, // Not valid in SSA form (see MLIL_LOAD_SSA) + MLIL_STORE, // Not valid in SSA form (see MLIL_STORE_SSA) + MLIL_VAR, // Not valid in SSA form (see MLIL_VAR_SSA) + MLIL_VAR_FIELD, // Not valid in SSA form (see MLIL_VAR_SSA_FIELD) + MLIL_ADDRESS_OF, + MLIL_ADDRESS_OF_FIELD, + MLIL_CONST, + MLIL_ADD, + MLIL_ADC, + MLIL_SUB, + MLIL_SBB, + MLIL_AND, + MLIL_OR, + MLIL_XOR, + MLIL_LSL, + MLIL_LSR, + MLIL_ASR, + MLIL_ROL, + MLIL_RLC, + MLIL_ROR, + MLIL_RRC, + MLIL_MUL, + MLIL_MULU_DP, + MLIL_MULS_DP, + MLIL_DIVU, + MLIL_DIVU_DP, + MLIL_DIVS, + MLIL_DIVS_DP, + MLIL_MODU, + MLIL_MODU_DP, + MLIL_MODS, + MLIL_MODS_DP, + MLIL_NEG, + MLIL_NOT, + MLIL_SX, + MLIL_ZX, + MLIL_JUMP, + MLIL_JUMP_TO, + MLIL_CALL, // Not valid in SSA form (see MLIL_CALL_SSA) + MLIL_CALL_UNTYPED, // Not valid in SSA form (see MLIL_CALL_UNTYPED_SSA) + MLIL_CALL_OUTPUT, // Only valid within MLIL_CALL or MLIL_SYSCALL family instructions + MLIL_CALL_PARAM, // Only valid within MLIL_CALL or MLIL_SYSCALL family instructions + MLIL_RET, // Not valid in SSA form (see MLIL_RET_SSA) + MLIL_NORET, + MLIL_IF, + MLIL_GOTO, + MLIL_CMP_E, + MLIL_CMP_NE, + MLIL_CMP_SLT, + MLIL_CMP_ULT, + MLIL_CMP_SLE, + MLIL_CMP_ULE, + MLIL_CMP_SGE, + MLIL_CMP_UGE, + MLIL_CMP_SGT, + MLIL_CMP_UGT, + MLIL_TEST_BIT, + MLIL_BOOL_TO_INT, + MLIL_SYSCALL, // Not valid in SSA form (see MLIL_SYSCALL_SSA) + MLIL_SYSCALL_UNTYPED, // Not valid in SSA form (see MLIL_SYSCALL_UNTYPED_SSA) + MLIL_BP, + MLIL_TRAP, + MLIL_UNDEF, + MLIL_UNIMPL, + MLIL_UNIMPL_MEM, + + // The following instructions are only used in SSA form + MLIL_SET_VAR_SSA, + MLIL_SET_VAR_SSA_FIELD, + MLIL_SET_VAR_SPLIT_SSA, + MLIL_SET_VAR_ALIASED, + MLIL_SET_VAR_ALIASED_FIELD, + MLIL_VAR_SSA, + MLIL_VAR_SSA_FIELD, + MLIL_VAR_ALIASED, + MLIL_VAR_ALIASED_FIELD, + MLIL_CALL_SSA, + MLIL_CALL_UNTYPED_SSA, + MLIL_SYSCALL_SSA, + MLIL_SYSCALL_UNTYPED_SSA, + MLIL_CALL_PARAM_SSA, // Only valid within the MLIL_CALL_SSA, MLIL_SYSCALL_SSA family instructions + MLIL_CALL_OUTPUT_SSA, // Only valid within the MLIL_CALL_SSA or MLIL_SYSCALL_SSA family instructions + MLIL_LOAD_SSA, + MLIL_STORE_SSA, + MLIL_VAR_PHI, + MLIL_MEM_PHI + }; + + struct BNMediumLevelILInstruction + { + BNMediumLevelILOperation operation; + size_t size; + uint64_t operands[5]; + uint64_t address; + }; + + struct BNMediumLevelILLabel + { + bool resolved; + size_t ref; + size_t operand; + }; + + enum BNVariableSourceType + { + StackVariableSourceType, + RegisterVariableSourceType, + FlagVariableSourceType + }; + + struct BNVariable + { + BNVariableSourceType type; + uint32_t index; + int64_t storage; + }; + // Callbacks struct BNLogListener { @@ -1013,11 +1181,11 @@ extern "C" uint32_t (*getFloatReturnValueRegister)(void* ctxt); }; - struct BNStackVariable + struct BNVariableNameAndType { + BNVariable var; BNType* type; char* name; - int64_t offset; bool autoDefined; }; @@ -1026,7 +1194,7 @@ extern "C" uint32_t sourceOperand; BNType* type; char* name; - int64_t startingOffset; + uint64_t varIdentifier; int64_t referencedOffset; }; @@ -1275,6 +1443,19 @@ extern "C" BNType* type; }; + enum BNILBranchDependence + { + NotBranchDependent, + TrueBranchDependent, + FalseBranchDependent + }; + + struct BNILBranchInstructionAndDependence + { + size_t branch; + BNILBranchDependence dependence; + }; + BINARYNINJACOREAPI char* BNAllocString(const char* contents); BINARYNINJACOREAPI void BNFreeString(char* str); BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count); @@ -1731,26 +1912,21 @@ extern "C" BINARYNINJACOREAPI size_t BNGetLowLevelILForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI size_t* BNGetLowLevelILExitsForInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); - BINARYNINJACOREAPI void BNFreeLowLevelILInstructionList(size_t* list); + BINARYNINJACOREAPI void BNFreeILInstructionList(size_t* list); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetFunctionMediumLevelIL(BNFunction* func); BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAtInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, uint32_t reg); BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, uint32_t reg); - BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAtLowLevelILInstruction(BNFunction* func, size_t i, uint32_t reg); - BINARYNINJACOREAPI BNRegisterValue BNGetRegisterValueAfterLowLevelILInstruction(BNFunction* func, size_t i, uint32_t reg); BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAtInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, int64_t offset, size_t size); BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAfterInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, int64_t offset, size_t size); - BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAtLowLevelILInstruction(BNFunction* func, size_t i, - int64_t offset, size_t size); - BINARYNINJACOREAPI BNRegisterValue BNGetStackContentsAfterLowLevelILInstruction(BNFunction* func, size_t i, - int64_t offset, size_t size); BINARYNINJACOREAPI BNRegisterValue BNGetParameterValueAtInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, BNType* functionType, size_t i); BINARYNINJACOREAPI BNRegisterValue BNGetParameterValueAtLowLevelILInstruction(BNFunction* func, size_t instr, BNType* functionType, size_t i); - BINARYNINJACOREAPI void BNFreeRegisterValue(BNRegisterValue* value); + BINARYNINJACOREAPI void BNFreePossibleValueSet(BNPossibleValueSet* value); BINARYNINJACOREAPI uint32_t* BNGetRegistersReadByInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, size_t* count); BINARYNINJACOREAPI uint32_t* BNGetRegistersWrittenByInstruction(BNFunction* func, BNArchitecture* arch, uint64_t addr, @@ -1811,14 +1987,27 @@ extern "C" uint64_t len, size_t* count); BINARYNINJACOREAPI void BNFreeStringReferenceList(BNStringReference* strings); - BINARYNINJACOREAPI BNStackVariable* BNGetStackLayout(BNFunction* func, size_t* count); - BINARYNINJACOREAPI void BNFreeStackLayout(BNStackVariable* vars, size_t count); + BINARYNINJACOREAPI BNVariableNameAndType* BNGetStackLayout(BNFunction* func, size_t* count); + BINARYNINJACOREAPI void BNFreeVariableList(BNVariableNameAndType* vars, size_t count); BINARYNINJACOREAPI void BNCreateAutoStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name); BINARYNINJACOREAPI void BNCreateUserStackVariable(BNFunction* func, int64_t offset, BNType* type, const char* name); BINARYNINJACOREAPI void BNDeleteAutoStackVariable(BNFunction* func, int64_t offset); BINARYNINJACOREAPI void BNDeleteUserStackVariable(BNFunction* func, int64_t offset); - BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(BNFunction* func, int64_t offset, BNStackVariable* var); - BINARYNINJACOREAPI void BNFreeStackVariable(BNStackVariable* var); + BINARYNINJACOREAPI bool BNGetStackVariableAtFrameOffset(BNFunction* func, BNArchitecture* arch, uint64_t addr, + int64_t offset, BNVariableNameAndType* var); + BINARYNINJACOREAPI void BNFreeVariableNameAndType(BNVariableNameAndType* var); + + BINARYNINJACOREAPI BNVariableNameAndType* BNGetFunctionVariables(BNFunction* func, size_t* count); + BINARYNINJACOREAPI void BNCreateAutoVariable(BNFunction* func, const BNVariable* var, BNType* type, + const char* name, bool ignoreDisjointUses); + BINARYNINJACOREAPI void BNCreateUserVariable(BNFunction* func, const BNVariable* var, BNType* type, + const char* name, bool ignoreDisjointUses); + BINARYNINJACOREAPI void BNDeleteAutoVariable(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI void BNDeleteUserVariable(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI BNType* BNGetVariableType(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI char* BNGetVariableName(BNFunction* func, const BNVariable* var); + BINARYNINJACOREAPI uint64_t BNToVariableIdentifier(const BNVariable* var); + BINARYNINJACOREAPI BNVariable BNFromVariableIdentifier(uint64_t id); BINARYNINJACOREAPI void BNSetAutoIndirectBranches(BNFunction* func, BNArchitecture* sourceArch, uint64_t source, BNArchitectureAndAddress* branches, size_t count); @@ -2010,7 +2199,10 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILFunction* BNNewLowLevelILFunctionReference(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNFreeLowLevelILFunction(BNLowLevelILFunction* func); BINARYNINJACOREAPI uint64_t BNLowLevelILGetCurrentAddress(BNLowLevelILFunction* func); - BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func, uint64_t addr); + BINARYNINJACOREAPI void BNLowLevelILSetCurrentAddress(BNLowLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI size_t BNLowLevelILGetInstructionStart(BNLowLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI void BNLowLevelILClearIndirectBranches(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNLowLevelILSetIndirectBranches(BNLowLevelILFunction* func, BNArchitectureAndAddress* branches, size_t count); @@ -2033,6 +2225,7 @@ extern "C" BINARYNINJACOREAPI BNLowLevelILInstruction BNGetLowLevelILByIndex(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILIndexForInstruction(BNLowLevelILFunction* func, size_t i); BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionCount(BNLowLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetLowLevelILExprCount(BNLowLevelILFunction* func); BINARYNINJACOREAPI void BNAddLowLevelILLabelForAddress(BNLowLevelILFunction* func, BNArchitecture* arch, uint64_t addr); BINARYNINJACOREAPI BNLowLevelILLabel* BNGetLowLevelILLabelForAddress(BNLowLevelILFunction* func, @@ -2048,6 +2241,168 @@ extern "C" BINARYNINJACOREAPI BNBasicBlock** BNGetLowLevelILBasicBlockList(BNLowLevelILFunction* func, size_t* count); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILSSAForm(BNLowLevelILFunction* func); + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILNonSSAForm(BNLowLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAInstructionIndex(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetLowLevelILNonSSAInstructionIndex(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAExprIndex(BNLowLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNGetLowLevelILNonSSAExprIndex(BNLowLevelILFunction* func, size_t expr); + + BINARYNINJACOREAPI size_t BNGetLowLevelILSSARegisterDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAFlagDefinition(BNLowLevelILFunction* func, uint32_t reg, size_t idx); + BINARYNINJACOREAPI size_t BNGetLowLevelILSSAMemoryDefinition(BNLowLevelILFunction* func, size_t idx); + BINARYNINJACOREAPI size_t* BNGetLowLevelILSSARegisterUses(BNLowLevelILFunction* func, uint32_t reg, size_t idx, + size_t* count); + BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAFlagUses(BNLowLevelILFunction* func, uint32_t reg, size_t idx, + size_t* count); + BINARYNINJACOREAPI size_t* BNGetLowLevelILSSAMemoryUses(BNLowLevelILFunction* func, size_t idx, size_t* count); + + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSARegisterValue(BNLowLevelILFunction* func, + uint32_t reg, size_t idx); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILSSAFlagValue(BNLowLevelILFunction* func, + uint32_t flag, size_t idx); + + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILExprValue(BNLowLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleExprValues(BNLowLevelILFunction* func, size_t expr); + + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILRegisterValueAtInstruction(BNLowLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILRegisterValueAfterInstruction(BNLowLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleRegisterValuesAtInstruction(BNLowLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleRegisterValuesAfterInstruction(BNLowLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILFlagValueAtInstruction(BNLowLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILFlagValueAfterInstruction(BNLowLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleFlagValuesAtInstruction(BNLowLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleFlagValuesAfterInstruction(BNLowLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILStackContentsAtInstruction(BNLowLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetLowLevelILStackContentsAfterInstruction(BNLowLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleStackContentsAtInstruction(BNLowLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetLowLevelILPossibleStackContentsAfterInstruction(BNLowLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILForLowLevelIL(BNLowLevelILFunction* func); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMappedMediumLevelIL(BNLowLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetMappedMediumLevelILInstructionIndex(BNLowLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetMappedMediumLevelILExprIndex(BNLowLevelILFunction* func, size_t expr); + + // Medium-level IL + BINARYNINJACOREAPI BNMediumLevelILFunction* BNCreateMediumLevelILFunction(BNArchitecture* arch, BNFunction* func); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNNewMediumLevelILFunctionReference(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNFreeMediumLevelILFunction(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI uint64_t BNMediumLevelILGetCurrentAddress(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI void BNMediumLevelILSetCurrentAddress(BNMediumLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI size_t BNMediumLevelILGetInstructionStart(BNMediumLevelILFunction* func, + BNArchitecture* arch, uint64_t addr); + BINARYNINJACOREAPI size_t BNMediumLevelILAddExpr(BNMediumLevelILFunction* func, BNMediumLevelILOperation operation, + size_t size, uint64_t a, uint64_t b, uint64_t c, uint64_t d, uint64_t e); + BINARYNINJACOREAPI size_t BNMediumLevelILAddInstruction(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNMediumLevelILGoto(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); + BINARYNINJACOREAPI size_t BNMediumLevelILIf(BNMediumLevelILFunction* func, uint64_t op, + BNMediumLevelILLabel* t, BNMediumLevelILLabel* f); + BINARYNINJACOREAPI void BNMediumLevelILInitLabel(BNMediumLevelILLabel* label); + BINARYNINJACOREAPI void BNMediumLevelILMarkLabel(BNMediumLevelILFunction* func, BNMediumLevelILLabel* label); + BINARYNINJACOREAPI void BNFinalizeMediumLevelILFunction(BNMediumLevelILFunction* func); + + BINARYNINJACOREAPI size_t BNMediumLevelILAddLabelList(BNMediumLevelILFunction* func, + BNMediumLevelILLabel** labels, size_t count); + BINARYNINJACOREAPI size_t BNMediumLevelILAddOperandList(BNMediumLevelILFunction* func, + uint64_t* operands, size_t count); + BINARYNINJACOREAPI uint64_t* BNMediumLevelILGetOperandList(BNMediumLevelILFunction* func, size_t expr, + size_t operand, size_t* count); + BINARYNINJACOREAPI void BNMediumLevelILFreeOperandList(uint64_t* operands); + + BINARYNINJACOREAPI BNMediumLevelILInstruction BNGetMediumLevelILByIndex(BNMediumLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetMediumLevelILIndexForInstruction(BNMediumLevelILFunction* func, size_t i); + BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionForExpr(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILInstructionCount(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetMediumLevelILExprCount(BNMediumLevelILFunction* func); + + BINARYNINJACOREAPI bool BNGetMediumLevelILExprText(BNMediumLevelILFunction* func, BNArchitecture* arch, size_t i, + BNInstructionTextToken** tokens, size_t* count); + BINARYNINJACOREAPI bool BNGetMediumLevelILInstructionText(BNMediumLevelILFunction* il, BNFunction* func, + BNArchitecture* arch, size_t i, BNInstructionTextToken** tokens, size_t* count); + + BINARYNINJACOREAPI BNBasicBlock** BNGetMediumLevelILBasicBlockList(BNMediumLevelILFunction* func, size_t* count); + + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILSSAForm(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI BNMediumLevelILFunction* BNGetMediumLevelILNonSSAForm(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAInstructionIndex(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAInstructionIndex(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAExprIndex(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILNonSSAExprIndex(BNMediumLevelILFunction* func, size_t expr); + + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarDefinition(BNMediumLevelILFunction* func, + const BNVariable* var, size_t idx); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryDefinition(BNMediumLevelILFunction* func, size_t idx); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAVarUses(BNMediumLevelILFunction* func, const BNVariable* var, + size_t idx, size_t* count); + BINARYNINJACOREAPI size_t* BNGetMediumLevelILSSAMemoryUses(BNMediumLevelILFunction* func, + size_t idx, size_t* count); + + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILSSAVarValue(BNMediumLevelILFunction* func, + const BNVariable* var, size_t idx); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILExprValue(BNMediumLevelILFunction* func, size_t expr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleSSAVarValues(BNMediumLevelILFunction* func, + const BNVariable* var, size_t idx, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleExprValues(BNMediumLevelILFunction* func, size_t expr); + + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAVarIndexAtILInstruction(BNMediumLevelILFunction* func, + const BNVariable* var, size_t instr); + BINARYNINJACOREAPI size_t BNGetMediumLevelILSSAMemoryIndexAtILInstruction(BNMediumLevelILFunction* func, + size_t instr); + BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForRegisterAtInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForFlagAtInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNVariable BNGetMediumLevelILVariableForStackLocationAtInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t instr); + + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILRegisterValueAtInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILRegisterValueAfterInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleRegisterValuesAtInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(BNMediumLevelILFunction* func, + uint32_t reg, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILFlagValueAtInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILFlagValueAfterInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleFlagValuesAtInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleFlagValuesAfterInstruction(BNMediumLevelILFunction* func, + uint32_t flag, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILStackContentsAtInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNRegisterValue BNGetMediumLevelILStackContentsAfterInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleStackContentsAtInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + BINARYNINJACOREAPI BNPossibleValueSet BNGetMediumLevelILPossibleStackContentsAfterInstruction(BNMediumLevelILFunction* func, + int64_t offset, size_t len, size_t instr); + + BINARYNINJACOREAPI BNILBranchDependence BNGetMediumLevelILBranchDependence(BNMediumLevelILFunction* func, + size_t curInstr, size_t branchInstr); + BINARYNINJACOREAPI BNILBranchInstructionAndDependence* BNGetAllMediumLevelILBranchDependence( + BNMediumLevelILFunction* func, size_t instr, size_t* count); + BINARYNINJACOREAPI void BNFreeILBranchDependenceList(BNILBranchInstructionAndDependence* branches); + + BINARYNINJACOREAPI BNLowLevelILFunction* BNGetLowLevelILForMediumLevelIL(BNMediumLevelILFunction* func); + BINARYNINJACOREAPI size_t BNGetLowLevelILInstructionIndex(BNMediumLevelILFunction* func, size_t instr); + BINARYNINJACOREAPI size_t BNGetLowLevelILExprIndex(BNMediumLevelILFunction* func, size_t expr); + // Types BINARYNINJACOREAPI BNType* BNCreateVoidType(void); BINARYNINJACOREAPI BNType* BNCreateBoolType(void); diff --git a/function.cpp b/function.cpp index b1d008ee..d4f91db1 100644 --- a/function.cpp +++ b/function.cpp @@ -24,6 +24,73 @@ using namespace BinaryNinja; using namespace std; +Variable::Variable() +{ + type = RegisterVariableSourceType; + index = 0; + storage = 0; +} + + +Variable::Variable(BNVariableSourceType t, uint32_t i, uint64_t s) +{ + type = t; + index = i; + storage = s; +} + + +Variable::Variable(const BNVariable& var) +{ + type = var.type; + index = var.index; + storage = var.storage; +} + + +Variable& Variable::operator=(const Variable& var) +{ + type = var.type; + index = var.index; + storage = var.storage; + return *this; +} + + +bool Variable::operator==(const Variable& var) const +{ + if (type != var.type) + return false; + if (index != var.index) + return false; + return storage == var.storage; +} + + +bool Variable::operator!=(const Variable& var) const +{ + return !((*this) == var); +} + + +bool Variable::operator<(const Variable& var) const +{ + return ToIdentifier() < var.ToIdentifier(); +} + + +uint64_t Variable::ToIdentifier() const +{ + return BNToVariableIdentifier(this); +} + + +Variable Variable::FromIdentifier(uint64_t id) +{ + return BNFromVariableIdentifier(id); +} + + Function::Function(BNFunction* func) { m_object = func; @@ -161,23 +228,28 @@ vector<size_t> Function::GetLowLevelILExitsForInstruction(Architecture* arch, ui vector<size_t> result; result.insert(result.end(), exits, &exits[count]); - BNFreeLowLevelILInstructionList(exits); + BNFreeILInstructionList(exits); return result; } -static RegisterValue GetRegisterValueFromAPIObject(BNRegisterValue& value) +RegisterValue RegisterValue::FromAPIObject(BNRegisterValue& value) { RegisterValue result; result.state = value.state; - result.reg = value.reg; result.value = value.value; - result.rangeStart = value.rangeStart; - result.rangeEnd = value.rangeEnd; - result.rangeStep = value.rangeStep; + return result; +} + + +PossibleValueSet PossibleValueSet::FromAPIObject(BNPossibleValueSet& value) +{ + PossibleValueSet result; + result.state = value.state; + result.value = value.value; if (value.state == LookupTableValue) { - for (size_t i = 0; i < (size_t)value.rangeEnd; i++) + for (size_t i = 0; i < value.count; i++) { LookupTableEntry entry; entry.fromValues.insert(entry.fromValues.end(), &value.table[i].fromValues[0], @@ -186,7 +258,17 @@ static RegisterValue GetRegisterValueFromAPIObject(BNRegisterValue& value) result.table.push_back(entry); } } - BNFreeRegisterValue(&value); + else if ((value.state == SignedRangeValue) || (value.state == UnsignedRangeValue)) + { + for (size_t i = 0; i < value.count; i++) + result.ranges.push_back(value.ranges[i]); + } + else if ((value.state == InSetOfValues) || (value.state == NotInSetOfValues)) + { + for (size_t i = 0; i < value.count; i++) + result.valueSet.insert(value.valueSet[i]); + } + BNFreePossibleValueSet(&value); return result; } @@ -194,56 +276,28 @@ static RegisterValue GetRegisterValueFromAPIObject(BNRegisterValue& value) RegisterValue Function::GetRegisterValueAtInstruction(Architecture* arch, uint64_t addr, uint32_t reg) { BNRegisterValue value = BNGetRegisterValueAtInstruction(m_object, arch->GetObject(), addr, reg); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetRegisterValueAfterInstruction(Architecture* arch, uint64_t addr, uint32_t reg) { BNRegisterValue value = BNGetRegisterValueAfterInstruction(m_object, arch->GetObject(), addr, reg); - return GetRegisterValueFromAPIObject(value); -} - - -RegisterValue Function::GetRegisterValueAtLowLevelILInstruction(size_t i, uint32_t reg) -{ - BNRegisterValue value = BNGetRegisterValueAtLowLevelILInstruction(m_object, i, reg); - return GetRegisterValueFromAPIObject(value); -} - - -RegisterValue Function::GetRegisterValueAfterLowLevelILInstruction(size_t i, uint32_t reg) -{ - BNRegisterValue value = BNGetRegisterValueAfterLowLevelILInstruction(m_object, i, reg); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetStackContentsAtInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size) { BNRegisterValue value = BNGetStackContentsAtInstruction(m_object, arch->GetObject(), addr, offset, size); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } RegisterValue Function::GetStackContentsAfterInstruction(Architecture* arch, uint64_t addr, int64_t offset, size_t size) { BNRegisterValue value = BNGetStackContentsAfterInstruction(m_object, arch->GetObject(), addr, offset, size); - return GetRegisterValueFromAPIObject(value); -} - - -RegisterValue Function::GetStackContentsAtLowLevelILInstruction(size_t i, int64_t offset, size_t size) -{ - BNRegisterValue value = BNGetStackContentsAtLowLevelILInstruction(m_object, i, offset, size); - return GetRegisterValueFromAPIObject(value); -} - - -RegisterValue Function::GetStackContentsAfterLowLevelILInstruction(size_t i, int64_t offset, size_t size) -{ - BNRegisterValue value = BNGetStackContentsAfterLowLevelILInstruction(m_object, i, offset, size); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } @@ -251,7 +305,7 @@ RegisterValue Function::GetParameterValueAtInstruction(Architecture* arch, uint6 { BNRegisterValue value = BNGetParameterValueAtInstruction(m_object, arch->GetObject(), addr, functionType ? functionType->GetObject() : nullptr, i); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } @@ -259,7 +313,7 @@ RegisterValue Function::GetParameterValueAtLowLevelILInstruction(size_t instr, T { BNRegisterValue value = BNGetParameterValueAtLowLevelILInstruction(m_object, instr, functionType ? functionType->GetObject() : nullptr, i); - return GetRegisterValueFromAPIObject(value); + return RegisterValue::FromAPIObject(value); } @@ -301,7 +355,7 @@ vector<StackVariableReference> Function::GetStackVariablesReferencedByInstructio ref.sourceOperand = refs[i].sourceOperand; ref.type = refs[i].type ? new Type(BNNewTypeReference(refs[i].type)) : nullptr; ref.name = refs[i].name; - ref.startingOffset = refs[i].startingOffset; + ref.var = Variable::FromIdentifier(refs[i].varIdentifier); ref.referencedOffset = refs[i].referencedOffset; result.push_back(ref); } @@ -343,7 +397,7 @@ set<size_t> Function::GetLiftedILFlagUsesForDefinition(size_t i, uint32_t flag) set<size_t> result; result.insert(&instrs[0], &instrs[count]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -355,7 +409,7 @@ set<size_t> Function::GetLiftedILFlagDefinitionsForUse(size_t i, uint32_t flag) set<size_t> result; result.insert(&instrs[0], &instrs[count]); - BNFreeLowLevelILInstructionList(instrs); + BNFreeILInstructionList(instrs); return result; } @@ -384,6 +438,12 @@ set<uint32_t> Function::GetFlagsWrittenByLiftedILInstruction(size_t i) } +Ref<MediumLevelILFunction> Function::GetMediumLevelIL() const +{ + return new MediumLevelILFunction(BNGetFunctionMediumLevelIL(m_object)); +} + + Ref<Type> Function::GetType() const { return new Type(BNGetFunctionType(m_object)); @@ -421,23 +481,23 @@ Ref<FunctionGraph> Function::CreateFunctionGraph() } -map<int64_t, StackVariable> Function::GetStackLayout() +map<int64_t, vector<VariableNameAndType>> Function::GetStackLayout() { size_t count; - BNStackVariable* vars = BNGetStackLayout(m_object, &count); + BNVariableNameAndType* vars = BNGetStackLayout(m_object, &count); - map<int64_t, StackVariable> result; + map<int64_t, vector<VariableNameAndType>> result; for (size_t i = 0; i < count; i++) { - StackVariable var; + VariableNameAndType var; var.name = vars[i].name; var.type = new Type(BNNewTypeReference(vars[i].type)); - var.offset = vars[i].offset; + var.var = vars[i].var; var.autoDefined = vars[i].autoDefined; - result[vars[i].offset] = var; + result[vars[i].var.storage].push_back(var); } - BNFreeStackLayout(vars, count); + BNFreeVariableList(vars, count); return result; } @@ -466,22 +526,86 @@ void Function::DeleteUserStackVariable(int64_t offset) } -bool Function::GetStackVariableAtFrameOffset(int64_t offset, StackVariable& result) +bool Function::GetStackVariableAtFrameOffset(Architecture* arch, uint64_t addr, + int64_t offset, VariableNameAndType& result) { - BNStackVariable var; - if (!BNGetStackVariableAtFrameOffset(m_object, offset, &var)) + BNVariableNameAndType var; + if (!BNGetStackVariableAtFrameOffset(m_object, arch->GetObject(), addr, offset, &var)) return false; result.type = new Type(BNNewTypeReference(var.type)); result.name = var.name; - result.offset = var.offset; + result.var = var.var; result.autoDefined = var.autoDefined; - BNFreeStackVariable(&var); + BNFreeVariableNameAndType(&var); return true; } +map<Variable, VariableNameAndType> Function::GetVariables() +{ + size_t count; + BNVariableNameAndType* vars = BNGetFunctionVariables(m_object, &count); + + map<Variable, VariableNameAndType> result; + for (size_t i = 0; i < count; i++) + { + VariableNameAndType var; + var.name = vars[i].name; + var.type = new Type(BNNewTypeReference(vars[i].type)); + var.var = vars[i].var; + var.autoDefined = vars[i].autoDefined; + result[vars[i].var] = var; + } + + BNFreeVariableList(vars, count); + return result; +} + + +void Function::CreateAutoVariable(const Variable& var, Ref<Type> type, const string& name, bool ignoreDisjointUses) +{ + BNCreateAutoVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses); +} + + +void Function::CreateUserVariable(const Variable& var, Ref<Type> type, const string& name, bool ignoreDisjointUses) +{ + BNCreateUserVariable(m_object, &var, type->GetObject(), name.c_str(), ignoreDisjointUses); +} + + +void Function::DeleteAutoVariable(const Variable& var) +{ + BNDeleteAutoVariable(m_object, &var); +} + + +void Function::DeleteUserVariable(const Variable& var) +{ + BNDeleteUserVariable(m_object, &var); +} + + +Ref<Type> Function::GetVariableType(const Variable& var) +{ + BNType* type = BNGetVariableType(m_object, &var); + if (!type) + return nullptr; + return new Type(type); +} + + +string Function::GetVariableName(const Variable& var) +{ + char* name = BNGetVariableName(m_object, &var); + string result = name; + BNFreeString(name); + return result; +} + + void Function::SetAutoIndirectBranches(Architecture* sourceArch, uint64_t source, const std::vector<ArchAndAddr>& branches) { BNArchitectureAndAddress* branchList = new BNArchitectureAndAddress[branches.size()]; diff --git a/lowlevelil.cpp b/lowlevelil.cpp index bf3b980e..9764445e 100644 --- a/lowlevelil.cpp +++ b/lowlevelil.cpp @@ -48,9 +48,15 @@ uint64_t LowLevelILFunction::GetCurrentAddress() const } -void LowLevelILFunction::SetCurrentAddress(uint64_t addr) +void LowLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) { - BNLowLevelILSetCurrentAddress(m_object, addr); + BNLowLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); +} + + +size_t LowLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) +{ + return BNLowLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); } @@ -547,6 +553,12 @@ size_t LowLevelILFunction::GetInstructionCount() const } +size_t LowLevelILFunction::GetExprCount() const +{ + return BNGetLowLevelILExprCount(m_object); +} + + void LowLevelILFunction::AddLabelForAddress(Architecture* arch, ExprId addr) { BNAddLowLevelILLabelForAddress(m_object, arch->GetObject(), addr); @@ -643,3 +655,247 @@ vector<Ref<BasicBlock>> LowLevelILFunction::GetBasicBlocks() const BNFreeBasicBlockList(blocks, count); return result; } + + +Ref<LowLevelILFunction> LowLevelILFunction::GetSSAForm() const +{ + BNLowLevelILFunction* func = BNGetLowLevelILSSAForm(m_object); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} + + +Ref<LowLevelILFunction> LowLevelILFunction::GetNonSSAForm() const +{ + BNLowLevelILFunction* func = BNGetLowLevelILNonSSAForm(m_object); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} + + +size_t LowLevelILFunction::GetSSAInstructionIndex(size_t instr) const +{ + return BNGetLowLevelILSSAInstructionIndex(m_object, instr); +} + + +size_t LowLevelILFunction::GetNonSSAInstructionIndex(size_t instr) const +{ + return BNGetLowLevelILNonSSAInstructionIndex(m_object, instr); +} + + +size_t LowLevelILFunction::GetSSAExprIndex(size_t expr) const +{ + return BNGetLowLevelILSSAExprIndex(m_object, expr); +} + + +size_t LowLevelILFunction::GetNonSSAExprIndex(size_t expr) const +{ + return BNGetLowLevelILNonSSAExprIndex(m_object, expr); +} + + +size_t LowLevelILFunction::GetSSARegisterDefinition(uint32_t reg, size_t idx) const +{ + return BNGetLowLevelILSSARegisterDefinition(m_object, reg, idx); +} + + +size_t LowLevelILFunction::GetSSAFlagDefinition(uint32_t flag, size_t idx) const +{ + return BNGetLowLevelILSSAFlagDefinition(m_object, flag, idx); +} + + +size_t LowLevelILFunction::GetSSAMemoryDefinition(size_t idx) const +{ + return BNGetLowLevelILSSAMemoryDefinition(m_object, idx); +} + + +set<size_t> LowLevelILFunction::GetSSARegisterUses(uint32_t reg, size_t idx) const +{ + size_t count; + size_t* instrs = BNGetLowLevelILSSARegisterUses(m_object, reg, idx, &count); + + set<size_t> result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +set<size_t> LowLevelILFunction::GetSSAFlagUses(uint32_t flag, size_t idx) const +{ + size_t count; + size_t* instrs = BNGetLowLevelILSSAFlagUses(m_object, flag, idx, &count); + + set<size_t> result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +set<size_t> LowLevelILFunction::GetSSAMemoryUses(size_t idx) const +{ + size_t count; + size_t* instrs = BNGetLowLevelILSSAMemoryUses(m_object, idx, &count); + + set<size_t> result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +RegisterValue LowLevelILFunction::GetSSARegisterValue(uint32_t reg, size_t idx) +{ + BNRegisterValue value = BNGetLowLevelILSSARegisterValue(m_object, reg, idx); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetSSAFlagValue(uint32_t flag, size_t idx) +{ + BNRegisterValue value = BNGetLowLevelILSSAFlagValue(m_object, flag, idx); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetExprValue(size_t expr) +{ + BNRegisterValue value = BNGetLowLevelILExprValue(m_object, expr); + return RegisterValue::FromAPIObject(value); +} + + +PossibleValueSet LowLevelILFunction::GetPossibleExprValues(size_t expr) +{ + BNPossibleValueSet value = BNGetLowLevelILPossibleExprValues(m_object, expr); + return PossibleValueSet::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILRegisterValueAtInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetRegisterValueAfterInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILRegisterValueAfterInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +PossibleValueSet LowLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr) +{ + BNPossibleValueSet value = BNGetLowLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +PossibleValueSet LowLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr) +{ + BNPossibleValueSet value = BNGetLowLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetFlagValueAtInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILFlagValueAtInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetFlagValueAfterInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILFlagValueAfterInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +PossibleValueSet LowLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr) +{ + BNPossibleValueSet value = BNGetLowLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +PossibleValueSet LowLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr) +{ + BNPossibleValueSet value = BNGetLowLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILStackContentsAtInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue LowLevelILFunction::GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetLowLevelILStackContentsAfterInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +PossibleValueSet LowLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +{ + BNPossibleValueSet value = BNGetLowLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +PossibleValueSet LowLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +{ + BNPossibleValueSet value = BNGetLowLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +Ref<MediumLevelILFunction> LowLevelILFunction::GetMediumLevelIL() const +{ + BNMediumLevelILFunction* func = BNGetMediumLevelILForLowLevelIL(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +Ref<MediumLevelILFunction> LowLevelILFunction::GetMappedMediumLevelIL() const +{ + BNMediumLevelILFunction* func = BNGetMappedMediumLevelIL(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +size_t LowLevelILFunction::GetMappedMediumLevelILInstructionIndex(size_t instr) const +{ + return BNGetMappedMediumLevelILInstructionIndex(m_object, instr); +} + + +size_t LowLevelILFunction::GetMappedMediumLevelILExprIndex(size_t expr) const +{ + return BNGetMappedMediumLevelILExprIndex(m_object, expr); +} diff --git a/mediumlevelil.cpp b/mediumlevelil.cpp new file mode 100644 index 00000000..868f3f75 --- /dev/null +++ b/mediumlevelil.cpp @@ -0,0 +1,494 @@ +// Copyright (c) 2017 Vector 35 LLC +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +#include "binaryninjaapi.h" + +using namespace BinaryNinja; +using namespace std; + + +MediumLevelILLabel::MediumLevelILLabel() +{ + BNMediumLevelILInitLabel(this); +} + + +MediumLevelILFunction::MediumLevelILFunction(Architecture* arch, Function* func) +{ + m_object = BNCreateMediumLevelILFunction(arch->GetObject(), func ? func->GetObject() : nullptr); +} + + +MediumLevelILFunction::MediumLevelILFunction(BNMediumLevelILFunction* func) +{ + m_object = func; +} + + +uint64_t MediumLevelILFunction::GetCurrentAddress() const +{ + return BNMediumLevelILGetCurrentAddress(m_object); +} + + +void MediumLevelILFunction::SetCurrentAddress(Architecture* arch, uint64_t addr) +{ + BNMediumLevelILSetCurrentAddress(m_object, arch ? arch->GetObject() : nullptr, addr); +} + + +size_t MediumLevelILFunction::GetInstructionStart(Architecture* arch, uint64_t addr) +{ + return BNMediumLevelILGetInstructionStart(m_object, arch ? arch->GetObject() : nullptr, addr); +} + + +ExprId MediumLevelILFunction::AddExpr(BNMediumLevelILOperation operation, size_t size, + ExprId a, ExprId b, ExprId c, ExprId d, ExprId e) +{ + return BNMediumLevelILAddExpr(m_object, operation, size, a, b, c, d, e); +} + + +ExprId MediumLevelILFunction::AddInstruction(size_t expr) +{ + return BNMediumLevelILAddInstruction(m_object, expr); +} + + +ExprId MediumLevelILFunction::Goto(BNMediumLevelILLabel& label) +{ + return BNMediumLevelILGoto(m_object, &label); +} + + +ExprId MediumLevelILFunction::If(ExprId operand, BNMediumLevelILLabel& t, BNMediumLevelILLabel& f) +{ + return BNMediumLevelILIf(m_object, operand, &t, &f); +} + + +void MediumLevelILFunction::MarkLabel(BNMediumLevelILLabel& label) +{ + BNMediumLevelILMarkLabel(m_object, &label); +} + + +vector<uint64_t> MediumLevelILFunction::GetOperandList(ExprId expr, size_t listOperand) +{ + size_t count; + uint64_t* operands = BNMediumLevelILGetOperandList(m_object, expr, listOperand, &count); + vector<uint64_t> result; + for (size_t i = 0; i < count; i++) + result.push_back(operands[i]); + BNMediumLevelILFreeOperandList(operands); + return result; +} + + +ExprId MediumLevelILFunction::AddLabelList(const vector<BNMediumLevelILLabel*>& labels) +{ + BNMediumLevelILLabel** labelList = new BNMediumLevelILLabel*[labels.size()]; + for (size_t i = 0; i < labels.size(); i++) + labelList[i] = labels[i]; + ExprId result = (ExprId)BNMediumLevelILAddLabelList(m_object, labelList, labels.size()); + delete[] labelList; + return result; +} + + +ExprId MediumLevelILFunction::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)BNMediumLevelILAddOperandList(m_object, operandList, operands.size()); + delete[] operandList; + return result; +} + + +BNMediumLevelILInstruction MediumLevelILFunction::operator[](size_t i) const +{ + return BNGetMediumLevelILByIndex(m_object, i); +} + + +size_t MediumLevelILFunction::GetIndexForInstruction(size_t i) const +{ + return BNGetMediumLevelILIndexForInstruction(m_object, i); +} + + +size_t MediumLevelILFunction::GetInstructionForExpr(size_t expr) const +{ + return BNGetMediumLevelILInstructionForExpr(m_object, expr); +} + + +size_t MediumLevelILFunction::GetInstructionCount() const +{ + return BNGetMediumLevelILInstructionCount(m_object); +} + + +size_t MediumLevelILFunction::GetExprCount() const +{ + return BNGetMediumLevelILExprCount(m_object); +} + + +void MediumLevelILFunction::Finalize() +{ + BNFinalizeMediumLevelILFunction(m_object); +} + + +bool MediumLevelILFunction::GetExprText(Architecture* arch, ExprId expr, vector<InstructionTextToken>& tokens) +{ + size_t count; + BNInstructionTextToken* list; + if (!BNGetMediumLevelILExprText(m_object, arch->GetObject(), expr, &list, &count)) + return false; + + tokens.clear(); + for (size_t i = 0; i < count; i++) + { + InstructionTextToken token; + token.type = list[i].type; + token.text = list[i].text; + token.value = list[i].value; + token.size = list[i].size; + token.operand = list[i].operand; + token.context = list[i].context; + token.address = list[i].address; + tokens.push_back(token); + } + + BNFreeInstructionText(list, count); + return true; +} + + +bool MediumLevelILFunction::GetInstructionText(Function* func, Architecture* arch, size_t instr, + vector<InstructionTextToken>& tokens) +{ + size_t count; + BNInstructionTextToken* list; + if (!BNGetMediumLevelILInstructionText(m_object, func ? func->GetObject() : nullptr, arch->GetObject(), + instr, &list, &count)) + return false; + + tokens.clear(); + for (size_t i = 0; i < count; i++) + { + InstructionTextToken token; + token.type = list[i].type; + token.text = list[i].text; + token.value = list[i].value; + token.size = list[i].size; + token.operand = list[i].operand; + token.context = list[i].context; + token.address = list[i].address; + tokens.push_back(token); + } + + BNFreeInstructionText(list, count); + return true; +} + + +vector<Ref<BasicBlock>> MediumLevelILFunction::GetBasicBlocks() const +{ + size_t count; + BNBasicBlock** blocks = BNGetMediumLevelILBasicBlockList(m_object, &count); + + vector<Ref<BasicBlock>> result; + for (size_t i = 0; i < count; i++) + result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); + + BNFreeBasicBlockList(blocks, count); + return result; +} + + +Ref<MediumLevelILFunction> MediumLevelILFunction::GetSSAForm() const +{ + BNMediumLevelILFunction* func = BNGetMediumLevelILSSAForm(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +Ref<MediumLevelILFunction> MediumLevelILFunction::GetNonSSAForm() const +{ + BNMediumLevelILFunction* func = BNGetMediumLevelILNonSSAForm(m_object); + if (!func) + return nullptr; + return new MediumLevelILFunction(func); +} + + +size_t MediumLevelILFunction::GetSSAInstructionIndex(size_t instr) const +{ + return BNGetMediumLevelILSSAInstructionIndex(m_object, instr); +} + + +size_t MediumLevelILFunction::GetNonSSAInstructionIndex(size_t instr) const +{ + return BNGetMediumLevelILNonSSAInstructionIndex(m_object, instr); +} + + +size_t MediumLevelILFunction::GetSSAExprIndex(size_t expr) const +{ + return BNGetMediumLevelILSSAExprIndex(m_object, expr); +} + + +size_t MediumLevelILFunction::GetNonSSAExprIndex(size_t expr) const +{ + return BNGetMediumLevelILNonSSAExprIndex(m_object, expr); +} + + +size_t MediumLevelILFunction::GetSSAVarDefinition(const Variable& var, size_t idx) const +{ + return BNGetMediumLevelILSSAVarDefinition(m_object, &var, idx); +} + + +size_t MediumLevelILFunction::GetSSAMemoryDefinition(size_t idx) const +{ + return BNGetMediumLevelILSSAMemoryDefinition(m_object, idx); +} + + +set<size_t> MediumLevelILFunction::GetSSAVarUses(const Variable& var, size_t idx) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILSSAVarUses(m_object, &var, idx, &count); + + set<size_t> result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +set<size_t> MediumLevelILFunction::GetSSAMemoryUses(size_t idx) const +{ + size_t count; + size_t* instrs = BNGetMediumLevelILSSAMemoryUses(m_object, idx, &count); + + set<size_t> result; + for (size_t i = 0; i < count; i++) + result.insert(instrs[i]); + + BNFreeILInstructionList(instrs); + return result; +} + + +RegisterValue MediumLevelILFunction::GetSSAVarValue(const Variable& var, size_t idx) +{ + BNRegisterValue value = BNGetMediumLevelILSSAVarValue(m_object, &var, idx); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetExprValue(size_t expr) +{ + BNRegisterValue value = BNGetMediumLevelILExprValue(m_object, expr); + return RegisterValue::FromAPIObject(value); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleSSAVarValues(const Variable& var, size_t idx, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleSSAVarValues(m_object, &var, idx, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleExprValues(size_t expr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleExprValues(m_object, expr); + return PossibleValueSet::FromAPIObject(value); +} + + +size_t MediumLevelILFunction::GetSSAVarIndexAtInstruction(const Variable& var, size_t instr) const +{ + return BNGetMediumLevelILSSAVarIndexAtILInstruction(m_object, &var, instr); +} + + +size_t MediumLevelILFunction::GetSSAMemoryIndexAtInstruction(size_t instr) const +{ + return BNGetMediumLevelILSSAMemoryIndexAtILInstruction(m_object, instr); +} + + +Variable MediumLevelILFunction::GetVariableForRegisterAtInstruction(uint32_t reg, size_t instr) const +{ + return BNGetMediumLevelILVariableForRegisterAtInstruction(m_object, reg, instr); +} + + +Variable MediumLevelILFunction::GetVariableForFlagAtInstruction(uint32_t flag, size_t instr) const +{ + return BNGetMediumLevelILVariableForFlagAtInstruction(m_object, flag, instr); +} + + +Variable MediumLevelILFunction::GetVariableForStackLocationAtInstruction(int64_t offset, size_t instr) const +{ + return BNGetMediumLevelILVariableForStackLocationAtInstruction(m_object, offset, instr); +} + + +RegisterValue MediumLevelILFunction::GetRegisterValueAtInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILRegisterValueAtInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetRegisterValueAfterInstruction(uint32_t reg, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILRegisterValueAfterInstruction(m_object, reg, instr); + return RegisterValue::FromAPIObject(value); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleRegisterValuesAtInstruction(uint32_t reg, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleRegisterValuesAtInstruction(m_object, reg, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleRegisterValuesAfterInstruction(uint32_t reg, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(m_object, reg, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetFlagValueAtInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILFlagValueAtInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetFlagValueAfterInstruction(uint32_t flag, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILFlagValueAfterInstruction(m_object, flag, instr); + return RegisterValue::FromAPIObject(value); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleFlagValuesAtInstruction(uint32_t flag, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleFlagValuesAtInstruction(m_object, flag, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleFlagValuesAfterInstruction(uint32_t flag, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleFlagValuesAfterInstruction(m_object, flag, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILStackContentsAtInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +RegisterValue MediumLevelILFunction::GetStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +{ + BNRegisterValue value = BNGetMediumLevelILStackContentsAfterInstruction(m_object, offset, len, instr); + return RegisterValue::FromAPIObject(value); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleStackContentsAtInstruction(int32_t offset, size_t len, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleStackContentsAtInstruction(m_object, offset, len, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +PossibleValueSet MediumLevelILFunction::GetPossibleStackContentsAfterInstruction(int32_t offset, size_t len, size_t instr) +{ + BNPossibleValueSet value = BNGetMediumLevelILPossibleStackContentsAfterInstruction(m_object, offset, len, instr); + return PossibleValueSet::FromAPIObject(value); +} + + +BNILBranchDependence MediumLevelILFunction::GetBranchDependenceAtInstruction(size_t curInstr, size_t branchInstr) const +{ + return BNGetMediumLevelILBranchDependence(m_object, curInstr, branchInstr); +} + + +map<size_t, BNILBranchDependence> MediumLevelILFunction::GetAllBranchDependenceAtInstruction(size_t instr) const +{ + size_t count; + BNILBranchInstructionAndDependence* deps = BNGetAllMediumLevelILBranchDependence(m_object, instr, &count); + + map<size_t, BNILBranchDependence> result; + for (size_t i = 0; i < count; i++) + result[deps[i].branch] = deps[i].dependence; + + BNFreeILBranchDependenceList(deps); + return result; +} + + +Ref<LowLevelILFunction> MediumLevelILFunction::GetLowLevelIL() const +{ + BNLowLevelILFunction* func = BNGetLowLevelILForMediumLevelIL(m_object); + if (!func) + return nullptr; + return new LowLevelILFunction(func); +} + + +size_t MediumLevelILFunction::GetLowLevelILInstructionIndex(size_t instr) const +{ + return BNGetLowLevelILInstructionIndex(m_object, instr); +} + + +size_t MediumLevelILFunction::GetLowLevelILExprIndex(size_t expr) const +{ + return BNGetLowLevelILExprIndex(m_object, expr); +} diff --git a/python/__init__.py b/python/__init__.py index f028bc5b..c7c5f768 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -32,6 +32,7 @@ from .basicblock import * from .function import * from .log import * from .lowlevelil import * +from .mediumlevelil import * from .types import * from .functionrecognizer import * from .update import * diff --git a/python/function.py b/python/function.py index 9e58c47d..18856ff2 100644 --- a/python/function.py +++ b/python/function.py @@ -26,13 +26,14 @@ import ctypes import _binaryninjacore as core from enums import (FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, - DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext) + DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType) import architecture import highlight import associateddatastore import types import basicblock import lowlevelil +import mediumlevelil import binaryview import log @@ -50,93 +51,158 @@ class RegisterValue(object): def __init__(self, arch, value): self.type = RegisterValueType(value.state) if value.state == RegisterValueType.EntryValue: - self.reg = arch.get_reg_name(value.reg) - elif value.state == RegisterValueType.OffsetFromEntryValue: - self.reg = arch.get_reg_name(value.reg) + self.reg = arch.get_reg_name(value.value) + elif value.state == RegisterValueType.ConstantValue: + self.value = value.value + elif value.state == RegisterValueType.StackFrameOffset: self.offset = value.value + + def __repr__(self): + if self.type == RegisterValueType.EntryValue: + return "<entry %s>" % self.reg + if self.type == RegisterValueType.ConstantValue: + return "<const %#x>" % self.value + if self.type == RegisterValueType.StackFrameOffset: + return "<stack frame offset %#x>" % self.offset + if self.type == RegisterValueType.ReturnAddressValue: + return "<return address>" + return "<undetermined>" + + +class ValueRange(object): + def __init__(self, start, end, step): + self.start = start + self.end = end + self.step = step + + def __repr__(self): + if self.step == 1: + return "<range: %#x to %#x>" % (self.start, self.end) + return "<range: %#x to %#x, step %#x>" % (self.start, self.end, self.step) + + +class PossibleValueSet(object): + def __init__(self, arch, value): + self.type = RegisterValueType(value.state) + if value.state == RegisterValueType.EntryValue: + self.reg = arch.get_reg_name(value.value) elif value.state == RegisterValueType.ConstantValue: self.value = value.value elif value.state == RegisterValueType.StackFrameOffset: self.offset = value.value elif value.state == RegisterValueType.SignedRangeValue: self.offset = value.value - self.start = value.rangeStart - self.end = value.rangeEnd - self.step = value.rangeStep - if self.start & (1 << 63): - self.start |= ~((1 << 63) - 1) - if self.end & (1 << 63): - self.end |= ~((1 << 63) - 1) + self.ranges = [] + for i in xrange(0, value.count): + start = value.ranges[i].start + end = value.ranges[i].end + step = value.ranges[i].step + if start & (1 << 63): + start |= ~((1 << 63) - 1) + if end & (1 << 63): + end |= ~((1 << 63) - 1) + self.ranges.append(ValueRange(start, end, step)) elif value.state == RegisterValueType.UnsignedRangeValue: self.offset = value.value - self.start = value.rangeStart - self.end = value.rangeEnd - self.step = value.rangeStep + self.ranges = [] + for i in xrange(0, value.count): + start = value.ranges[i].start + end = value.ranges[i].end + step = value.ranges[i].step + self.ranges.append(ValueRange(start, end, step)) elif value.state == RegisterValueType.LookupTableValue: self.table = [] self.mapping = {} - for i in xrange(0, value.rangeEnd): + for i in xrange(0, value.count): from_list = [] for j in xrange(0, value.table[i].fromCount): from_list.append(value.table[i].fromValues[j]) self.mapping[value.table[i].fromValues[j]] = value.table[i].toValue self.table.append(LookupTableEntry(from_list, value.table[i].toValue)) - elif value.state == RegisterValueType.OffsetFromUndeterminedValue: - self.offset = value.value + elif (value.state == RegisterValueType.InSetOfValues) or (value.state == RegisterValueType.NotInSetOfValues): + self.values = set() + for i in xrange(0, value.count): + self.values.add(value.valueSet[i]) def __repr__(self): if self.type == RegisterValueType.EntryValue: return "<entry %s>" % self.reg - if self.type == RegisterValueType.OffsetFromEntryValue: - return "<entry %s + %#x>" % (self.reg, self.offset) if self.type == RegisterValueType.ConstantValue: return "<const %#x>" % self.value if self.type == RegisterValueType.StackFrameOffset: return "<stack frame offset %#x>" % self.offset - if (self.type == RegisterValueType.SignedRangeValue) or (self.type == RegisterValueType.UnsignedRangeValue): - if self.step == 1: - return "<range: %#x to %#x>" % (self.start, self.end) - return "<range: %#x to %#x, step %#x>" % (self.start, self.end, self.step) + if self.type == RegisterValueType.SignedRangeValue: + return "<signed ranges: %s>" % repr(self.ranges) + if self.type == RegisterValueType.UnsignedRangeValue: + return "<unsigned ranges: %s>" % repr(self.ranges) if self.type == RegisterValueType.LookupTableValue: return "<table: %s>" % ', '.join([repr(i) for i in self.table]) - if self.type == RegisterValueType.OffsetFromUndeterminedValue: - return "<undetermined with offset %#x>" % self.offset + if self.type == RegisterValueType.InSetOfValues: + return "<in %s>" % repr(self.values) + if self.type == RegisterValueType.NotInSetOfValues: + return "<not in %s>" % repr(self.values) + if self.type == RegisterValueType.ReturnAddressValue: + return "<return address>" return "<undetermined>" -class StackVariable(object): - def __init__(self, ofs, name, t): - self.offset = ofs - self.name = name - self.type = t - - def __repr__(self): - return "<var@%x: %s %s>" % (self.offset, self.type, self.name) - - def __str__(self): - return self.name - - class StackVariableReference(object): - def __init__(self, src_operand, t, name, start_ofs, ref_ofs): + def __init__(self, src_operand, t, name, var, ref_ofs): self.source_operand = src_operand self.type = t self.name = name - self.starting_offset = start_ofs + self.var = var self.referenced_offset = ref_ofs if self.source_operand == 0xffffffff: self.source_operand = None def __repr__(self): if self.source_operand is None: - if self.referenced_offset != self.starting_offset: - return "<ref to %s%+#x>" % (self.name, self.referenced_offset - self.starting_offset) + if self.referenced_offset != self.var.storage: + return "<ref to %s%+#x>" % (self.name, self.referenced_offset - self.var.storage) return "<ref to %s>" % self.name - if self.referenced_offset != self.starting_offset: - return "<operand %d ref to %s%+#x>" % (self.source_operand, self.name, self.referenced_offset) + if self.referenced_offset != self.var.storage: + return "<operand %d ref to %s%+#x>" % (self.source_operand, self.name, self.var.storage) return "<operand %d ref to %s>" % (self.source_operand, self.name) +class Variable(object): + def __init__(self, func, source_type, index, storage, name = None, var_type = None): + self.function = func + self.source_type = VariableSourceType(source_type) + self.index = index + self.storage = storage + + var = core.BNVariable() + var.type = source_type + var.index = index + var.storage = storage + self.identifier = core.BNToVariableIdentifier(var) + + if name is None: + name = core.BNGetVariableName(func.handle, var) + if var_type is None: + var_type = core.BNGetVariableType(func.handle, var) + if var_type: + var_type = types.Type(var_type) + + self.name = name + self.type = var_type + + @classmethod + def from_identifier(self, func, identifier, name = None, var_type = None): + var = core.BNFromVariableIdentifier(identifier) + return Variable(func, VariableSourceType(var.type), var.index, var.storage, name, var_type) + + def __repr__(self): + if self.type is None: + return "<var %s>" % self.name + return "<var %s %s%s>" % (self.type.get_string_before_name(), self.name, self.type.get_string_after_name()) + + def __str__(self): + return self.name + + class ConstantReference(object): def __init__(self, val, size): self.value = val @@ -298,6 +364,11 @@ class Function(object): return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedIL(self.handle), self) @property + def medium_level_il(self): + """Function medium level IL (read-only)""" + return mediumlevelil.MediumLevelILFunction(self.arch, core.BNGetFunctionMediumLevelIL(self.handle), self) + + @property def function_type(self): """Function type object""" return types.Type(core.BNGetFunctionType(self.handle)) @@ -308,14 +379,28 @@ class Function(object): @property def stack_layout(self): - """List of function stack (read-only)""" + """List of function stack variables (read-only)""" count = ctypes.c_ulonglong() v = core.BNGetStackLayout(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(StackVariable(v[i].offset, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type)))) - result.sort(key = lambda x: x.offset) - core.BNFreeStackLayout(v, count.value) + result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, + types.Type(handle = core.BNNewTypeReference(v[i].type)))) + result.sort(key = lambda x: x.identifier) + core.BNFreeVariableList(v, count.value) + return result + + @property + def vars(self): + """List of function variables (read-only)""" + count = ctypes.c_ulonglong() + v = core.BNGetFunctionVariables(self.handle, count) + result = [] + for i in xrange(0, count.value): + result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, + types.Type(handle = core.BNNewTypeReference(v[i].type)))) + result.sort(key = lambda x: x.identifier) + core.BNFreeVariableList(v, count.value) return result @property @@ -396,7 +481,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(exits[i]) - core.BNFreeLowLevelILInstructionList(exits) + core.BNFreeILInstructionList(exits) return result def get_reg_value_at(self, addr, reg, arch=None): @@ -418,7 +503,6 @@ class Function(object): reg = arch.regs[reg].index value = core.BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg) result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) return result def get_reg_value_after(self, addr, reg, arch=None): @@ -440,37 +524,6 @@ class Function(object): reg = arch.regs[reg].index value = core.BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg) result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_reg_value_at_low_level_il_instruction(self, i, reg, arch=None): - """ - ``get_reg_value_at_low_level_il_instruction`` returns the value of the specified register ``reg`` at the il address - i - - :param int i: il address of instruction to query - :param Architecture arch: (optional) Architecture for the given function - :rtype: function.RegisterValue - :Example: - - >>> func.get_reg_value_at_low_level_il_instruction(15, 'rdi') - <const 0x2> - """ - if arch is None: - arch = self.arch - if isinstance(reg, str): - reg = self.arch.regs[reg].index - value = core.BNGetRegisterValueAtLowLevelILInstruction(self.handle, i, reg) - result = RegisterValue(arch, value) - core.BNFreeRegisterValue(value) - return result - - def get_reg_value_after_low_level_il_instruction(self, i, reg): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - value = core.BNGetRegisterValueAfterLowLevelILInstruction(self.handle, i, reg) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) return result def get_stack_contents_at(self, addr, offset, size, arch=None): @@ -496,7 +549,6 @@ class Function(object): arch = self.arch 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, addr, offset, size, arch=None): @@ -504,19 +556,6 @@ class Function(object): arch = self.arch 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): - 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): - value = core.BNGetStackContentsAfterInstruction(self.handle, i, offset, size) - result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) return result def get_parameter_at(self, addr, func_type, i, arch=None): @@ -526,7 +565,6 @@ class Function(object): 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): @@ -534,7 +572,6 @@ class Function(object): func_type = func_type.handle value = core.BNGetParameterValueAtLowLevelILInstruction(self.handle, instr, func_type, i) result = RegisterValue(self.arch, value) - core.BNFreeRegisterValue(value) return result def get_regs_read_by(self, addr, arch=None): @@ -566,8 +603,10 @@ class Function(object): refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count) result = [] for i in xrange(0, count.value): - result.append(StackVariableReference(refs[i].sourceOperand, types.Type(core.BNNewTypeReference(refs[i].type)), - refs[i].name, refs[i].startingOffset, refs[i].referencedOffset)) + var_type = types.Type(core.BNNewTypeReference(refs[i].type)) + result.append(StackVariableReference(refs[i].sourceOperand, var_type, + refs[i].name, Variable.from_identifier(self, refs[i].varIdentifier, refs[i].name, var_type), + refs[i].referencedOffset)) core.BNFreeStackVariableReferenceList(refs, count.value) return result @@ -595,7 +634,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_lifted_il_flag_definitions_for_use(self, i, flag): @@ -606,7 +645,7 @@ class Function(object): result = [] for i in xrange(0, count.value): result.append(instrs[i]) - core.BNFreeLowLevelILInstructionList(instrs) + core.BNFreeILInstructionList(instrs) return result def get_flags_read_by_lifted_il_instruction(self, i): @@ -802,6 +841,57 @@ class Function(object): color = highlight.HighlightColor(color) core.BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color._get_core_struct()) + def create_auto_stack_var(self, offset, var_type, name): + core.BNCreateAutoStackVariable(self.handle, offset, var_type.handle, name) + + def create_user_stack_var(self, offset, var_type, name): + core.BNCreateUserStackVariable(self.handle, offset, var_type.handle, name) + + def delete_auto_stack_var(self, offset): + core.BNDeleteAutoStackVariable(self.handle, offset) + + def delete_user_stack_var(self, offset): + core.BNDeleteUserStackVariable(self.handle, offset) + + def create_auto_var(self, var, var_type, name, ignore_disjoint_uses = False): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + core.BNCreateAutoVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses) + + def create_user_var(self, var, var_type, name, ignore_disjoint_uses = False): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + core.BNCreateUserVariable(self.handle, var_data, var_type.handle, name, ignore_disjoint_uses) + + def delete_auto_var(self, var): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + core.BNDeleteAutoVariable(self.handle, var_data) + + def delete_user_var(self, var): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + core.BNDeleteUserVariable(self.handle, var_data) + + def get_stack_var_at_frame_offset(self, offset, addr, arch=None): + if arch is None: + arch = self.arch + found_var = core.BNVariableNameAndType() + if not core.BNGetStackVariableAtFrameOffset(self.handle, arch.handle, addr, offset, found_var): + return None + result = Variable(self, found_var.var.type, found_var.var.index, found_var.var.storage, + found_var.name, types.Type(handle = core.BNNewTypeReference(found_var.type))) + core.BNFreeVariableNameAndType(found_var) + return result + class AdvancedFunctionAnalysisDataRequestor(object): def __init__(self, func = None): diff --git a/python/lowlevelil.py b/python/lowlevelil.py index c80fcd0d..a737d95e 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -25,6 +25,7 @@ import _binaryninjacore as core from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType import function import basicblock +import mediumlevelil class LowLevelILLabel(object): @@ -53,7 +54,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_PUSH: [("src", "expr")], LowLevelILOperation.LLIL_POP: [], LowLevelILOperation.LLIL_REG: [("src", "reg")], - LowLevelILOperation.LLIL_CONST: [("value", "int")], + LowLevelILOperation.LLIL_CONST: [("constant", "int")], LowLevelILOperation.LLIL_FLAG: [("src", "flag")], LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")], LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")], @@ -107,10 +108,29 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_BOOL_TO_INT: [("src", "expr")], LowLevelILOperation.LLIL_SYSCALL: [], LowLevelILOperation.LLIL_BP: [], - LowLevelILOperation.LLIL_TRAP: [("value", "int")], + LowLevelILOperation.LLIL_TRAP: [("vector", "int")], LowLevelILOperation.LLIL_UNDEF: [], LowLevelILOperation.LLIL_UNIMPL: [], - LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")] + LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg"), ("index", "int"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("dest", "reg"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SPLIT_SSA: [("hi", "expr"), ("lo", "expr"), ("src", "expr")], + LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg", "index", "int")], + LowLevelILOperation.LLIL_REG_SSA: [("src", "reg"), ("index", "int")], + LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("src", "reg")], + LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag"), ("index", "int"), ("src", "expr")], + LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag"), ("index", "int")], + LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag"), ("index", "int"), ("bit", "int")], + LowLevelILOperation.LLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")], + LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")], + LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")], + LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg"), ("index", "int"), ("src_memory", "int")], + LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "reg_ssa_list")], + LowLevelILOperation.LLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], + LowLevelILOperation.LLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], + LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg"), ("index", "int"), ("src", "reg_ssa_list")], + LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "reg"), ("index", "int"), ("src", "flag_ssa_list")], + LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] } def __init__(self, func, expr_index, instr_index=None): @@ -142,16 +162,41 @@ class LowLevelILInstruction(object): else: value = func.arch.get_reg_name(instr.operands[i]) elif operand_type == "flag": - value = func.arch.get_flag_name(instr.operands[i]) + if (instr.operands[i] & 0x80000000) != 0: + value = instr.operands[i] + else: + value = func.arch.get_flag_name(instr.operands[i]) elif operand_type == "cond": value = LowLevelILFlagCondition(instr.operands[i]) elif operand_type == "int_list": count = ctypes.c_ulonglong() - operands = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) value = [] for i in xrange(count.value): - value.append(operands[i]) - core.BNLowLevelILFreeOperandList(operands) + value.append(operand_list[i]) + core.BNLowLevelILFreeOperandList(operand_list) + elif operand_type == "reg_ssa_list": + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + value = [] + for i in xrange(count.value / 2): + reg = operand_list[i * 2] + reg_index = operand_list[(i * 2) + 1] + if (reg & 0x80000000) == 0: + reg = func.arch.get_reg_name(reg) + value.append((reg, reg_index)) + core.BNLowLevelILFreeOperandList(operand_list) + elif operand_type == "flag_ssa_list": + count = ctypes.c_ulonglong() + operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + value = [] + for i in xrange(count.value / 2): + flag = operand_list[i * 2] + flag_index = operand_list[(i * 2) + 1] + if (flag & 0x80000000) == 0: + flag = func.arch.get_flag_name(flag) + value.append((flag, flag_index)) + core.BNLowLevelILFreeOperandList(operand_list) self.operands.append(value) self.__dict__[name] = value @@ -193,6 +238,123 @@ class LowLevelILInstruction(object): core.BNFreeInstructionText(tokens, count.value) return result + @property + def ssa_form(self): + """SSA form of expression (read-only)""" + return LowLevelILInstruction(self.function.ssa_form, + core.BNGetLowLevelILSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def non_ssa_form(self): + """Non-SSA form of expression (read-only)""" + return LowLevelILInstruction(self.function.non_ssa_form, + core.BNGetLowLevelILNonSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def mapped_medium_level_il(self): + """Gets the medium level IL expression corresponding to this expression""" + expr = self.function.get_mapped_medium_level_il_expr_index(self.expr_index) + if expr is None: + return None + return mediumlevelil.MediumLevelILInstruction(self.function.mapped_medium_level_il, expr) + + @property + def value(self): + """Value of expression if constant or a known value (read-only)""" + value = core.BNGetLowLevelILExprValue(self.function.handle, self.expr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + @property + def possible_values(self): + """Possible values of expression using path-sensitive static data flow analysis (read-only)""" + value = core.BNGetLowLevelILPossibleExprValues(self.function.handle, self.expr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_reg_value(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetLowLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_reg_value_after(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetLowLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_possible_reg_values(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_possible_reg_values_after(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_flag_value(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetLowLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_flag_value_after(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetLowLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_possible_flag_values(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_possible_flag_values_after(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_stack_contents(self, offset, size): + value = core.BNGetLowLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_stack_contents_after(self, offset, size): + value = core.BNGetLowLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_possible_stack_contents(self, offset, size): + value = core.BNGetLowLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_possible_stack_contents_after(self, offset, size): + value = core.BNGetLowLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -270,7 +432,12 @@ class LowLevelILFunction(object): @current_address.setter def current_address(self, value): - core.BNLowLevelILSetCurrentAddress(self.handle, value) + core.BNLowLevelILSetCurrentAddress(self.handle, self.arch.handle, value) + + def set_current_address(self, value, arch = None): + if arch is None: + arch = self.arch + core.BNLowLevelILSetCurrentAddress(self.handle, arch.handle, value) @property def temp_reg_count(self): @@ -296,6 +463,40 @@ class LowLevelILFunction(object): core.BNFreeBasicBlockList(blocks, count.value) return result + @property + def ssa_form(self): + """Low level IL in SSA form (read-only)""" + result = core.BNGetLowLevelILSSAForm(self.handle) + if not result: + return None + return LowLevelILFunction(self.arch, result, self.source_function) + + @property + def non_ssa_form(self): + """Low level IL in non-SSA (default) form (read-only)""" + result = core.BNGetLowLevelILNonSSAForm(self.handle) + if not result: + return None + return LowLevelILFunction(self.arch, result, self.source_function) + + @property + def medium_level_il(self): + """Medium level IL for this low level IL.""" + result = core.BNGetMediumLevelILForLowLevelIL(self.handle) + if not result: + return None + return mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function) + + @property + def mapped_medium_level_il(self): + """Medium level IL with mappings between low level IL and medium level IL. Unused stores are not removed. + Typically, this should only be used to answer queries on assembly or low level IL where the query is + easier to perform on medium level IL.""" + result = core.BNGetMappedMediumLevelIL(self.handle) + if not result: + return None + return mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function) + def __setattr__(self, name, value): try: object.__setattr__(self, name, value) @@ -329,6 +530,14 @@ class LowLevelILFunction(object): finally: core.BNFreeBasicBlockList(blocks, count.value) + def get_instruction_start(self, addr, arch = None): + if arch is None: + arch = self.arch + result = core.BNLowLevelILGetInstructionStart(self.handle, arch.handle, addr) + if result >= core.BNGetLowLevelILInstructionCount(self.handle): + return None + return result + def clear_indirect_branches(self): core.BNLowLevelILClearIndirectBranches(self.handle) @@ -1262,6 +1471,89 @@ class LowLevelILFunction(object): return None return LowLevelILLabel(label) + def get_ssa_instruction_index(self, instr): + return core.BNGetLowLevelILSSAInstructionIndex(self.handle, instr) + + def get_non_ssa_instruction_index(self, instr): + return core.BNGetLowLevelILNonSSAInstructionIndex(self.handle, instr) + + def get_ssa_reg_definition(self, reg, index): + result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, index) + if result >= core.BNGetLowLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_flag_definition(self, flag, index): + result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, index) + if result >= core.BNGetLowLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_memory_definition(self, index): + result = core.BNGetLowLevelILSSAMemoryDefinition(self.handle, index) + if result >= core.BNGetLowLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_reg_uses(self, reg, index): + count = ctypes.c_ulonglong() + instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_ssa_flag_uses(self, flag, index): + count = ctypes.c_ulonglong() + instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_ssa_memory_uses(self, index): + count = ctypes.c_ulonglong() + instrs = core.BNGetLowLevelILSSAMemoryUses(self.handle, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_ssa_reg_value(self, reg, index): + if isinstance(reg, str): + reg = self.arch.regs[reg].index + value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, index) + result = function.RegisterValue(self.arch, value) + return result + + def get_ssa_flag_value(self, flag, index): + if isinstance(flag, str): + flag = self.arch.get_flag_by_name(flag) + value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, index) + result = function.RegisterValue(self.arch, value) + return result + + def get_mapped_medium_level_il_instruction_index(self, instr): + med_il = self.mapped_medium_level_il + if med_il is None: + return None + result = core.BNGetMappedMediumLevelILInstructionIndex(self.handle, instr) + if result >= core.BNGetMediumLevelILInstructionCount(med_il.handle): + return None + return result + + def get_mapped_medium_level_il_expr_index(self, expr): + med_il = self.mapped_medium_level_il + if med_il is None: + return None + result = core.BNGetMappedMediumLevelILExprIndex(self.handle, expr) + if result >= core.BNGetMediumLevelILExprCount(med_il.handle): + return None + return result + class LowLevelILBasicBlock(basicblock.BasicBlock): def __init__(self, view, handle, owner): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py new file mode 100644 index 00000000..bc7a5c89 --- /dev/null +++ b/python/mediumlevelil.py @@ -0,0 +1,735 @@ +# Copyright (c) 2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import ctypes + +# Binary Ninja components +import _binaryninjacore as core +from .enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDependence +import function +import basicblock +import lowlevelil + + +class MediumLevelILLabel(object): + def __init__(self, handle = None): + if handle is None: + self.handle = (core.BNMediumLevelILLabel * 1)() + core.BNMediumLevelILInitLabel(self.handle) + else: + self.handle = handle + + +class MediumLevelILInstruction(object): + """ + ``class MediumLevelILInstruction`` Medium Level Intermediate Language Instructions are infinite length tree-based + instructions. Tree-based instructions use infix notation with the left hand operand being the destination operand. + Infix notation is thus more natural to read than other notations (e.g. x86 ``mov eax, 0`` vs. MLIL ``eax = 0``). + """ + + ILOperations = { + MediumLevelILOperation.MLIL_NOP: [], + MediumLevelILOperation.MLIL_SET_VAR: [("dest", "var"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_FIELD: [("dest", "var"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT: [("high", "var"), ("low", "var"), ("src", "expr")], + MediumLevelILOperation.MLIL_LOAD: [("src", "expr")], + MediumLevelILOperation.MLIL_STORE: [("dest", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR: [("src", "var")], + MediumLevelILOperation.MLIL_VAR_FIELD: [("src", "var"), ("offset", "int")], + MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")], + MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [("src", "var"), ("offset", "int")], + MediumLevelILOperation.MLIL_CONST: [("constant", "int")], + MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_SBB: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_AND: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_OR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_XOR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_LSL: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_LSR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ASR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ROL: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RLC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_ROR: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_RRC: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MUL: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MULU_DP: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MULS_DP: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVU: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVS: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_DIVS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODU: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODU_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODS: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_MODS_DP: [("hi", "expr"), ("lo", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_NEG: [("src", "expr")], + MediumLevelILOperation.MLIL_NOT: [("src", "expr")], + MediumLevelILOperation.MLIL_SX: [("src", "expr")], + MediumLevelILOperation.MLIL_ZX: [("src", "expr")], + MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], + MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], + MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_CALL_UNTYPED: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_CALL_OUTPUT: [("dest", "var_list")], + MediumLevelILOperation.MLIL_CALL_PARAM: [("src", "var_list")], + MediumLevelILOperation.MLIL_RET: [("src", "expr_list")], + MediumLevelILOperation.MLIL_NORET: [], + MediumLevelILOperation.MLIL_IF: [("condition", "expr"), ("true", "int"), ("false", "int")], + MediumLevelILOperation.MLIL_GOTO: [("dest", "int")], + MediumLevelILOperation.MLIL_CMP_E: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_NE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SLT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_ULT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SLE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_ULE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SGE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_UGE: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_SGT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_CMP_UGT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_TEST_BIT: [("left", "expr"), ("right", "expr")], + MediumLevelILOperation.MLIL_BOOL_TO_INT: [("src", "expr")], + MediumLevelILOperation.MLIL_SYSCALL: [("output", "var_list"), ("params", "expr_list")], + MediumLevelILOperation.MLIL_SYSCALL_UNTYPED: [("output", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_BP: [], + MediumLevelILOperation.MLIL_TRAP: [("vector", "int")], + MediumLevelILOperation.MLIL_UNDEF: [], + MediumLevelILOperation.MLIL_UNIMPL: [], + MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("dest_index", "int"), ("src_index", "int"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "exor")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("offset", "int"), ("src", "exor")], + MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")], + MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")], + MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var"), ("src_memory", "int"), ("offset", "int")], + MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("params", "expr_list"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA: [("output", "expr"), ("params", "expr"), ("stack", "expr")], + MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "var_ssa_list")], + MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], + MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var"), ("index", "int"), ("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] + } + + def __init__(self, func, expr_index, instr_index=None): + instr = core.BNGetMediumLevelILByIndex(func.handle, expr_index) + self.function = func + self.expr_index = expr_index + if instr_index is None: + self.instr_index = core.BNGetMediumLevelILInstructionForExpr(func.handle, expr_index) + else: + self.instr_index = instr_index + self.operation = MediumLevelILOperation(instr.operation) + self.size = instr.size + self.address = instr.address + operands = MediumLevelILInstruction.ILOperations[instr.operation] + self.operands = [] + i = 0 + for operand in operands: + name, operand_type = operand + if operand_type == "int": + value = instr.operands[i] + elif operand_type == "expr": + value = MediumLevelILInstruction(func, instr.operands[i]) + elif operand_type == "var": + value = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + elif operand_type == "int_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + value = [] + for j in xrange(count.value): + value.append(operand_list[j]) + core.BNMediumLevelILFreeOperandList(operand_list) + elif operand_type == "var_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = [] + for j in xrange(count.value): + value.append(function.Variable.from_identifier(self.function.source_function, operand_list[j])) + core.BNMediumLevelILFreeOperandList(operand_list) + elif operand_type == "var_ssa_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = [] + for j in xrange(count.value / 2): + var_id = operand_list[j * 2] + var_index = operand_list[(j * 2) + 2] + value.append((function.Variable.from_identifier(self.function.source_function, + var_id), var_index)) + core.BNMediumLevelILFreeOperandList(operand_list) + elif operand_type == "expr_list": + count = ctypes.c_ulonglong() + operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 + value = [] + for j in xrange(count.value): + value.append(MediumLevelILInstruction(func, operand_list[j])) + core.BNMediumLevelILFreeOperandList(operand_list) + self.operands.append(value) + self.__dict__[name] = value + i += 1 + + def __str__(self): + tokens = self.tokens + if tokens is None: + return "invalid" + result = "" + for token in tokens: + result += token.text + return result + + def __repr__(self): + return "<il: %s>" % str(self) + + @property + def tokens(self): + """MLIL tokens (read-only)""" + count = ctypes.c_ulonglong() + tokens = ctypes.POINTER(core.BNInstructionTextToken)() + if ((self.instr_index is not None) and (self.function.source_function is not None) and + (self.expr_index == core.BNGetMediumLevelILIndexForInstruction(self.function.handle, self.instr_index))): + if not core.BNGetMediumLevelILInstructionText(self.function.handle, self.function.source_function.handle, + self.function.arch.handle, self.instr_index, tokens, count): + return None + else: + if not core.BNGetMediumLevelILExprText(self.function.handle, self.function.arch.handle, + self.expr_index, tokens, count): + return None + result = [] + for i in xrange(0, count.value): + token_type = InstructionTextTokenType(tokens[i].type) + text = tokens[i].text + value = tokens[i].value + size = tokens[i].size + operand = tokens[i].operand + context = tokens[i].context + address = tokens[i].address + result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address)) + core.BNFreeInstructionText(tokens, count.value) + return result + + @property + def ssa_form(self): + """SSA form of expression (read-only)""" + return MediumLevelILInstruction(self.function.ssa_form, + core.BNGetMediumLevelILSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def non_ssa_form(self): + """Non-SSA form of expression (read-only)""" + return MediumLevelILInstruction(self.function.non_ssa_form, + core.BNGetMediumLevelILNonSSAExprIndex(self.function.handle, self.expr_index)) + + @property + def value(self): + """Value of expression if constant or a known value (read-only)""" + value = core.BNGetMediumLevelILExprValue(self.function.handle, self.expr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + @property + def possible_values(self): + """Possible values of expression using path-sensitive static data flow analysis (read-only)""" + value = core.BNGetMediumLevelILPossibleExprValues(self.function.handle, self.expr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + @property + def branch_dependence(self): + """Set of branching instructions that must take the true or false path to reach this instruction""" + count = ctypes.c_ulonglong() + deps = core.BNGetAllMediumLevelILBranchDependence(self.function.handle, self.instr_index, count) + result = {} + for i in xrange(0, count.value): + result[deps[i].branch] = ILBranchDependence(deps[i].dependence) + core.BNFreeILBranchDependenceList(deps) + return result + + @property + def low_level_il(self): + """Low level IL form of this expression""" + expr = self.function.get_low_level_il_expr_index(self.expr_index) + if expr is None: + return None + return lowlevelil.LowLevelILInstruction(self.function.low_level_il.ssa_form, expr) + + @property + def ssa_memory_index(self): + """Index of active memory contents in SSA form for this instruction""" + return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.function.handle, self.instr_index) + + def get_ssa_var_possible_values(self, var, index): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, index, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_ssa_var_index(self, var): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + return core.BNGetMediumLevelILSSAVarIndexAtILInstruction(self.function.handle, var_data, self.instr_index) + + def get_var_for_reg(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index) + return function.Variable(self.function.source_function, result.type, result.index, result.storage) + + def get_var_for_flag(self, flag): + if isinstance(flag, str): + flag = self.function.arch.regs[flag].index + result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index) + return function.Variable(self.function.source_function, result.type, result.index, result.storage) + + def get_var_for_stack_location(self, offset): + result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(self.function.handle, offset, self.instr_index) + return function.Variable(self.function.source_function, result.type, result.index, result.storage) + + def get_reg_value(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_reg_value_after(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_possible_reg_values(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_possible_reg_values_after(self, reg): + if isinstance(reg, str): + reg = self.function.arch.regs[reg].index + value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_flag_value(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_flag_value_after(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_possible_flag_values(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_possible_flag_values_after(self, flag): + if isinstance(flag, str): + flag = self.function.arch.flags[flag].index + value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_stack_contents(self, offset, size): + value = core.BNGetMediumLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_stack_contents_after(self, offset, size): + value = core.BNGetMediumLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = function.RegisterValue(self.function.arch, value) + return result + + def get_possible_stack_contents(self, offset, size): + value = core.BNGetMediumLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_possible_stack_contents_after(self, offset, size): + value = core.BNGetMediumLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) + result = function.PossibleValueSet(self.function.arch, value) + core.BNFreePossibleValueSet(value) + return result + + def get_branch_dependence(self, branch_instr): + return ILBranchDependence(core.BNGetMediumLevelILBranchDependence(self.function.handle, self.instr_index, branch_instr)) + + def __setattr__(self, name, value): + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + +class MediumLevelILExpr(object): + """ + ``class MediumLevelILExpr`` hold the index of IL Expressions. + + .. note:: This class shouldn't be instantiated directly. Rather the helper members of MediumLevelILFunction should be \ + used instead. + """ + def __init__(self, index): + self.index = index + + +class MediumLevelILFunction(object): + """ + ``class MediumLevelILFunction`` contains the list of MediumLevelILExpr objects that make up a function. MediumLevelILExpr + objects can be added to the MediumLevelILFunction by calling ``append`` and passing the result of the various class + methods which return MediumLevelILExpr objects. + """ + def __init__(self, arch, handle = None, source_func = None): + self.arch = arch + self.source_function = source_func + if handle is not None: + self.handle = core.handle_of_type(handle, core.BNMediumLevelILFunction) + else: + func_handle = None + if self.source_function is not None: + func_handle = self.source_function.handle + self.handle = core.BNCreateMediumLevelILFunction(arch.handle, func_handle) + + def __del__(self): + core.BNFreeMediumLevelILFunction(self.handle) + + def __eq__(self, value): + if not isinstance(value, MediumLevelILFunction): + return False + return ctypes.addressof(self.handle.contents) == ctypes.addressof(value.handle.contents) + + def __ne__(self, value): + if not isinstance(value, MediumLevelILFunction): + return True + return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + + @property + def current_address(self): + """Current IL Address (read/write)""" + return core.BNMediumLevelILGetCurrentAddress(self.handle) + + @current_address.setter + def current_address(self, value): + core.BNMediumLevelILSetCurrentAddress(self.handle, self.arch.handle, value) + + def set_current_address(self, value, arch = None): + if arch is None: + arch = self.arch + core.BNMediumLevelILSetCurrentAddress(self.handle, arch.handle, value) + + @property + def basic_blocks(self): + """list of MediumLevelILBasicBlock objects (read-only)""" + count = ctypes.c_ulonglong() + blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count) + result = [] + view = None + if self.source_function is not None: + view = self.source_function.view + for i in xrange(0, count.value): + result.append(MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)) + core.BNFreeBasicBlockList(blocks, count.value) + return result + + @property + def ssa_form(self): + """Medium level IL in SSA form (read-only)""" + result = core.BNGetMediumLevelILSSAForm(self.handle) + if not result: + return None + return MediumLevelILFunction(self.arch, result, self.source_function) + + @property + def non_ssa_form(self): + """Medium level IL in non-SSA (default) form (read-only)""" + result = core.BNGetMediumLevelILNonSSAForm(self.handle) + if not result: + return None + return MediumLevelILFunction(self.arch, result, self.source_function) + + @property + def low_level_il(self): + """Low level IL for this function""" + result = core.BNGetLowLevelILForMediumLevelIL(self.handle) + if not result: + return None + return lowlevelil.LowLevelILFunction(self.arch, result, self.source_function) + + def __setattr__(self, name, value): + try: + object.__setattr__(self, name, value) + except AttributeError: + raise AttributeError("attribute '%s' is read only" % name) + + def __len__(self): + return int(core.BNGetMediumLevelILInstructionCount(self.handle)) + + def __getitem__(self, i): + if isinstance(i, slice) or isinstance(i, tuple): + raise IndexError("expected integer instruction index") + if isinstance(i, MediumLevelILExpr): + return MediumLevelILInstruction(self, i.index) + if (i < 0) or (i >= len(self)): + raise IndexError("index out of range") + return MediumLevelILInstruction(self, core.BNGetMediumLevelILIndexForInstruction(self.handle, i), i) + + def __setitem__(self, i, j): + raise IndexError("instruction modification not implemented") + + def __iter__(self): + count = ctypes.c_ulonglong() + blocks = core.BNGetMediumLevelILBasicBlockList(self.handle, count) + view = None + if self.source_function is not None: + view = self.source_function.view + try: + for i in xrange(0, count.value): + yield MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) + finally: + core.BNFreeBasicBlockList(blocks, count.value) + + def get_instruction_start(self, addr, arch = None): + if arch is None: + arch = self.arch + result = core.BNMediumLevelILGetInstructionStart(self.handle, arch.handle, addr) + if result >= core.BNGetMediumLevelILInstructionCount(self.handle): + return None + return result + + def expr(self, operation, a = 0, b = 0, c = 0, d = 0, e = 0, size = 0): + if isinstance(operation, str): + operation = MediumLevelILOperation[operation] + elif isinstance(operation, MediumLevelILOperation): + operation = operation.value + return MediumLevelILExpr(core.BNMediumLevelILAddExpr(self.handle, operation, size, a, b, c, d, e)) + + def append(self, expr): + """ + ``append`` adds the MediumLevelILExpr ``expr`` to the current MediumLevelILFunction. + + :param MediumLevelILExpr expr: the MediumLevelILExpr to add to the current MediumLevelILFunction + :return: number of MediumLevelILExpr in the current function + :rtype: int + """ + return core.BNMediumLevelILAddInstruction(self.handle, expr.index) + + def goto(self, label): + """ + ``goto`` returns a goto expression which jumps to the provided MediumLevelILLabel. + + :param MediumLevelILLabel label: Label to jump to + :return: the MediumLevelILExpr that jumps to the provided label + :rtype: MediumLevelILExpr + """ + return MediumLevelILExpr(core.BNMediumLevelILGoto(self.handle, label.handle)) + + def if_expr(self, operand, t, f): + """ + ``if_expr`` returns the ``if`` expression which depending on condition ``operand`` jumps to the MediumLevelILLabel + ``t`` when the condition expression ``operand`` is non-zero and ``f`` when it's zero. + + :param MediumLevelILExpr operand: comparison expression to evaluate. + :param MediumLevelILLabel t: Label for the true branch + :param MediumLevelILLabel f: Label for the false branch + :return: the MediumLevelILExpr for the if expression + :rtype: MediumLevelILExpr + """ + return MediumLevelILExpr(core.BNMediumLevelILIf(self.handle, operand.index, t.handle, f.handle)) + + def mark_label(self, label): + """ + ``mark_label`` assigns a MediumLevelILLabel to the current IL address. + + :param MediumLevelILLabel label: + :rtype: None + """ + core.BNMediumLevelILMarkLabel(self.handle, label.handle) + + def add_label_list(self, labels): + """ + ``add_label_list`` returns a label list expression for the given list of MediumLevelILLabel objects. + + :param list(MediumLevelILLabel) lables: the list of MediumLevelILLabel to get a label list expression from + :return: the label list expression + :rtype: MediumLevelILExpr + """ + label_list = (ctypes.POINTER(core.BNMediumLevelILLabel) * len(labels))() + for i in xrange(len(labels)): + label_list[i] = labels[i].handle + return MediumLevelILExpr(core.BNMediumLevelILAddLabelList(self.handle, label_list, len(labels))) + + def add_operand_list(self, operands): + """ + ``add_operand_list`` returns an operand list expression for the given list of integer operands. + + :param list(int) operands: list of operand numbers + :return: an operand list expression + :rtype: MediumLevelILExpr + """ + operand_list = (ctypes.c_ulonglong * len(operands))() + for i in xrange(len(operands)): + operand_list[i] = operands[i] + return MediumLevelILExpr(core.BNMediumLevelILAddOperandList(self.handle, operand_list, len(operands))) + + def operand(self, n, expr): + """ + ``operand`` sets the operand number of the expression ``expr`` and passes back ``expr`` without modification. + + :param int n: + :param MediumLevelILExpr expr: + :return: returns the expression ``expr`` unmodified + :rtype: MediumLevelILExpr + """ + core.BNMediumLevelILSetExprSourceOperand(self.handle, expr.index, n) + return expr + + def finalize(self): + """ + ``finalize`` ends the function and computes the list of basic blocks. + + :rtype: None + """ + core.BNFinalizeMediumLevelILFunction(self.handle) + + def get_ssa_instruction_index(self, instr): + return core.BNGetMediumLevelILSSAInstructionIndex(self.handle, instr) + + def get_non_ssa_instruction_index(self, instr): + return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr) + + def get_ssa_var_definition(self, var, index): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, index) + if result >= core.BNGetMediumLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_memory_definition(self, index): + result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, index) + if result >= core.BNGetMediumLevelILInstructionCount(self.handle): + return None + return result + + def get_ssa_var_uses(self, var, index): + count = ctypes.c_ulonglong() + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_ssa_memory_uses(self, index): + count = ctypes.c_ulonglong() + instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, index, count) + result = [] + for i in xrange(0, count.value): + result.append(instrs[i]) + core.BNFreeILInstructionList(instrs) + return result + + def get_ssa_var_value(self, var, index): + var_data = core.BNVariable() + var_data.type = var.source_type + var_data.index = var.index + var_data.storage = var.storage + value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index) + result = function.RegisterValue(self.arch, value) + return result + + def get_low_level_il_instruction_index(self, instr): + low_il = self.low_level_il + if low_il is None: + return None + low_il = low_il.ssa_form + if low_il is None: + return None + result = core.BNGetLowLevelILInstructionIndex(self.handle, instr) + if result >= core.BNGetLowLevelILInstructionCount(low_il.handle): + return None + return result + + def get_low_level_il_expr_index(self, expr): + low_il = self.low_level_il + if low_il is None: + return None + low_il = low_il.ssa_form + if low_il is None: + return None + result = core.BNGetLowLevelILExprIndex(self.handle, expr) + if result >= core.BNGetLowLevelILExprCount(low_il.handle): + return None + return result + + +class MediumLevelILBasicBlock(basicblock.BasicBlock): + def __init__(self, view, handle, owner): + super(MediumLevelILBasicBlock, self).__init__(view, handle) + self.il_function = owner + + def __iter__(self): + for idx in xrange(self.start, self.end): + yield self.il_function[idx] + + def __getitem__(self, idx): + size = self.end - self.start + if idx > size or idx < -size: + raise IndexError("list index is out of range") + if idx >= 0: + return self.il_function[idx + self.start] + else: + return self.il_function[self.end + idx] |
