diff options
| author | Rusty Wagner <rusty@vector35.com> | 2017-12-26 17:14:16 -0500 |
|---|---|---|
| committer | Rusty Wagner <rusty@vector35.com> | 2017-12-26 17:14:16 -0500 |
| commit | 9fc4766a507d5299cd4de78170c5798b02bb9698 (patch) | |
| tree | a4589f36a46e662cc16613db88f1c83c69512181 /examples | |
| parent | 06b97009b2a09dc7816f6ace2d6a4bff66cb3f26 (diff) | |
| parent | 26edabfdd7211012c7c8a03186d3025eea9aa345 (diff) | |
Merge branch 'dev' into fpu
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/cmdline_disasm/Makefile | 51 | ||||
| -rw-r--r-- | examples/cmdline_disasm/src/disasm.cpp | 152 | ||||
| m--------- | examples/x86_extension/src/asmx86 | 0 | ||||
| -rw-r--r-- | examples/x86_extension/src/x86_extension.cpp | 107 |
4 files changed, 308 insertions, 2 deletions
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 <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> + +#include <sys/types.h> +#include <sys/stat.h> + +#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 <arch+mode> <byte0> <byte1> ...\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<input_n && i<sizeof(input); ++i) { + if(parse_uint8_hex(av[i+2], input+i)) { + printf("ERROR: can't parse byte: %s\n", av[i+2]); + goto cleanup; + } + } + + printf("parsed bytes: "); + for(i=0; i<input_n; ++i) + printf("%02X ", input[i]); + printf("\n"); + + /* actually disassemble now */ + nBytesDisasm = input_n; + BNGetInstructionText(arch, (const uint8_t *)input, 0, &nBytesDisasm, + &ttResult, &ttCount); + + //printf("%zu text tokens\n", ttCount); + + for(i=0; i<ttCount; ++i) + printf("%s", ttResult[i].text); + printf("\n"); + + /* done! */ + cleanup: + if(ttResult) + BNFreeInstructionText(ttResult, ttCount); + return rc; +} + +/****************************************************************************** + PARSING +******************************************************************************/ + +int parse_nib(const char *str, uint8_t *val) +{ + int rc = -1; + char c = *str; + + if(c>='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; +} + diff --git a/examples/x86_extension/src/asmx86 b/examples/x86_extension/src/asmx86 -Subproject f78096d79ccfcc5169b6e2ae0fa89e3eed5b85c +Subproject 9a1bf01f4c456779544a445db45b1496c50ff37 diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp index 9efcc119..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 @@ -327,6 +328,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); @@ -345,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 @@ -356,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, @@ -485,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(); |
