From 3d45c0be55585e0d868e1a09c86fdaf925d490a3 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 7 Nov 2017 16:47:28 -0500 Subject: Update to latest asmx86 --- examples/x86_extension/src/asmx86 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/x86_extension/src/asmx86 b/examples/x86_extension/src/asmx86 index f78096d7..9a1bf01f 160000 --- a/examples/x86_extension/src/asmx86 +++ b/examples/x86_extension/src/asmx86 @@ -1 +1 @@ -Subproject commit f78096d79ccfcc5169b6e2ae0fa89e3eed5b85cc +Subproject commit 9a1bf01f4c456779544a445db45b1496c50ff372 -- cgit v1.3.1 From 0cff612e91e59a343fad898daa6fa51ab525a789 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Mon, 13 Nov 2017 17:09:13 -0500 Subject: Add GetInstructionAlignment Callback to Architecture. --- architecture.cpp | 20 ++++++++++++++++++++ binaryninjaapi.h | 3 +++ binaryninjacore.h | 2 ++ examples/x86_extension/src/x86_extension.cpp | 5 +++++ python/architecture.py | 13 ++++++++++++- python/examples/nes.py | 1 + 6 files changed, 43 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/architecture.cpp b/architecture.cpp index eb588394..17d02909 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -111,6 +111,13 @@ size_t Architecture::GetDefaultIntegerSizeCallback(void* ctxt) } +size_t Architecture::GetInstructionAlignmentCallback(void* ctxt) +{ + Architecture* arch = (Architecture*)ctxt; + return arch->GetInstructionAlignment(); +} + + size_t Architecture::GetMaxInstructionLengthCallback(void* ctxt) { Architecture* arch = (Architecture*)ctxt; @@ -443,6 +450,7 @@ void Architecture::Register(Architecture* arch) callbacks.getEndianness = GetEndiannessCallback; callbacks.getAddressSize = GetAddressSizeCallback; callbacks.getDefaultIntegerSize = GetDefaultIntegerSizeCallback; + callbacks.getInstructionAlignment = GetInstructionAlignmentCallback; callbacks.getMaxInstructionLength = GetMaxInstructionLengthCallback; callbacks.getOpcodeDisplayLength = GetOpcodeDisplayLengthCallback; callbacks.getAssociatedArchitectureByAddress = GetAssociatedArchitectureByAddressCallback; @@ -523,6 +531,12 @@ size_t Architecture::GetDefaultIntegerSize() const } +size_t Architecture::GetInstructionAlignment() const +{ + return 1; +} + + size_t Architecture::GetMaxInstructionLength() const { return BN_DEFAULT_NSTRUCTION_LENGTH; @@ -905,6 +919,12 @@ size_t CoreArchitecture::GetDefaultIntegerSize() const } +size_t CoreArchitecture::GetInstructionAlignment() const +{ + return BNGetArchitectureInstructionAlignment(m_object); +} + + size_t CoreArchitecture::GetMaxInstructionLength() const { return BNGetArchitectureMaxInstructionLength(m_object); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 5f3aace7..4f62ef5f 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1585,6 +1585,7 @@ namespace BinaryNinja static BNEndianness GetEndiannessCallback(void* ctxt); static size_t GetAddressSizeCallback(void* ctxt); static size_t GetDefaultIntegerSizeCallback(void* ctxt); + static size_t GetInstructionAlignmentCallback(void* ctxt); static size_t GetMaxInstructionLengthCallback(void* ctxt); static size_t GetOpcodeDisplayLengthCallback(void* ctxt); static BNArchitecture* GetAssociatedArchitectureByAddressCallback(void* ctxt, uint64_t* addr); @@ -1640,6 +1641,7 @@ namespace BinaryNinja virtual size_t GetAddressSize() const = 0; virtual size_t GetDefaultIntegerSize() const; + virtual size_t GetInstructionAlignment() const; virtual size_t GetMaxInstructionLength() const; virtual size_t GetOpcodeDisplayLength() const; @@ -1780,6 +1782,7 @@ namespace BinaryNinja 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 GetAssociatedArchitectureByAddress(uint64_t& addr) override; diff --git a/binaryninjacore.h b/binaryninjacore.h index 45e6310c..cb99958c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1003,6 +1003,7 @@ extern "C" BNEndianness (*getEndianness)(void* ctxt); size_t (*getAddressSize)(void* ctxt); size_t (*getDefaultIntegerSize)(void* ctxt); + size_t (*getInstructionAlignment)(void* ctxt); size_t (*getMaxInstructionLength)(void* ctxt); size_t (*getOpcodeDisplayLength)(void* ctxt); BNArchitecture* (*getAssociatedArchitectureByAddress)(void* ctxt, uint64_t* addr); @@ -1946,6 +1947,7 @@ extern "C" BINARYNINJACOREAPI BNEndianness BNGetArchitectureEndianness(BNArchitecture* arch); BINARYNINJACOREAPI size_t BNGetArchitectureAddressSize(BNArchitecture* arch); BINARYNINJACOREAPI size_t BNGetArchitectureDefaultIntegerSize(BNArchitecture* arch); + BINARYNINJACOREAPI size_t BNGetArchitectureInstructionAlignment(BNArchitecture* arch); BINARYNINJACOREAPI size_t BNGetArchitectureMaxInstructionLength(BNArchitecture* arch); BINARYNINJACOREAPI size_t BNGetArchitectureOpcodeDisplayLength(BNArchitecture* arch); BINARYNINJACOREAPI BNArchitecture* BNGetAssociatedArchitectureByAddress(BNArchitecture* arch, uint64_t* addr); diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp index 9efcc119..076551ab 100644 --- a/examples/x86_extension/src/x86_extension.cpp +++ b/examples/x86_extension/src/x86_extension.cpp @@ -327,6 +327,11 @@ public: 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); diff --git a/python/architecture.py b/python/architecture.py index 72403fec..41a130bf 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -111,6 +111,7 @@ class Architecture(object): endianness = Endianness.LittleEndian address_size = 8 default_int_size = 4 + instr_alignment = 1 max_instr_length = 16 opcode_display_length = 8 regs = {} @@ -132,6 +133,7 @@ class Architecture(object): self.__dict__["endianness"] = Endianness(core.BNGetArchitectureEndianness(self.handle)) self.__dict__["address_size"] = core.BNGetArchitectureAddressSize(self.handle) self.__dict__["default_int_size"] = core.BNGetArchitectureDefaultIntegerSize(self.handle) + self.__dict__["instr_alignment"] = core.BNGetArchitectureInstructionAlignment(self.handle) self.__dict__["max_instr_length"] = core.BNGetArchitectureMaxInstructionLength(self.handle) self.__dict__["opcode_display_length"] = core.BNGetArchitectureOpcodeDisplayLength(self.handle) self.__dict__["stack_pointer"] = core.BNGetArchitectureRegisterName(self.handle, @@ -228,6 +230,7 @@ class Architecture(object): self._cb.getEndianness = self._cb.getEndianness.__class__(self._get_endianness) self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size) self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size) + self._cb.getInstructionAlignment = self._cb.getInstructionAlignment.__class__(self._get_instruction_alignment) self._cb.getMaxInstructionLength = self._cb.getMaxInstructionLength.__class__(self._get_max_instruction_length) self._cb.getOpcodeDisplayLength = self._cb.getOpcodeDisplayLength.__class__(self._get_opcode_display_length) self._cb.getAssociatedArchitectureByAddress = \ @@ -385,7 +388,8 @@ class Architecture(object): def __setattr__(self, name, value): if ((name == "name") or (name == "endianness") or (name == "address_size") or - (name == "default_int_size") or (name == "regs") or (name == "get_max_instruction_length")): + (name == "default_int_size") or (name == "regs") or (name == "get_max_instruction_length") or + (name == "get_instruction_alignment")): raise AttributeError("attribute '%s' is read only" % name) else: try: @@ -420,6 +424,13 @@ class Architecture(object): log.log_error(traceback.format_exc()) return 4 + def __get_instruction_alignment(self, ctxt): + try: + return self.__class__.instr_alignment + except: + log.log_error(traceback.format_exc()) + return 1 + def _get_max_instruction_length(self, ctxt): try: return self.__class__.max_instr_length diff --git a/python/examples/nes.py b/python/examples/nes.py index e55a90b7..39544c9f 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -367,6 +367,7 @@ class M6502(Architecture): name = "6502" address_size = 2 default_int_size = 1 + instr_alignment = 1 max_instr_length = 3 regs = { "a": RegisterInfo("a", 1), -- cgit v1.3.1 From db7fbfe8029ecf9126a2cb0e7b0d2c372fe47daa Mon Sep 17 00:00:00 2001 From: Andrew Lamoureux Date: Tue, 21 Nov 2017 16:33:51 -0500 Subject: example: use arch plugins for cmdline disassembler --- examples/cmdline_disasm/Makefile | 51 +++++++++++ examples/cmdline_disasm/src/disasm.cpp | 152 +++++++++++++++++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 examples/cmdline_disasm/Makefile create mode 100644 examples/cmdline_disasm/src/disasm.cpp (limited to 'examples') diff --git a/examples/cmdline_disasm/Makefile b/examples/cmdline_disasm/Makefile new file mode 100644 index 00000000..12931876 --- /dev/null +++ b/examples/cmdline_disasm/Makefile @@ -0,0 +1,51 @@ +# 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 := $(HOME)/binaryninja/ + CC := gcc +else + BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS + CC := clang +endif + +SRCDIR := src +BUILDDIR := build +TARGETDIR := bin + +TARGETNAME := disasm +TARGET := $(TARGETDIR)/$(TARGETNAME) + +SRCEXT := cpp +SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) + +LIBS := -L $(BINJAPATH) -lbinaryninjacore +CPPFLAGS := -c -O2 -Wall -W -fPIC --std=c++11 -pipe + +all: $(TARGET) + +ifeq ($(UNAME_S),Linux) +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -Wl,-rpath=$(BINJAPATH) -ldl -o $@ +else +$(TARGET): $(OBJECTS) + @mkdir -p $(TARGETDIR) + $(CC) $^ $(BINJA_API_A) $(LIBS) -o $@ + install_name_tool -change @rpath/libbinaryninjacore.dylib $(BINJAPATH)/libbinaryninjacore.dylib $@ +endif + +$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) + @mkdir -p $(BUILDDIR) + $(CC) $(CPPFLAGS) $(INC) -c -o $@ $< + +clean: + $(RM) -r $(BUILDDIR) $(TARGETDIR) + +.PHONY: clean diff --git a/examples/cmdline_disasm/src/disasm.cpp b/examples/cmdline_disasm/src/disasm.cpp new file mode 100644 index 00000000..c763fc11 --- /dev/null +++ b/examples/cmdline_disasm/src/disasm.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include + +#include +#include + +#include "binaryninjacore.h" +#include "binaryninjaapi.h" + +using namespace BinaryNinja; + +/* forward declarations */ +int parse_nib(const char *str, uint8_t *val); +int parse_uint8_hex(const char *str, uint8_t *result); + +/****************************************************************************** + MAIN +******************************************************************************/ + +void usage(int ac, char **av) +{ + (void)ac; + printf(" syntax: %s ...\n", av[0]); + printf("examples:\n"); + printf(" %s x86 83 83 ec 0c\n", av[0]); + printf(" %s x86_64 48 89 e5\n", av[0]); + printf(" %s armv7 14 d0 4d e2\n", av[0]); + printf(" %s armv7eb d0 14 e2 4d\n", av[0]); + printf(" %s thumb2 4f f0 00 0c\n", av[0]); + printf(" %s thumb2eb f0 4f 0c 00\n", av[0]); + printf(" %s ppc 93 e1 ff fc\n", av[0]); + printf(" %s aarch64 ff 43 00 d1\n", av[0]); + printf(" %s mips32 27 bd ff f0\n", av[0]); + printf(" %s mipsel32 f0 ff bd 27\n", av[0]); +} + +int main(int ac, char **av) +{ + int rc = -1; + unsigned int i; + + char *archmode; + BNArchitecture *arch; + + size_t nBytesDisasm; + + uint8_t input[64]; + unsigned int input_n; + + BNInstructionTextToken *ttResult = NULL; + size_t ttCount; + + char *path_bundled_plugins; + + /* plugin path */ + path_bundled_plugins = BNGetBundledPluginDirectory(); + printf("using bundled plugin path: %s\n", path_bundled_plugins); + BNSetBundledPluginDirectory(path_bundled_plugins); + BNInitCorePlugins(); + + /* parse architecture argument */ + if(ac < 2) + { usage(ac, av); goto cleanup; } + archmode = av[1]; + + printf("looking up architecture \"%s\"\n", archmode); + arch = BNGetArchitectureByName(archmode); + if(!arch) { + printf("ERROR: BNGetArchitectureByName() (is \"%s\" valid?)\n", archmode); + usage(ac, av); + goto cleanup; + } + + /* parse bytes argument */ + input_n = ac - 2; + for(i=0; i='0' && c<='9') { + *val = c-'0'; + rc = 0; + } + else if(c>='a' && c<='f') { + *val = 10 + (c-'a'); + rc = 0; + } + else if(c>='A' && c<='F') { + *val = 10 + (c-'A'); + rc = 0; + } + else { + printf("ERROR: %s('%c', ...)\n", __func__, c); + } + + return rc; +} + +int parse_uint8_hex(const char *str, uint8_t *result) +{ + int rc=-1; + uint8_t v1, v2; + + if(parse_nib(str, &v1)) + goto cleanup; + if(parse_nib(str+1, &v2)) + goto cleanup; + + *result = (v1 << 4) | v2; + rc = 0; + + cleanup: + return rc; +} + -- cgit v1.3.1 From 859b86c233a8783f134c498b9c32ea1826ed4503 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Tue, 12 Dec 2017 11:02:19 -0500 Subject: Add fixes for x86_extension wrapper --- examples/x86_extension/src/x86_extension.cpp | 102 ++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp index 076551ab..a2ba4c9c 100644 --- a/examples/x86_extension/src/x86_extension.cpp +++ b/examples/x86_extension/src/x86_extension.cpp @@ -306,6 +306,7 @@ static void Repeat(size_t addrSize, } } + // This is a wrapper for the x86 architecture. Its useful for extending and improving // the existing core x86 architecture. class x86ArchitectureExtension: public Architecture @@ -350,8 +351,11 @@ public: il.AddInstruction(il.Undefined()); return false; } - if (instr.operation == CPUID) + + 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 @@ -361,8 +365,96 @@ public: 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); } - return m_arch->GetInstructionLowLevelIL(data, addr, len, il); } virtual size_t GetFlagWriteLowLevelIL(BNLowLevelILOperation op, size_t size, uint32_t flagWriteType, @@ -490,6 +582,12 @@ public: extern "C" { + BINARYNINJAPLUGIN void CorePluginDependencies() + { + // Make sure we load after the original x86 plugin loads + SetCurrentPluginLoadOrder(LatePluginLoadOrder); + } + BINARYNINJAPLUGIN bool CorePluginInit() { Architecture* x86ext = new x86ArchitectureExtension(); -- cgit v1.3.1