summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2017-08-19 22:38:10 -0400
committerPeter LaFosse <peter@vector35.com>2017-08-19 22:38:10 -0400
commitdabc2ee689cb5dba068fd5461c66973838d05640 (patch)
tree92ffbf57454ee82f1a3355d37c7be1d7eb62f971
parente40b46fdf8b76acb5ca2d0a062b0b8ac2ca99a16 (diff)
Add C++ x86 architecture wrapper for extending architectures
-rw-r--r--.gitmodules3
-rw-r--r--examples/x86_extension/Makefile59
m---------examples/x86_extension/src/asmx860
-rw-r--r--examples/x86_extension/src/x86_extension.cpp205
4 files changed, 267 insertions, 0 deletions
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..1962d2b4
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "examples/x86_extension/src/asmx86"]
+ path = examples/x86_extension/src/asmx86
+ url = https://github.com/Vector35/asmx86.git
diff --git a/examples/x86_extension/Makefile b/examples/x86_extension/Makefile
new file mode 100644
index 00000000..3fa1739b
--- /dev/null
+++ b/examples/x86_extension/Makefile
@@ -0,0 +1,59 @@
+# Path to prebuilt libbinaryninjaapi.a
+BINJA_API_A := ../../bin/libbinaryninjaapi.a
+
+# Path to binaryninjaapi.h and json
+INC := -I../../
+
+UNAME_S := $(shell uname -s)
+ifeq ($(UNAME_S),Linux)
+ # Path to binaryninja install
+ BINJAPATH := $(shell cat ~/.binaryninja/lastrun)
+ PLUGIN_DIR := ~/.binaryninja/plugins/
+ CC := g++
+else
+ BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS
+ PLUGIN_DIR := ~/Library/Application\ Support/Binary\ Ninja/plugins/
+ CC := clang++
+endif
+
+SRCDIR := src
+BUILDDIR := build
+TARGETDIR := bin
+
+TARGETNAME := x86_extension
+TARGET := $(TARGETDIR)/$(TARGETNAME)
+
+SRCEXT := cpp
+SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
+OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) src/asmx86/libasmx86.a
+
+LIBS := -L$(BINJAPATH) -lbinaryninjacore
+CFLAGS := -c -std=gnu++11 -O2 -Wall -W -fPIC -pipe
+
+all: $(TARGET)
+
+ifeq ($(UNAME_S),Linux)
+$(TARGET): $(OBJECTS)
+ @mkdir -p $(TARGETDIR)
+ $(CC) $^ $(BINJA_API_A) $(LIBS) -shared -Wl,-rpath=$(BINJAPATH) -ldl -o bin/lib$(TARGETNAME).so
+else
+$(TARGET): $(OBJECTS)
+ @mkdir -p $(TARGETDIR)
+ $(CC) $^ $(BINJA_API_A) $(LIBS) -single_module -dynamiclib -o bin/lib$(TARGETNAME).dylib
+ install_name_tool -add_rpath $(BINJAPATH)/libbinaryninjacore.dylib bin/lib$(TARGETNAME).dylib
+endif
+
+$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
+ @mkdir -p $(BUILDDIR)
+ $(CC) $(CFLAGS) $(INC) -c -o $@ $<
+
+src/asmx86/libasmx86.a:
+ $(MAKE) -C src/asmx86
+
+install:
+ cp bin/lib$(TARGETNAME).dylib $(PLUGIN_DIR)
+
+clean:
+ $(RM) -r $(BUILDDIR) $(TARGETDIR)
+
+.PHONY: clean
diff --git a/examples/x86_extension/src/asmx86 b/examples/x86_extension/src/asmx86
new file mode 160000
+Subproject d6254c69ea1128064218b7193e0c4f0cd13d089
diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp
new file mode 100644
index 00000000..2e4f441f
--- /dev/null
+++ b/examples/x86_extension/src/x86_extension.cpp
@@ -0,0 +1,205 @@
+#define _CRT_SECURE_NO_WARNINGS
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include "binaryninjaapi.h"
+#include "asmx86/asmx86.h"
+
+using namespace BinaryNinja;
+using namespace std;
+using namespace asmx86;
+
+// This is a wrapper for the x86 architecture. Its useful for extending and improving
+// the existing core x86 architecture.
+class x86ArchitectureExtension: public Architecture
+{
+ 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
+ {
+ return LittleEndian;
+ }
+
+ 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))
+ {
+ il.AddInstruction(il.Undefined());
+ return false;
+ }
+ if (instr.operation == 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;
+ }
+ 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);
+ }
+};
+
+
+extern "C"
+{
+ BINARYNINJAPLUGIN bool CorePluginInit()
+ {
+ Architecture* x86ext = new x86ArchitectureExtension();
+ 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;
+ }
+}