summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--architecture.cpp378
-rw-r--r--binaryninjaapi.h89
-rw-r--r--binaryninjacore.h4
-rw-r--r--examples/x86_extension/src/x86_extension.cpp585
4 files changed, 490 insertions, 566 deletions
diff --git a/architecture.cpp b/architecture.cpp
index 90f8e622..a1aaca2d 100644
--- a/architecture.cpp
+++ b/architecture.cpp
@@ -640,6 +640,13 @@ bool Architecture::SkipAndReturnValueCallback(void* ctxt, uint8_t* data, uint64_
}
+void Architecture::Register(BNCustomArchitecture* callbacks)
+{
+ AddRefForRegistration();
+ BNRegisterArchitecture(m_nameForRegister.c_str(), callbacks);
+}
+
+
void Architecture::Register(Architecture* arch)
{
BNCustomArchitecture callbacks;
@@ -701,8 +708,7 @@ void Architecture::Register(Architecture* arch)
callbacks.alwaysBranch = AlwaysBranchCallback;
callbacks.invertBranch = InvertBranchCallback;
callbacks.skipAndReturnValue = SkipAndReturnValueCallback;
- arch->AddRefForRegistration();
- BNRegisterArchitecture(arch->m_nameForRegister.c_str(), &callbacks);
+ arch->Register(&callbacks);
}
@@ -1228,6 +1234,12 @@ Ref<Platform> Architecture::GetStandalonePlatform()
}
+void Architecture::AddArchitectureRedirection(Architecture* from, Architecture* to)
+{
+ BNAddArchitectureRedirection(m_object, from->GetObject(), to->GetObject());
+}
+
+
CoreArchitecture::CoreArchitecture(BNArchitecture* arch): Architecture(arch)
{
}
@@ -1712,3 +1724,365 @@ bool CoreArchitecture::SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t l
{
return BNArchitectureSkipAndReturnValue(m_object, data, addr, len, value);
}
+
+
+ArchitectureExtension::ArchitectureExtension(const string& name, Architecture* base): Architecture(name), m_base(base)
+{
+}
+
+
+void ArchitectureExtension::Register(BNCustomArchitecture* callbacks)
+{
+ AddRefForRegistration();
+ BNRegisterArchitectureExtension(m_nameForRegister.c_str(), m_base->GetObject(), callbacks);
+}
+
+
+BNEndianness ArchitectureExtension::GetEndianness() const
+{
+ return m_base->GetEndianness();
+}
+
+
+size_t ArchitectureExtension::GetAddressSize() const
+{
+ return m_base->GetAddressSize();
+}
+
+
+size_t ArchitectureExtension::GetDefaultIntegerSize() const
+{
+ return m_base->GetDefaultIntegerSize();
+}
+
+
+size_t ArchitectureExtension::GetInstructionAlignment() const
+{
+ return m_base->GetInstructionAlignment();
+}
+
+
+size_t ArchitectureExtension::GetMaxInstructionLength() const
+{
+ return m_base->GetMaxInstructionLength();
+}
+
+
+size_t ArchitectureExtension::GetOpcodeDisplayLength() const
+{
+ return m_base->GetOpcodeDisplayLength();
+}
+
+
+Ref<Architecture> ArchitectureExtension::GetAssociatedArchitectureByAddress(uint64_t& addr)
+{
+ Ref<Architecture> result = m_base->GetAssociatedArchitectureByAddress(addr);
+ if (result == m_base)
+ return this;
+ return result;
+}
+
+
+bool ArchitectureExtension::GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result)
+{
+ return m_base->GetInstructionInfo(data, addr, maxLen, result);
+}
+
+
+bool ArchitectureExtension::GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len,
+ vector<InstructionTextToken>& result)
+{
+ return m_base->GetInstructionText(data, addr, len, result);
+}
+
+
+bool ArchitectureExtension::GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il)
+{
+ return m_base->GetInstructionLowLevelIL(data, addr, len, il);
+}
+
+
+string ArchitectureExtension::GetRegisterName(uint32_t reg)
+{
+ return m_base->GetRegisterName(reg);
+}
+
+
+string ArchitectureExtension::GetFlagName(uint32_t flag)
+{
+ return m_base->GetFlagName(flag);
+}
+
+
+string ArchitectureExtension::GetFlagWriteTypeName(uint32_t flags)
+{
+ return m_base->GetFlagWriteTypeName(flags);
+}
+
+
+string ArchitectureExtension::GetSemanticFlagClassName(uint32_t semClass)
+{
+ return m_base->GetSemanticFlagClassName(semClass);
+}
+
+
+string ArchitectureExtension::GetSemanticFlagGroupName(uint32_t semGroup)
+{
+ return m_base->GetSemanticFlagGroupName(semGroup);
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetFullWidthRegisters()
+{
+ return m_base->GetFullWidthRegisters();
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetAllRegisters()
+{
+ return m_base->GetAllRegisters();
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetAllFlags()
+{
+ return m_base->GetAllFlags();
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetAllFlagWriteTypes()
+{
+ return m_base->GetAllFlagWriteTypes();
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetAllSemanticFlagClasses()
+{
+ return m_base->GetAllSemanticFlagClasses();
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetAllSemanticFlagGroups()
+{
+ return m_base->GetAllSemanticFlagGroups();
+}
+
+
+BNFlagRole ArchitectureExtension::GetFlagRole(uint32_t flag, uint32_t semClass)
+{
+ return m_base->GetFlagRole(flag, semClass);
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond,
+ uint32_t semClass)
+{
+ return m_base->GetFlagsRequiredForFlagCondition(cond, semClass);
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup)
+{
+ return m_base->GetFlagsRequiredForSemanticFlagGroup(semGroup);
+}
+
+
+map<uint32_t, BNLowLevelILFlagCondition> ArchitectureExtension::GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup)
+{
+ return m_base->GetFlagConditionsForSemanticFlagGroup(semGroup);
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetFlagsWrittenByFlagWriteType(uint32_t writeType)
+{
+ return m_base->GetFlagsWrittenByFlagWriteType(writeType);
+}
+
+
+uint32_t ArchitectureExtension::GetSemanticClassForFlagWriteType(uint32_t writeType)
+{
+ return m_base->GetSemanticClassForFlagWriteType(writeType);
+}
+
+
+ExprId ArchitectureExtension::GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
+ uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il)
+{
+ return m_base->GetFlagWriteLowLevelIL(op, size, flagWriteType, flag, operands, operandCount, il);
+}
+
+
+ExprId ArchitectureExtension::GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond,
+ uint32_t semClass, LowLevelILFunction& il)
+{
+ return m_base->GetFlagConditionLowLevelIL(cond, semClass, il);
+}
+
+
+ExprId ArchitectureExtension::GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il)
+{
+ return m_base->GetSemanticFlagGroupLowLevelIL(semGroup, il);
+}
+
+
+BNRegisterInfo ArchitectureExtension::GetRegisterInfo(uint32_t reg)
+{
+ return m_base->GetRegisterInfo(reg);
+}
+
+
+uint32_t ArchitectureExtension::GetStackPointerRegister()
+{
+ return m_base->GetStackPointerRegister();
+}
+
+
+uint32_t ArchitectureExtension::GetLinkRegister()
+{
+ return m_base->GetLinkRegister();
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetGlobalRegisters()
+{
+ return m_base->GetGlobalRegisters();
+}
+
+
+string ArchitectureExtension::GetRegisterStackName(uint32_t regStack)
+{
+ return m_base->GetRegisterStackName(regStack);
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetAllRegisterStacks()
+{
+ return m_base->GetAllRegisterStacks();
+}
+
+
+BNRegisterStackInfo ArchitectureExtension::GetRegisterStackInfo(uint32_t regStack)
+{
+ return m_base->GetRegisterStackInfo(regStack);
+}
+
+
+string ArchitectureExtension::GetIntrinsicName(uint32_t intrinsic)
+{
+ return m_base->GetIntrinsicName(intrinsic);
+}
+
+
+vector<uint32_t> ArchitectureExtension::GetAllIntrinsics()
+{
+ return m_base->GetAllIntrinsics();
+}
+
+
+vector<NameAndType> ArchitectureExtension::GetIntrinsicInputs(uint32_t intrinsic)
+{
+ return m_base->GetIntrinsicInputs(intrinsic);
+}
+
+
+vector<Confidence<Ref<Type>>> ArchitectureExtension::GetIntrinsicOutputs(uint32_t intrinsic)
+{
+ return m_base->GetIntrinsicOutputs(intrinsic);
+}
+
+
+bool ArchitectureExtension::Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors)
+{
+ return m_base->Assemble(code, addr, result, errors);
+}
+
+
+bool ArchitectureExtension::IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len)
+{
+ return m_base->IsNeverBranchPatchAvailable(data, addr, len);
+}
+
+
+bool ArchitectureExtension::IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len)
+{
+ return m_base->IsAlwaysBranchPatchAvailable(data, addr, len);
+}
+
+
+bool ArchitectureExtension::IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len)
+{
+ return m_base->IsInvertBranchPatchAvailable(data, addr, len);
+}
+
+
+bool ArchitectureExtension::IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len)
+{
+ return m_base->IsSkipAndReturnValuePatchAvailable(data, addr, len);
+}
+
+
+bool ArchitectureExtension::IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len)
+{
+ return m_base->IsSkipAndReturnValuePatchAvailable(data, addr, len);
+}
+
+
+bool ArchitectureExtension::ConvertToNop(uint8_t* data, uint64_t addr, size_t len)
+{
+ return m_base->ConvertToNop(data, addr, len);
+}
+
+
+bool ArchitectureExtension::AlwaysBranch(uint8_t* data, uint64_t addr, size_t len)
+{
+ return m_base->AlwaysBranch(data, addr, len);
+}
+
+
+bool ArchitectureExtension::InvertBranch(uint8_t* data, uint64_t addr, size_t len)
+{
+ return m_base->InvertBranch(data, addr, len);
+}
+
+
+bool ArchitectureExtension::SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value)
+{
+ return m_base->SkipAndReturnValue(data, addr, len, value);
+}
+
+
+ArchitectureHook::ArchitectureHook(Architecture* base): CoreArchitecture(nullptr), m_base(base)
+{
+ // Architecture hooks allow existing architecture implementations to be extended without creating
+ // a new Architecture object for the changes. By deriving from the ArchitectureHook class and passing
+ // the original Architecture object of the architecture to be extended, any reimplemented functions
+ // will be called first before the original architecture's implementation. You MUST call the base
+ // class method to call the original implementation's version of the function, as calling the
+ // same function on the original Architecture object will call your implementation again.
+
+ // Example of a hook to modify the lifting process:
+
+ // class ArchitectureHookExample: public ArchitectureHook
+ // {
+ // public:
+ // ArchitectureHookExample(Architecture* existingArch) : ArchitectureHook(existingArch)
+ // {
+ // }
+ //
+ // virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len,
+ // LowLevelILFunction& il) override
+ // {
+ // // Perform extra lifting here
+ // // ...
+ // // For unhandled cases, call the original architecture's implementation
+ // return ArchitectureHook::GetInstructionLowLevelIL(data, addr, len, il);
+ // }
+ // };
+}
+
+
+void ArchitectureHook::Register(BNCustomArchitecture* callbacks)
+{
+ AddRefForRegistration();
+ m_object = BNRegisterArchitectureHook(m_base->GetObject(), callbacks);
+}
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 91162af7..89eba009 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -1668,6 +1668,8 @@ namespace BinaryNinja
static bool InvertBranchCallback(void* ctxt, uint8_t* data, uint64_t addr, size_t len);
static bool SkipAndReturnValueCallback(void* ctxt, uint8_t* data, uint64_t addr, size_t len, uint64_t value);
+ virtual void Register(BNCustomArchitecture* callbacks);
+
public:
Architecture(const std::string& name);
@@ -1832,6 +1834,8 @@ namespace BinaryNinja
Ref<CallingConvention> GetStdcallCallingConvention();
Ref<CallingConvention> GetFastcallCallingConvention();
Ref<Platform> GetStandalonePlatform();
+
+ void AddArchitectureRedirection(Architecture* from, Architecture* to);
};
class CoreArchitecture: public Architecture
@@ -1900,6 +1904,91 @@ namespace BinaryNinja
virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override;
};
+ class ArchitectureExtension: public Architecture
+ {
+ protected:
+ Ref<Architecture> m_base;
+
+ virtual void Register(BNCustomArchitecture* callbacks) override;
+
+ public:
+ ArchitectureExtension(const std::string& name, Architecture* base);
+
+ Ref<Architecture> GetBaseArchitecture() const { return m_base; }
+
+ virtual BNEndianness GetEndianness() const override;
+ virtual size_t GetAddressSize() const override;
+ virtual size_t GetDefaultIntegerSize() const override;
+ virtual size_t GetInstructionAlignment() const override;
+ virtual size_t GetMaxInstructionLength() const override;
+ virtual size_t GetOpcodeDisplayLength() const override;
+ virtual Ref<Architecture> GetAssociatedArchitectureByAddress(uint64_t& addr) override;
+ virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override;
+ virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len,
+ std::vector<InstructionTextToken>& result) override;
+ virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override;
+ virtual std::string GetRegisterName(uint32_t reg) override;
+ virtual std::string GetFlagName(uint32_t flag) override;
+ virtual std::string GetFlagWriteTypeName(uint32_t flags) override;
+ virtual std::string GetSemanticFlagClassName(uint32_t semClass) override;
+ virtual std::string GetSemanticFlagGroupName(uint32_t semGroup) override;
+ virtual std::vector<uint32_t> GetFullWidthRegisters() override;
+ virtual std::vector<uint32_t> GetAllRegisters() override;
+ virtual std::vector<uint32_t> GetAllFlags() override;
+ virtual std::vector<uint32_t> GetAllFlagWriteTypes() override;
+ virtual std::vector<uint32_t> GetAllSemanticFlagClasses() override;
+ virtual std::vector<uint32_t> GetAllSemanticFlagGroups() override;
+ virtual BNFlagRole GetFlagRole(uint32_t flag, uint32_t semClass = 0) override;
+ virtual std::vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond,
+ uint32_t semClass = 0) override;
+ virtual std::vector<uint32_t> GetFlagsRequiredForSemanticFlagGroup(uint32_t semGroup) override;
+ virtual std::map<uint32_t, BNLowLevelILFlagCondition> GetFlagConditionsForSemanticFlagGroup(uint32_t semGroup) override;
+ virtual std::vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType) override;
+ virtual uint32_t GetSemanticClassForFlagWriteType(uint32_t writeType) override;
+ virtual ExprId GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
+ uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override;
+ virtual ExprId GetFlagConditionLowLevelIL(BNLowLevelILFlagCondition cond,
+ uint32_t semClass, LowLevelILFunction& il) override;
+ virtual ExprId GetSemanticFlagGroupLowLevelIL(uint32_t semGroup, LowLevelILFunction& il) override;
+ virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override;
+ virtual uint32_t GetStackPointerRegister() override;
+ virtual uint32_t GetLinkRegister() override;
+ virtual std::vector<uint32_t> GetGlobalRegisters() override;
+
+ virtual std::string GetRegisterStackName(uint32_t regStack) override;
+ virtual std::vector<uint32_t> GetAllRegisterStacks() override;
+ virtual BNRegisterStackInfo GetRegisterStackInfo(uint32_t regStack) override;
+
+ virtual std::string GetIntrinsicName(uint32_t intrinsic) override;
+ virtual std::vector<uint32_t> GetAllIntrinsics() override;
+ virtual std::vector<NameAndType> GetIntrinsicInputs(uint32_t intrinsic) override;
+ virtual std::vector<Confidence<Ref<Type>>> GetIntrinsicOutputs(uint32_t intrinsic) override;
+
+ virtual bool Assemble(const std::string& code, uint64_t addr, DataBuffer& result, std::string& errors) override;
+
+ virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override;
+ virtual bool IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override;
+ virtual bool IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override;
+ virtual bool IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override;
+ virtual bool IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override;
+
+ virtual bool ConvertToNop(uint8_t* data, uint64_t addr, size_t len) override;
+ virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override;
+ virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override;
+ virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override;
+ };
+
+ class ArchitectureHook: public CoreArchitecture
+ {
+ protected:
+ Ref<Architecture> m_base;
+
+ virtual void Register(BNCustomArchitecture* callbacks) override;
+
+ public:
+ ArchitectureHook(Architecture* base);
+ };
+
class Structure;
class NamedTypeReference;
class Enumeration;
diff --git a/binaryninjacore.h b/binaryninjacore.h
index fa7a818a..5329a1d9 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -2085,6 +2085,10 @@ extern "C"
BINARYNINJACOREAPI BNArchitecture** BNGetArchitectureList(size_t* count);
BINARYNINJACOREAPI void BNFreeArchitectureList(BNArchitecture** archs);
BINARYNINJACOREAPI BNArchitecture* BNRegisterArchitecture(const char* name, BNCustomArchitecture* arch);
+ BINARYNINJACOREAPI BNArchitecture* BNRegisterArchitectureExtension(const char* name,
+ BNArchitecture* base, BNCustomArchitecture* arch);
+ BINARYNINJACOREAPI void BNAddArchitectureRedirection(BNArchitecture* arch, BNArchitecture* from, BNArchitecture* to);
+ BINARYNINJACOREAPI BNArchitecture* BNRegisterArchitectureHook(BNArchitecture* base, BNCustomArchitecture* arch);
BINARYNINJACOREAPI char* BNGetArchitectureName(BNArchitecture* arch);
BINARYNINJACOREAPI BNEndianness BNGetArchitectureEndianness(BNArchitecture* arch);
diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp
index a2ba4c9c..87f2c2cb 100644
--- a/examples/x86_extension/src/x86_extension.cpp
+++ b/examples/x86_extension/src/x86_extension.cpp
@@ -10,572 +10,37 @@ using namespace std;
using namespace asmx86;
-#define IL_FLAG_C 0
-#define IL_FLAG_P 2
-#define IL_FLAG_A 4
-#define IL_FLAG_Z 6
-#define IL_FLAG_S 7
-#define IL_FLAG_D 10
-#define IL_FLAG_O 11
-
-#define IL_FLAGWRITE_ALL 1
-#define IL_FLAGWRITE_NOCARRY 2
-#define IL_FLAGWRITE_CO 3
-
-#define REG_FSBASE 0x100
-#define REG_GSBASE 0x101
-
-#define TRAP_DIV 0
-#define TRAP_ICEBP 1
-#define TRAP_NMI 2
-#define TRAP_BP 3
-#define TRAP_OVERFLOW 4
-#define TRAP_BOUND 5
-#define TRAP_ILL 6
-#define TRAP_NOT_AVAIL 7
-#define TRAP_DOUBLE 8
-#define TRAP_TSS 10
-#define TRAP_NO_SEG 11
-#define TRAP_STACK 12
-#define TRAP_GPF 13
-#define TRAP_PAGE 14
-#define TRAP_FPU 16
-#define TRAP_ALIGN 17
-#define TRAP_MCE 18
-#define TRAP_SIMD 19
-
-static uint8_t GetShiftCountForScale(uint8_t scale)
-{
- switch (scale)
- {
- case 2:
- return 1;
- case 4:
- return 2;
- case 8:
- return 3;
- default:
- return 0;
- }
-}
-
-
-static uint32_t GetStackPointer(size_t addrSize)
-{
- switch (addrSize)
- {
- case 2:
- return REG_SP;
- case 4:
- return REG_ESP;
- default:
- return REG_RSP;
- }
-}
-
-
-static uint32_t GetFramePointer(size_t addrSize)
-{
- switch (addrSize)
- {
- case 2:
- return REG_BP;
- case 4:
- return REG_EBP;
- default:
- return REG_RBP;
- }
-}
-
-
-static uint32_t GetCountRegister(size_t addrSize)
-{
- switch (addrSize)
- {
- case 2:
- return REG_CX;
- case 4:
- return REG_ECX;
- default:
- return REG_RCX;
- }
-}
-
-
-static size_t GetILOperandMemoryAddress(LowLevelILFunction& il, InstructionOperand& operand, size_t i, size_t addrSize)
-{
- size_t offset;
- if (operand.operand != MEM)
- offset = il.Operand(i, il.Undefined());
- else if ((operand.components[0] == NONE) && (operand.components[1] == NONE) && operand.relative)
- offset = il.Operand(i, il.ConstPointer(addrSize, operand.immediate));
- else if ((operand.components[0] == NONE) && (operand.components[1] == NONE))
- offset = il.Operand(i, il.Const(addrSize, operand.immediate));
- else if ((operand.components[1] == NONE) && (operand.immediate == 0))
- offset = il.Operand(i, il.Register(addrSize, operand.components[0]));
- else if (operand.components[1] == NONE)
- {
- offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]),
- il.Const(addrSize, operand.immediate)));
- }
- else if ((operand.components[0] == NONE) && (operand.scale == 1) && (operand.immediate == 0))
- offset = il.Operand(i, il.Register(addrSize, operand.components[1]));
- else if ((operand.components[0] == NONE) && (operand.scale == 1))
- {
- offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[1]),
- il.Const(addrSize, operand.immediate)));
- }
- else if ((operand.components[0] == NONE) && (operand.immediate == 0))
- {
- offset = il.Operand(i, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]),
- il.Const(1, GetShiftCountForScale(operand.scale))));
- }
- else if (operand.components[0] == NONE)
- {
- offset = il.Operand(i, il.Add(addrSize, il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]),
- il.Const(1, GetShiftCountForScale(operand.scale))), il.Const(addrSize, operand.immediate)));
- }
- else if ((operand.scale == 1) && (operand.immediate == 0))
- {
- offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]),
- il.Register(addrSize, operand.components[1])));
- }
- else if (operand.scale == 1)
- {
- offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]),
- il.Register(addrSize, operand.components[1])), il.Const(addrSize, operand.immediate)));
- }
- else if (operand.immediate == 0)
- {
- offset = il.Operand(i, il.Add(addrSize, il.Register(addrSize, operand.components[0]),
- il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]),
- il.Const(1, GetShiftCountForScale(operand.scale)))));
- }
- else
- {
- offset = il.Operand(i, il.Add(addrSize, il.Add(addrSize, il.Register(addrSize, operand.components[0]),
- il.ShiftLeft(addrSize, il.Register(addrSize, operand.components[1]),
- il.Const(1, GetShiftCountForScale(operand.scale)))), il.Const(addrSize, operand.immediate)));
- }
-
- if (operand.segment == SEG_FS)
- return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_FSBASE), offset));
- if (operand.segment == SEG_GS)
- return il.Operand(i, il.Add(addrSize, il.Register(addrSize, REG_GSBASE), offset));
- return offset;
-}
-
-
-static size_t ReadILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, bool isAddress = false)
-{
- InstructionOperand& operand = instr.operands[i];
- switch (operand.operand)
- {
- case NONE:
- return il.Undefined();
- case IMM:
- if (isAddress)
- return il.Operand(i, il.ConstPointer(operand.size, operand.immediate));
- else
- return il.Operand(i, il.Const(operand.size, operand.immediate));
- case MEM:
- return il.Operand(i, il.Load(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize)));
- default:
- return il.Operand(i, il.Register(operand.size, operand.operand));
- }
-}
-
-
-static size_t WriteILOperand(LowLevelILFunction& il, Instruction& instr, size_t i, size_t addrSize, size_t value)
-{
- InstructionOperand& operand = instr.operands[i];
- switch (operand.operand)
- {
- case NONE:
- case IMM:
- return il.Undefined();
- case MEM:
- return il.Operand(i, il.Store(operand.size, GetILOperandMemoryAddress(il, operand, i, addrSize), value));
- default:
- return il.Operand(i, il.SetRegister(operand.size, operand.operand, value));
- }
-}
-
-
-static size_t DirectJump(Architecture* arch, LowLevelILFunction& il, uint64_t target, size_t addrSize)
-{
- BNLowLevelILLabel* label = il.GetLabelForAddress(arch, target);
- if (label)
- return il.Goto(*label);
- else
- return il.Jump(il.ConstPointer(addrSize, target));
-}
-
-
-static void ConditionalJump(Architecture* arch, LowLevelILFunction& il, size_t cond, size_t addrSize, uint64_t t, uint64_t f)
-{
- BNLowLevelILLabel* trueLabel = il.GetLabelForAddress(arch, t);
- BNLowLevelILLabel* falseLabel = il.GetLabelForAddress(arch, f);
-
- if (trueLabel && falseLabel)
- {
- il.AddInstruction(il.If(cond, *trueLabel, *falseLabel));
- return;
- }
-
- LowLevelILLabel trueCode, falseCode;
-
- if (trueLabel)
- {
- il.AddInstruction(il.If(cond, *trueLabel, falseCode));
- il.MarkLabel(falseCode);
- il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f)));
- return;
- }
-
- if (falseLabel)
- {
- il.AddInstruction(il.If(cond, trueCode, *falseLabel));
- il.MarkLabel(trueCode);
- il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t)));
- return;
- }
-
- il.AddInstruction(il.If(cond, trueCode, falseCode));
- il.MarkLabel(trueCode);
- il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t)));
- il.MarkLabel(falseCode);
- il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f)));
-}
-
-
-static void DirFlagIf(size_t addrSize,
- LowLevelILFunction& il,
- std::function<void (size_t addrSize, LowLevelILFunction& il)> addPreTestIl,
- std::function<void (size_t addrSize, LowLevelILFunction& il)> addDirFlagSetIl,
- std::function<void (size_t addrSize, LowLevelILFunction& il)> addDirFlagClearIl)
-{
- LowLevelILLabel dirFlagSet, dirFlagClear, dirFlagDone;
-
- addPreTestIl(addrSize, il);
-
- il.AddInstruction(il.If(il.Flag(IL_FLAG_D), dirFlagSet, dirFlagClear));
- il.MarkLabel(dirFlagSet);
-
- addDirFlagSetIl(addrSize, il);
-
- il.AddInstruction(il.Goto(dirFlagDone));
- il.MarkLabel(dirFlagClear);
-
- addDirFlagClearIl(addrSize, il);
-
- il.AddInstruction(il.Goto(dirFlagDone));
- il.MarkLabel(dirFlagDone);
-}
-
-
-static void Repeat(size_t addrSize,
- Instruction& instr,
- LowLevelILFunction& il,
- std::function<void (size_t addrSize, LowLevelILFunction& il)> addil)
-{
- LowLevelILLabel trueLabel, falseLabel, doneLabel;
- if (instr.flags & X86_FLAG_ANY_REP)
- {
- il.AddInstruction(il.Goto(trueLabel));
- il.MarkLabel(trueLabel);
- il.AddInstruction(il.If(il.CompareEqual(addrSize, il.Register(addrSize, GetCountRegister(addrSize)),
- il.Const(addrSize, 0)), doneLabel, falseLabel));
- il.MarkLabel(falseLabel);
- }
-
- addil(addrSize, il);
-
- if (instr.flags & X86_FLAG_ANY_REP)
- {
- il.AddInstruction(il.SetRegister(addrSize, GetCountRegister(addrSize),
- il.Sub(addrSize, il.Register(addrSize, GetCountRegister(addrSize)),
- il.Const(addrSize, 1))));
- if (instr.flags & X86_FLAG_REPE)
- il.AddInstruction(il.If(il.FlagCondition(LLFC_E), trueLabel, doneLabel));
- else if (instr.flags & X86_FLAG_REPNE)
- il.AddInstruction(il.If(il.FlagCondition(LLFC_NE), trueLabel, doneLabel));
- else
- il.AddInstruction(il.Goto(trueLabel));
- il.MarkLabel(doneLabel);
- }
-}
-
-
// This is a wrapper for the x86 architecture. Its useful for extending and improving
// the existing core x86 architecture.
-class x86ArchitectureExtension: public Architecture
+class x86ArchitectureExtension: public ArchitectureHook
{
- Architecture* m_arch;
public:
- x86ArchitectureExtension() : Architecture("x86_extension")
- {
- m_arch = new CoreArchitecture(BNGetArchitectureByName("x86"));
- }
-
- virtual size_t GetAddressSize() const override
- {
- return 4;
- }
-
- virtual BNEndianness GetEndianness() const override
+ x86ArchitectureExtension(Architecture* x86) : ArchitectureHook(x86)
{
- return LittleEndian;
- }
-
- virtual size_t GetInstructionAlignment() const override
- {
- return 1;
- }
-
- virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override
- {
- return m_arch->GetInstructionInfo(data, addr, maxLen, result);
- }
-
- virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len, vector<InstructionTextToken>& result) override
- {
- return m_arch->GetInstructionText(data, addr, len, result);
}
virtual bool GetInstructionLowLevelIL(const uint8_t* data, uint64_t addr, size_t& len, LowLevelILFunction& il) override
{
Instruction instr;
- if (!asmx86::Disassemble32(data, addr, len, &instr))
+ if (asmx86::Disassemble32(data, addr, len, &instr))
{
- il.AddInstruction(il.Undefined());
- return false;
+ switch (instr.operation)
+ {
+ case CPUID:
+ // The default implementation of CPUID doesn't set registers to constant values
+ // Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1
+ il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read
+ il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3)));
+ il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800)));
+ il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf)));
+ il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff)));
+ len = instr.length;
+ return true;
+ default:
+ break;
+ }
}
-
- size_t addrSize = 4;
- switch (instr.operation)
- {
- case CPUID:
- // The default implementation of CPUID doesn't set registers to constant values
- // Here we'll emulate a Intel(R) Core(TM) i5-6267U CPU @ 2.90GHz with _eax set to 1
- il.AddInstruction(il.Register(4, REG_EAX)); // Reference the register so we know it is read
- il.AddInstruction(il.SetRegister(4, REG_EAX, il.Const(4, 0x000406e3)));
- il.AddInstruction(il.SetRegister(4, REG_EBX, il.Const(4, 0x03100800)));
- il.AddInstruction(il.SetRegister(4, REG_ECX, il.Const(4, 0x7ffafbbf)));
- il.AddInstruction(il.SetRegister(4, REG_EDX, il.Const(4, 0xbfebfbff)));
- len = instr.length;
- return true;
-
- case JMP:
- if (instr.operands[0].operand == IMM)
- il.AddInstruction(DirectJump(this, il, instr.operands[0].immediate, addrSize));
- else
- il.AddInstruction(il.Jump(ReadILOperand(il, instr, 0, addrSize, true)));
- return false;
-
- case JO:
- ConditionalJump(this, il, il.FlagCondition(LLFC_O), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JNO:
- ConditionalJump(this, il, il.FlagCondition(LLFC_NO), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JB:
- ConditionalJump(this, il, il.FlagCondition(LLFC_ULT), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JAE:
- ConditionalJump(this, il, il.FlagCondition(LLFC_UGE), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JE:
- ConditionalJump(this, il, il.FlagCondition(LLFC_E), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JNE:
- ConditionalJump(this, il, il.FlagCondition(LLFC_NE), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JBE:
- ConditionalJump(this, il, il.FlagCondition(LLFC_ULE), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JA:
- ConditionalJump(this, il, il.FlagCondition(LLFC_UGT), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JS:
- ConditionalJump(this, il, il.FlagCondition(LLFC_NEG), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JNS:
- ConditionalJump(this, il, il.FlagCondition(LLFC_POS), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JPE:
- ConditionalJump(this, il, il.Not(0, il.Flag(IL_FLAG_P)), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JPO:
- ConditionalJump(this, il, il.Flag(IL_FLAG_P), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JL:
- ConditionalJump(this, il, il.FlagCondition(LLFC_SLT), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JGE:
- ConditionalJump(this, il, il.FlagCondition(LLFC_SGE), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JLE:
- ConditionalJump(this, il, il.FlagCondition(LLFC_SLE), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JG:
- ConditionalJump(this, il, il.FlagCondition(LLFC_SGT), addrSize, instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JCXZ:
- ConditionalJump(this, il, il.CompareEqual(2, il.Register(2, REG_CX), il.Const(2, 0)), addrSize,
- instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JECXZ:
- ConditionalJump(this, il, il.CompareEqual(4, il.Register(4, REG_ECX), il.Const(4, 0)), addrSize,
- instr.operands[0].immediate, addr + instr.length);
- return false;
-
- case JRCXZ:
- ConditionalJump(this, il, il.CompareEqual(8, il.Register(8, REG_RCX), il.Const(8, 0)), addrSize,
- instr.operands[0].immediate, addr + instr.length);
- return false;
-
- default:
- return m_arch->GetInstructionLowLevelIL(data, addr, len, il);
- }
- }
-
- virtual size_t GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType,
- uint32_t flag, BNRegisterOrConstant* operands, size_t operandCount, LowLevelILFunction& il) override
- {
- return m_arch->GetFlagWriteLowLevelIL(op,size, flagWriteType, flag, operands, operandCount, il);
- }
-
- virtual string GetRegisterName(uint32_t reg) override
- {
- return m_arch->GetRegisterName(reg);
- }
-
- virtual string GetFlagName(uint32_t flag) override
- {
- return m_arch->GetFlagName(flag);
- }
-
- virtual vector<uint32_t> GetAllFlags() override
- {
- return m_arch->GetAllFlags();
- }
-
- virtual string GetFlagWriteTypeName(uint32_t flags) override
- {
- return m_arch->GetFlagWriteTypeName(flags);
- }
-
- virtual vector<uint32_t> GetAllFlagWriteTypes() override
- {
- return m_arch->GetAllFlagWriteTypes();
- }
-
- virtual BNFlagRole GetFlagRole(uint32_t flag) override
- {
- return m_arch->GetFlagRole(flag);
- }
-
- virtual vector<uint32_t> GetFlagsRequiredForFlagCondition(BNLowLevelILFlagCondition cond) override
- {
- return m_arch->GetFlagsRequiredForFlagCondition(cond);
- }
-
- virtual vector<uint32_t> GetFlagsWrittenByFlagWriteType(uint32_t writeType) override
- {
- return m_arch->GetFlagsWrittenByFlagWriteType(writeType);
- }
-
- virtual bool IsNeverBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
- {
- return m_arch->IsNeverBranchPatchAvailable(data, addr, len);
- }
-
- virtual bool IsAlwaysBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
- {
- return m_arch->IsAlwaysBranchPatchAvailable(data, addr, len);
- }
-
- virtual bool IsInvertBranchPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
- {
- return m_arch->IsInvertBranchPatchAvailable(data, addr, len);
- }
-
- virtual bool IsSkipAndReturnZeroPatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
- {
- return m_arch->IsSkipAndReturnZeroPatchAvailable(data, addr, len);
- }
-
- virtual bool IsSkipAndReturnValuePatchAvailable(const uint8_t* data, uint64_t addr, size_t len) override
- {
- return m_arch->IsSkipAndReturnValuePatchAvailable(data, addr, len);
- }
-
- virtual bool ConvertToNop(uint8_t* data, uint64_t addr, size_t len) override
- {
- return m_arch->ConvertToNop(data, addr, len);
- }
-
- virtual bool AlwaysBranch(uint8_t* data, uint64_t addr, size_t len) override
- {
- return m_arch->AlwaysBranch(data, addr, len);
- }
-
- virtual bool InvertBranch(uint8_t* data, uint64_t addr, size_t len) override
- {
- return m_arch->InvertBranch(data, addr, len);
- }
-
- virtual bool SkipAndReturnValue(uint8_t* data, uint64_t addr, size_t len, uint64_t value) override
- {
- return m_arch->SkipAndReturnValue(data, addr, len, value);
- }
-
- virtual vector<uint32_t> GetFullWidthRegisters() override
- {
- return m_arch->GetFullWidthRegisters();
- }
-
- virtual vector<uint32_t> GetGlobalRegisters() override
- {
- return m_arch->GetGlobalRegisters();
- }
-
- virtual vector<uint32_t> GetAllRegisters() override
- {
- return m_arch->GetAllRegisters();
- }
-
- virtual BNRegisterInfo GetRegisterInfo(uint32_t reg) override
- {
- return m_arch->GetRegisterInfo(reg);
- }
-
- virtual uint32_t GetStackPointerRegister() override
- {
- return m_arch->GetStackPointerRegister();
- }
-
- virtual bool Assemble(const string& code, uint64_t addr, DataBuffer& result, string& errors) override
- {
- return m_arch->Assemble(code, addr, result, errors);
+ return ArchitectureHook::GetInstructionLowLevelIL(data, addr, len, il);
}
};
@@ -585,21 +50,13 @@ extern "C"
BINARYNINJAPLUGIN void CorePluginDependencies()
{
// Make sure we load after the original x86 plugin loads
- SetCurrentPluginLoadOrder(LatePluginLoadOrder);
+ AddRequiredPluginDependency("arch_x86");
}
BINARYNINJAPLUGIN bool CorePluginInit()
{
- Architecture* x86ext = new x86ArchitectureExtension();
+ Architecture* x86ext = new x86ArchitectureExtension(Architecture::GetByName("x86"));
Architecture::Register(x86ext);
-
- // Register the architectures with the binary format parsers so that they know when to use
- // these architectures for disassembling an executable file
- BinaryViewType::RegisterArchitecture("ELF", 3, LittleEndian, x86ext);
- BinaryViewType::RegisterArchitecture("PE", 0x14c, LittleEndian, x86ext);
- BinaryViewType::RegisterArchitecture("Mach-O", 0x00000007, LittleEndian, x86ext);
- x86ext->SetBinaryViewTypeConstant("ELF", "R_COPY", 5);
- x86ext->SetBinaryViewTypeConstant("ELF", "R_JUMP_SLOT", 7);
return true;
}
}