summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2017-12-26 17:14:16 -0500
committerRusty Wagner <rusty@vector35.com>2017-12-26 17:14:16 -0500
commit9fc4766a507d5299cd4de78170c5798b02bb9698 (patch)
treea4589f36a46e662cc16613db88f1c83c69512181 /examples
parent06b97009b2a09dc7816f6ace2d6a4bff66cb3f26 (diff)
parent26edabfdd7211012c7c8a03186d3025eea9aa345 (diff)
Merge branch 'dev' into fpu
Diffstat (limited to 'examples')
-rw-r--r--examples/cmdline_disasm/Makefile51
-rw-r--r--examples/cmdline_disasm/src/disasm.cpp152
m---------examples/x86_extension/src/asmx860
-rw-r--r--examples/x86_extension/src/x86_extension.cpp107
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();