summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2017-08-31 21:41:25 -0400
committerRusty Wagner <rusty@vector35.com>2017-08-31 21:41:25 -0400
commit7cbb40a71ffb2583862191b7999e436807f9a0e8 (patch)
tree25846f8d0e811b16b28291aeaf6359bee51e28c4 /examples
parent980e2f090fb47f7f71a46b03e8c636819f3214ec (diff)
parent0b30396eb319e89e4f69d9cbac12fc3d4b453f53 (diff)
Merge branch 'dev'
Diffstat (limited to 'examples')
-rw-r--r--examples/llil_parser/CMakeLists.txt50
-rw-r--r--examples/llil_parser/Makefile51
-rw-r--r--examples/llil_parser/Makefile.win9
-rw-r--r--examples/llil_parser/src/llil_parser.cpp409
-rw-r--r--examples/mlil_parser/CMakeLists.txt50
-rw-r--r--examples/mlil_parser/Makefile51
-rw-r--r--examples/mlil_parser/Makefile.win9
-rw-r--r--examples/mlil_parser/src/mlil_parser.cpp356
-rw-r--r--examples/x86_extension/Makefile59
m---------examples/x86_extension/src/asmx860
-rw-r--r--examples/x86_extension/src/x86_extension.cpp502
11 files changed, 1546 insertions, 0 deletions
diff --git a/examples/llil_parser/CMakeLists.txt b/examples/llil_parser/CMakeLists.txt
new file mode 100644
index 00000000..6d782109
--- /dev/null
+++ b/examples/llil_parser/CMakeLists.txt
@@ -0,0 +1,50 @@
+# Mostly copied from https://github.com/Vector35/binaryninja-api/blob/dev/examples/breakpoint/CMakeLists.txt
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+project(LLIL_Parser)
+
+#-----------------------------------------------------------------------------
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..)
+#-----------------------------------------------------------------------------
+file( GLOB_RECURSE SRCS *.cpp *.h)
+#-----------------------------------------------------------------------------
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+#-----------------------------------------------------------------------------
+if(WIN32)
+ set(BINJA_DIR "C:\\Program Files\\Vector35\\BinaryNinja"
+ CACHE PATH "Binary Ninja installation directory")
+ set(BINJA_BIN_DIR "${BINJA_DIR}")
+ set(BINJA_PLUGINS_DIR "$ENV{APPDATA}/Binary Ninja/plugins"
+ CACHE PATH "Binary Ninja user plugins directory")
+elseif(APPLE)
+ set(BINJA_DIR "/Applications/Binary Ninja.app"
+ CACHE PATH "Binary Ninja installation directory")
+ set(BINJA_BIN_DIR "${BINJA_DIR}/Contents/MacOS")
+ set(BINJA_PLUGINS_DIR "$ENV{HOME}/Library/Application Support/Binary Ninja/plugins"
+ CACHE PATH "Binary Ninja user plugins directory")
+else()
+ set(BINJA_DIR "$ENV{HOME}/binaryninja"
+ CACHE PATH "Binary Ninja installation directory")
+ set(BINJA_BIN_DIR "${BINJA_DIR}")
+ set(BINJA_PLUGINS_DIR "$ENV{HOME}/.binaryninja/plugins"
+ CACHE PATH "Binary Ninja user plugins directory")
+endif()
+#-----------------------------------------------------------------------------
+add_executable (${PROJECT_NAME} ${SRCS} )
+#-----------------------------------------------------------------------------
+find_library(BINJA_API_LIBRARY binaryninjaapi
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../../bin ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Release ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Debug)
+find_library(BINJA_CORE_LIBRARY binaryninjacore
+ HINTS ${BINJA_BIN_DIR})
+#-----------------------------------------------------------------------------
+target_link_libraries(${PROJECT_NAME}
+ ${BINJA_API_LIBRARY}
+ ${BINJA_CORE_LIBRARY}
+ )
+#-----------------------------------------------------------------------------
+install (TARGETS ${PROJECT_NAME}
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION Lib
+ ARCHIVE DESTINATION Lib)
+
diff --git a/examples/llil_parser/Makefile b/examples/llil_parser/Makefile
new file mode 100644
index 00000000..13c01e62
--- /dev/null
+++ b/examples/llil_parser/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 := g++
+else
+ BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS
+ CC := clang++
+endif
+
+SRCDIR := src
+BUILDDIR := build
+TARGETDIR := bin
+
+TARGETNAME := llil_parser
+TARGET := $(TARGETDIR)/$(TARGETNAME)
+
+SRCEXT := cpp
+SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
+OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
+
+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) -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) $(CFLAGS) $(INC) -c -o $@ $<
+
+clean:
+ $(RM) -r $(BUILDDIR) $(TARGETDIR)
+
+.PHONY: clean
diff --git a/examples/llil_parser/Makefile.win b/examples/llil_parser/Makefile.win
new file mode 100644
index 00000000..fb714c0b
--- /dev/null
+++ b/examples/llil_parser/Makefile.win
@@ -0,0 +1,9 @@
+BINJA_API_INC_PATH = ..\..\
+BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib
+BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib"
+
+FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB)
+
+bininfo: ./src/llil_parser.cpp
+ if not exist bin mkdir bin
+ cl ./src/llil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo
diff --git a/examples/llil_parser/src/llil_parser.cpp b/examples/llil_parser/src/llil_parser.cpp
new file mode 100644
index 00000000..72ac71bd
--- /dev/null
+++ b/examples/llil_parser/src/llil_parser.cpp
@@ -0,0 +1,409 @@
+#include <stdio.h>
+#include <inttypes.h>
+#include "binaryninjacore.h"
+#include "binaryninjaapi.h"
+#include "lowlevelilinstruction.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+#ifndef __WIN32__
+#include <libgen.h>
+#include <dlfcn.h>
+static string GetPluginsDirectory()
+{
+ Dl_info info;
+ if (!dladdr((void *)BNGetBundledPluginDirectory, &info))
+ return NULL;
+
+ stringstream ss;
+ ss << dirname((char *)info.dli_fname) << "/plugins/";
+ return ss.str();
+}
+#else
+static string GetPluginsDirectory()
+{
+ return "C:\\Program Files\\Vector35\\Binary Ninja\\plugins\\";
+}
+#endif
+
+
+static void PrintIndent(size_t indent)
+{
+ for (size_t i = 0; i < indent; i++)
+ printf(" ");
+}
+
+
+static void PrintOperation(BNLowLevelILOperation operation)
+{
+#define ENUM_PRINTER(op) \
+ case op: \
+ printf(#op); \
+ break;
+
+ switch (operation)
+ {
+ ENUM_PRINTER(LLIL_NOP)
+ ENUM_PRINTER(LLIL_SET_REG)
+ ENUM_PRINTER(LLIL_SET_REG_SPLIT)
+ ENUM_PRINTER(LLIL_SET_FLAG)
+ ENUM_PRINTER(LLIL_LOAD)
+ ENUM_PRINTER(LLIL_STORE)
+ ENUM_PRINTER(LLIL_PUSH)
+ ENUM_PRINTER(LLIL_POP)
+ ENUM_PRINTER(LLIL_REG)
+ ENUM_PRINTER(LLIL_CONST)
+ ENUM_PRINTER(LLIL_CONST_PTR)
+ ENUM_PRINTER(LLIL_FLAG)
+ ENUM_PRINTER(LLIL_FLAG_BIT)
+ ENUM_PRINTER(LLIL_ADD)
+ ENUM_PRINTER(LLIL_ADC)
+ ENUM_PRINTER(LLIL_SUB)
+ ENUM_PRINTER(LLIL_SBB)
+ ENUM_PRINTER(LLIL_AND)
+ ENUM_PRINTER(LLIL_OR)
+ ENUM_PRINTER(LLIL_XOR)
+ ENUM_PRINTER(LLIL_LSL)
+ ENUM_PRINTER(LLIL_LSR)
+ ENUM_PRINTER(LLIL_ASR)
+ ENUM_PRINTER(LLIL_ROL)
+ ENUM_PRINTER(LLIL_RLC)
+ ENUM_PRINTER(LLIL_ROR)
+ ENUM_PRINTER(LLIL_RRC)
+ ENUM_PRINTER(LLIL_MUL)
+ ENUM_PRINTER(LLIL_MULU_DP)
+ ENUM_PRINTER(LLIL_MULS_DP)
+ ENUM_PRINTER(LLIL_DIVU)
+ ENUM_PRINTER(LLIL_DIVU_DP)
+ ENUM_PRINTER(LLIL_DIVS)
+ ENUM_PRINTER(LLIL_DIVS_DP)
+ ENUM_PRINTER(LLIL_MODU)
+ ENUM_PRINTER(LLIL_MODU_DP)
+ ENUM_PRINTER(LLIL_MODS)
+ ENUM_PRINTER(LLIL_MODS_DP)
+ ENUM_PRINTER(LLIL_NEG)
+ ENUM_PRINTER(LLIL_NOT)
+ ENUM_PRINTER(LLIL_SX)
+ ENUM_PRINTER(LLIL_ZX)
+ ENUM_PRINTER(LLIL_LOW_PART)
+ ENUM_PRINTER(LLIL_JUMP)
+ ENUM_PRINTER(LLIL_JUMP_TO)
+ ENUM_PRINTER(LLIL_CALL)
+ ENUM_PRINTER(LLIL_RET)
+ ENUM_PRINTER(LLIL_NORET)
+ ENUM_PRINTER(LLIL_IF)
+ ENUM_PRINTER(LLIL_GOTO)
+ ENUM_PRINTER(LLIL_FLAG_COND)
+ ENUM_PRINTER(LLIL_CMP_E)
+ ENUM_PRINTER(LLIL_CMP_NE)
+ ENUM_PRINTER(LLIL_CMP_SLT)
+ ENUM_PRINTER(LLIL_CMP_ULT)
+ ENUM_PRINTER(LLIL_CMP_SLE)
+ ENUM_PRINTER(LLIL_CMP_ULE)
+ ENUM_PRINTER(LLIL_CMP_SGE)
+ ENUM_PRINTER(LLIL_CMP_UGE)
+ ENUM_PRINTER(LLIL_CMP_SGT)
+ ENUM_PRINTER(LLIL_CMP_UGT)
+ ENUM_PRINTER(LLIL_TEST_BIT)
+ ENUM_PRINTER(LLIL_BOOL_TO_INT)
+ ENUM_PRINTER(LLIL_ADD_OVERFLOW)
+ ENUM_PRINTER(LLIL_SYSCALL)
+ ENUM_PRINTER(LLIL_BP)
+ ENUM_PRINTER(LLIL_TRAP)
+ ENUM_PRINTER(LLIL_UNDEF)
+ ENUM_PRINTER(LLIL_UNIMPL)
+ ENUM_PRINTER(LLIL_UNIMPL_MEM)
+ ENUM_PRINTER(LLIL_SET_REG_SSA)
+ ENUM_PRINTER(LLIL_SET_REG_SSA_PARTIAL)
+ ENUM_PRINTER(LLIL_SET_REG_SPLIT_SSA)
+ ENUM_PRINTER(LLIL_REG_SPLIT_DEST_SSA)
+ ENUM_PRINTER(LLIL_REG_SSA)
+ ENUM_PRINTER(LLIL_REG_SSA_PARTIAL)
+ ENUM_PRINTER(LLIL_SET_FLAG_SSA)
+ ENUM_PRINTER(LLIL_FLAG_SSA)
+ ENUM_PRINTER(LLIL_FLAG_BIT_SSA)
+ ENUM_PRINTER(LLIL_CALL_SSA)
+ ENUM_PRINTER(LLIL_SYSCALL_SSA)
+ ENUM_PRINTER(LLIL_CALL_PARAM_SSA)
+ ENUM_PRINTER(LLIL_CALL_STACK_SSA)
+ ENUM_PRINTER(LLIL_CALL_OUTPUT_SSA)
+ ENUM_PRINTER(LLIL_LOAD_SSA)
+ ENUM_PRINTER(LLIL_STORE_SSA)
+ ENUM_PRINTER(LLIL_REG_PHI)
+ ENUM_PRINTER(LLIL_FLAG_PHI)
+ ENUM_PRINTER(LLIL_MEM_PHI)
+ default:
+ printf("<invalid operation %" PRId32 ">", operation);
+ break;
+ }
+}
+
+
+static void PrintFlagCondition(BNLowLevelILFlagCondition cond)
+{
+ switch (cond)
+ {
+ ENUM_PRINTER(LLFC_E)
+ ENUM_PRINTER(LLFC_NE)
+ ENUM_PRINTER(LLFC_SLT)
+ ENUM_PRINTER(LLFC_ULT)
+ ENUM_PRINTER(LLFC_SLE)
+ ENUM_PRINTER(LLFC_ULE)
+ ENUM_PRINTER(LLFC_SGE)
+ ENUM_PRINTER(LLFC_UGE)
+ ENUM_PRINTER(LLFC_SGT)
+ ENUM_PRINTER(LLFC_UGT)
+ ENUM_PRINTER(LLFC_NEG)
+ ENUM_PRINTER(LLFC_POS)
+ ENUM_PRINTER(LLFC_O)
+ ENUM_PRINTER(LLFC_NO)
+ default:
+ printf("<invalid condition>");
+ break;
+ }
+}
+
+
+static void PrintRegister(LowLevelILFunction* func, uint32_t reg)
+{
+ if (LLIL_REG_IS_TEMP(reg))
+ printf("temp%d", LLIL_GET_TEMP_REG_INDEX(reg));
+ else
+ {
+ string name = func->GetArchitecture()->GetRegisterName(reg);
+ if (name.size() == 0)
+ printf("<no name>");
+ else
+ printf("%s", name.c_str());
+ }
+}
+
+
+static void PrintFlag(LowLevelILFunction* func, uint32_t flag)
+{
+ if (LLIL_REG_IS_TEMP(flag))
+ printf("cond:%d", LLIL_GET_TEMP_REG_INDEX(flag));
+ else
+ {
+ string name = func->GetArchitecture()->GetFlagName(flag);
+ if (name.size() == 0)
+ printf("<no name>");
+ else
+ printf("%s", name.c_str());
+ }
+}
+
+
+static void PrintILExpr(const LowLevelILInstruction& instr, size_t indent)
+{
+ PrintIndent(indent);
+ PrintOperation(instr.operation);
+ printf("\n");
+
+ indent++;
+
+ for (auto& operand : instr.GetOperands())
+ {
+ switch (operand.GetType())
+ {
+ case IntegerLowLevelOperand:
+ PrintIndent(indent);
+ printf("int 0x%" PRIx64 "\n", operand.GetInteger());
+ break;
+
+ case IndexLowLevelOperand:
+ PrintIndent(indent);
+ printf("index %" PRIdPTR "\n", operand.GetIndex());
+ break;
+
+ case ExprLowLevelOperand:
+ PrintILExpr(operand.GetExpr(), indent);
+ break;
+
+ case RegisterLowLevelOperand:
+ PrintIndent(indent);
+ printf("reg ");
+ PrintRegister(instr.function, operand.GetRegister());
+ printf("\n");
+ break;
+
+ case FlagLowLevelOperand:
+ PrintIndent(indent);
+ printf("flag ");
+ PrintFlag(instr.function, operand.GetFlag());
+ printf("\n");
+ break;
+
+ case FlagConditionLowLevelOperand:
+ PrintIndent(indent);
+ printf("flag condition ");
+ PrintFlagCondition(operand.GetFlagCondition());
+ printf("\n");
+ break;
+
+ case SSARegisterLowLevelOperand:
+ PrintIndent(indent);
+ printf("ssa reg ");
+ PrintRegister(instr.function, operand.GetSSARegister().reg);
+ printf("#%" PRIdPTR "\n", operand.GetSSARegister().version);
+ break;
+
+ case SSAFlagLowLevelOperand:
+ PrintIndent(indent);
+ printf("ssa flag ");
+ PrintFlag(instr.function, operand.GetSSAFlag().flag);
+ printf("#%" PRIdPTR "\n", operand.GetSSAFlag().version);
+ break;
+
+ case IndexListLowLevelOperand:
+ PrintIndent(indent);
+ printf("index list ");
+ for (auto i : operand.GetIndexList())
+ printf("%" PRIdPTR " ", i);
+ printf("\n");
+ break;
+
+ case SSARegisterListLowLevelOperand:
+ PrintIndent(indent);
+ printf("ssa reg list ");
+ for (auto& i : operand.GetSSARegisterList())
+ {
+ PrintRegister(instr.function, i.reg);
+ printf("#%" PRIdPTR " ", i.version);
+ }
+ printf("\n");
+ break;
+
+ case SSAFlagListLowLevelOperand:
+ PrintIndent(indent);
+ printf("ssa reg list ");
+ for (auto& i : operand.GetSSAFlagList())
+ {
+ PrintFlag(instr.function, i.flag);
+ printf("#%" PRIdPTR " ", i.version);
+ }
+ printf("\n");
+ break;
+
+ default:
+ PrintIndent(indent);
+ printf("<invalid operand>\n");
+ break;
+ }
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ {
+ fprintf(stderr, "Expected input filename\n");
+ return 1;
+ }
+
+ // In order to initiate the bundled plugins properly, the location
+ // of where bundled plugins directory is must be set. Since
+ // libbinaryninjacore is in the path get the path to it and use it to
+ // determine the plugins directory
+ SetBundledPluginDirectory(GetPluginsDirectory());
+ InitCorePlugins();
+ InitUserPlugins();
+
+ Ref<BinaryData> bd = new BinaryData(new FileMetadata(), argv[1]);
+ Ref<BinaryView> bv;
+ for (auto type : BinaryViewType::GetViewTypes())
+ {
+ if (type->IsTypeValidForData(bd) && type->GetName() != "Raw")
+ {
+ bv = type->Create(bd);
+ break;
+ }
+ }
+
+ if (!bv || bv->GetTypeName() == "Raw")
+ {
+ fprintf(stderr, "Input file does not appear to be an exectuable\n");
+ return -1;
+ }
+
+ bv->UpdateAnalysisAndWait();
+
+ // Go through all functions in the binary
+ for (auto& func : bv->GetAnalysisFunctionList())
+ {
+ // Get the name of the function and display it
+ Ref<Symbol> sym = func->GetSymbol();
+ if (sym)
+ printf("Function %s:\n", sym->GetFullName().c_str());
+ else
+ printf("Function at 0x%" PRIx64 ":\n", func->GetStart());
+
+ // Fetch the low level IL for the function
+ Ref<LowLevelILFunction> il = func->GetLowLevelIL();
+ if (!il)
+ {
+ printf(" Does not have LLIL\n\n");
+ continue;
+ }
+
+ // Loop through all blocks in the function
+ for (auto& block : il->GetBasicBlocks())
+ {
+ // Loop though each instruction in the block
+ for (size_t instrIndex = block->GetStart(); instrIndex < block->GetEnd(); instrIndex++)
+ {
+ // Fetch IL instruction
+ LowLevelILInstruction instr = (*il)[instrIndex];
+
+ // Display core's intrepretation of the IL instruction
+ vector<InstructionTextToken> tokens;
+ il->GetInstructionText(func, func->GetArchitecture(), instrIndex, tokens);
+ printf(" %" PRIdPTR " @ 0x%" PRIx64 " ", instrIndex, instr.address);
+ for (auto& token: tokens)
+ printf("%s", token.text.c_str());
+ printf("\n");
+
+ // Generically parse the IL tree and display the parts
+ PrintILExpr(instr, 2);
+
+ // Example of using visitors to find all constants in the instruction
+ instr.VisitExprs([&](const LowLevelILInstruction& expr) {
+ switch (expr.operation)
+ {
+ case LLIL_CONST:
+ case LLIL_CONST_PTR:
+ printf(" Found constant 0x%" PRIx64 "\n", expr.GetConstant());
+ return false; // Done parsing this
+ default:
+ break;
+ }
+ return true; // Parse any subexpressions
+ });
+
+ // Example of using the templated accessors for efficiently parsing load instructions
+ instr.VisitExprs([&](const LowLevelILInstruction& expr) {
+ switch (expr.operation)
+ {
+ case LLIL_LOAD:
+ if (expr.GetSourceExpr<LLIL_LOAD>().operation == LLIL_CONST_PTR)
+ {
+ printf(" Loading from address 0x%" PRIx64 "\n",
+ expr.GetSourceExpr<LLIL_LOAD>().GetConstant<LLIL_CONST_PTR>());
+ return false; // Done parsing this
+ }
+ break;
+ default:
+ break;
+ }
+ return true; // Parse any subexpressions
+ });
+ }
+ }
+
+ printf("\n");
+ }
+ return 0;
+}
diff --git a/examples/mlil_parser/CMakeLists.txt b/examples/mlil_parser/CMakeLists.txt
new file mode 100644
index 00000000..1bf6e3a7
--- /dev/null
+++ b/examples/mlil_parser/CMakeLists.txt
@@ -0,0 +1,50 @@
+# Mostly copied from https://github.com/Vector35/binaryninja-api/blob/dev/examples/breakpoint/CMakeLists.txt
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+project(MLIL_Parser)
+
+#-----------------------------------------------------------------------------
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..)
+#-----------------------------------------------------------------------------
+file( GLOB_RECURSE SRCS *.cpp *.h)
+#-----------------------------------------------------------------------------
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+#-----------------------------------------------------------------------------
+if(WIN32)
+ set(BINJA_DIR "C:\\Program Files\\Vector35\\BinaryNinja"
+ CACHE PATH "Binary Ninja installation directory")
+ set(BINJA_BIN_DIR "${BINJA_DIR}")
+ set(BINJA_PLUGINS_DIR "$ENV{APPDATA}/Binary Ninja/plugins"
+ CACHE PATH "Binary Ninja user plugins directory")
+elseif(APPLE)
+ set(BINJA_DIR "/Applications/Binary Ninja.app"
+ CACHE PATH "Binary Ninja installation directory")
+ set(BINJA_BIN_DIR "${BINJA_DIR}/Contents/MacOS")
+ set(BINJA_PLUGINS_DIR "$ENV{HOME}/Library/Application Support/Binary Ninja/plugins"
+ CACHE PATH "Binary Ninja user plugins directory")
+else()
+ set(BINJA_DIR "$ENV{HOME}/binaryninja"
+ CACHE PATH "Binary Ninja installation directory")
+ set(BINJA_BIN_DIR "${BINJA_DIR}")
+ set(BINJA_PLUGINS_DIR "$ENV{HOME}/.binaryninja/plugins"
+ CACHE PATH "Binary Ninja user plugins directory")
+endif()
+#-----------------------------------------------------------------------------
+add_executable (${PROJECT_NAME} ${SRCS} )
+#-----------------------------------------------------------------------------
+find_library(BINJA_API_LIBRARY binaryninjaapi
+ HINTS ${CMAKE_CURRENT_SOURCE_DIR}/../../bin ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Release ${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Debug)
+find_library(BINJA_CORE_LIBRARY binaryninjacore
+ HINTS ${BINJA_BIN_DIR})
+#-----------------------------------------------------------------------------
+target_link_libraries(${PROJECT_NAME}
+ ${BINJA_API_LIBRARY}
+ ${BINJA_CORE_LIBRARY}
+ )
+#-----------------------------------------------------------------------------
+install (TARGETS ${PROJECT_NAME}
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION Lib
+ ARCHIVE DESTINATION Lib)
+
diff --git a/examples/mlil_parser/Makefile b/examples/mlil_parser/Makefile
new file mode 100644
index 00000000..44b7b77f
--- /dev/null
+++ b/examples/mlil_parser/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 := g++
+else
+ BINJAPATH := /Applications/Binary\ Ninja.app/Contents/MacOS
+ CC := clang++
+endif
+
+SRCDIR := src
+BUILDDIR := build
+TARGETDIR := bin
+
+TARGETNAME := mlil_parser
+TARGET := $(TARGETDIR)/$(TARGETNAME)
+
+SRCEXT := cpp
+SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
+OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
+
+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) -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) $(CFLAGS) $(INC) -c -o $@ $<
+
+clean:
+ $(RM) -r $(BUILDDIR) $(TARGETDIR)
+
+.PHONY: clean
diff --git a/examples/mlil_parser/Makefile.win b/examples/mlil_parser/Makefile.win
new file mode 100644
index 00000000..92718ac0
--- /dev/null
+++ b/examples/mlil_parser/Makefile.win
@@ -0,0 +1,9 @@
+BINJA_API_INC_PATH = ..\..\
+BINJA_API_LIB = ..\..\bin\libbinaryninjaapi.lib
+BINJA_CORE_LIB = "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib"
+
+FLAGS = /DWIN32 /D__WIN32__ /EHsc /I$(BINJA_API_INC_PATH) /link $(BINJA_API_LIB) $(BINJA_CORE_LIB)
+
+bininfo: ./src/mlil_parser.cpp
+ if not exist bin mkdir bin
+ cl ./src/mlil_parser.cpp $(FLAGS) /Fe:.\bin\bininfo
diff --git a/examples/mlil_parser/src/mlil_parser.cpp b/examples/mlil_parser/src/mlil_parser.cpp
new file mode 100644
index 00000000..8fb762eb
--- /dev/null
+++ b/examples/mlil_parser/src/mlil_parser.cpp
@@ -0,0 +1,356 @@
+#include <stdio.h>
+#include <inttypes.h>
+#include "binaryninjacore.h"
+#include "binaryninjaapi.h"
+#include "mediumlevelilinstruction.h"
+
+using namespace BinaryNinja;
+using namespace std;
+
+
+#ifndef __WIN32__
+#include <libgen.h>
+#include <dlfcn.h>
+static string GetPluginsDirectory()
+{
+ Dl_info info;
+ if (!dladdr((void *)BNGetBundledPluginDirectory, &info))
+ return NULL;
+
+ stringstream ss;
+ ss << dirname((char *)info.dli_fname) << "/plugins/";
+ return ss.str();
+}
+#else
+static string GetPluginsDirectory()
+{
+ return "C:\\Program Files\\Vector35\\Binary Ninja\\plugins\\";
+}
+#endif
+
+
+static void PrintIndent(size_t indent)
+{
+ for (size_t i = 0; i < indent; i++)
+ printf(" ");
+}
+
+
+static void PrintOperation(BNMediumLevelILOperation operation)
+{
+#define ENUM_PRINTER(op) \
+ case op: \
+ printf(#op); \
+ break;
+
+ switch (operation)
+ {
+ ENUM_PRINTER(MLIL_NOP)
+ ENUM_PRINTER(MLIL_SET_VAR)
+ ENUM_PRINTER(MLIL_SET_VAR_FIELD)
+ ENUM_PRINTER(MLIL_SET_VAR_SPLIT)
+ ENUM_PRINTER(MLIL_LOAD)
+ ENUM_PRINTER(MLIL_LOAD_STRUCT)
+ ENUM_PRINTER(MLIL_STORE)
+ ENUM_PRINTER(MLIL_STORE_STRUCT)
+ ENUM_PRINTER(MLIL_VAR)
+ ENUM_PRINTER(MLIL_VAR_FIELD)
+ ENUM_PRINTER(MLIL_ADDRESS_OF)
+ ENUM_PRINTER(MLIL_ADDRESS_OF_FIELD)
+ ENUM_PRINTER(MLIL_CONST)
+ ENUM_PRINTER(MLIL_CONST_PTR)
+ ENUM_PRINTER(MLIL_ADD)
+ ENUM_PRINTER(MLIL_ADC)
+ ENUM_PRINTER(MLIL_SUB)
+ ENUM_PRINTER(MLIL_SBB)
+ ENUM_PRINTER(MLIL_AND)
+ ENUM_PRINTER(MLIL_OR)
+ ENUM_PRINTER(MLIL_XOR)
+ ENUM_PRINTER(MLIL_LSL)
+ ENUM_PRINTER(MLIL_LSR)
+ ENUM_PRINTER(MLIL_ASR)
+ ENUM_PRINTER(MLIL_ROL)
+ ENUM_PRINTER(MLIL_RLC)
+ ENUM_PRINTER(MLIL_ROR)
+ ENUM_PRINTER(MLIL_RRC)
+ ENUM_PRINTER(MLIL_MUL)
+ ENUM_PRINTER(MLIL_MULU_DP)
+ ENUM_PRINTER(MLIL_MULS_DP)
+ ENUM_PRINTER(MLIL_DIVU)
+ ENUM_PRINTER(MLIL_DIVU_DP)
+ ENUM_PRINTER(MLIL_DIVS)
+ ENUM_PRINTER(MLIL_DIVS_DP)
+ ENUM_PRINTER(MLIL_MODU)
+ ENUM_PRINTER(MLIL_MODU_DP)
+ ENUM_PRINTER(MLIL_MODS)
+ ENUM_PRINTER(MLIL_MODS_DP)
+ ENUM_PRINTER(MLIL_NEG)
+ ENUM_PRINTER(MLIL_NOT)
+ ENUM_PRINTER(MLIL_SX)
+ ENUM_PRINTER(MLIL_ZX)
+ ENUM_PRINTER(MLIL_LOW_PART)
+ ENUM_PRINTER(MLIL_JUMP)
+ ENUM_PRINTER(MLIL_JUMP_TO)
+ ENUM_PRINTER(MLIL_CALL)
+ ENUM_PRINTER(MLIL_CALL_UNTYPED)
+ ENUM_PRINTER(MLIL_CALL_OUTPUT)
+ ENUM_PRINTER(MLIL_CALL_PARAM)
+ ENUM_PRINTER(MLIL_RET)
+ ENUM_PRINTER(MLIL_NORET)
+ ENUM_PRINTER(MLIL_IF)
+ ENUM_PRINTER(MLIL_GOTO)
+ ENUM_PRINTER(MLIL_CMP_E)
+ ENUM_PRINTER(MLIL_CMP_NE)
+ ENUM_PRINTER(MLIL_CMP_SLT)
+ ENUM_PRINTER(MLIL_CMP_ULT)
+ ENUM_PRINTER(MLIL_CMP_SLE)
+ ENUM_PRINTER(MLIL_CMP_ULE)
+ ENUM_PRINTER(MLIL_CMP_SGE)
+ ENUM_PRINTER(MLIL_CMP_UGE)
+ ENUM_PRINTER(MLIL_CMP_SGT)
+ ENUM_PRINTER(MLIL_CMP_UGT)
+ ENUM_PRINTER(MLIL_TEST_BIT)
+ ENUM_PRINTER(MLIL_BOOL_TO_INT)
+ ENUM_PRINTER(MLIL_ADD_OVERFLOW)
+ ENUM_PRINTER(MLIL_SYSCALL)
+ ENUM_PRINTER(MLIL_SYSCALL_UNTYPED)
+ ENUM_PRINTER(MLIL_BP)
+ ENUM_PRINTER(MLIL_TRAP)
+ ENUM_PRINTER(MLIL_UNDEF)
+ ENUM_PRINTER(MLIL_UNIMPL)
+ ENUM_PRINTER(MLIL_UNIMPL_MEM)
+ ENUM_PRINTER(MLIL_SET_VAR_SSA)
+ ENUM_PRINTER(MLIL_SET_VAR_SSA_FIELD)
+ ENUM_PRINTER(MLIL_SET_VAR_SPLIT_SSA)
+ ENUM_PRINTER(MLIL_SET_VAR_ALIASED)
+ ENUM_PRINTER(MLIL_SET_VAR_ALIASED_FIELD)
+ ENUM_PRINTER(MLIL_VAR_SSA)
+ ENUM_PRINTER(MLIL_VAR_SSA_FIELD)
+ ENUM_PRINTER(MLIL_VAR_ALIASED)
+ ENUM_PRINTER(MLIL_VAR_ALIASED_FIELD)
+ ENUM_PRINTER(MLIL_CALL_SSA)
+ ENUM_PRINTER(MLIL_CALL_UNTYPED_SSA)
+ ENUM_PRINTER(MLIL_SYSCALL_SSA)
+ ENUM_PRINTER(MLIL_SYSCALL_UNTYPED_SSA)
+ ENUM_PRINTER(MLIL_CALL_PARAM_SSA)
+ ENUM_PRINTER(MLIL_CALL_OUTPUT_SSA)
+ ENUM_PRINTER(MLIL_LOAD_SSA)
+ ENUM_PRINTER(MLIL_LOAD_STRUCT_SSA)
+ ENUM_PRINTER(MLIL_STORE_SSA)
+ ENUM_PRINTER(MLIL_STORE_STRUCT_SSA)
+ ENUM_PRINTER(MLIL_VAR_PHI)
+ ENUM_PRINTER(MLIL_MEM_PHI)
+ default:
+ printf("<invalid operation %" PRId32 ">", operation);
+ break;
+ }
+}
+
+
+static void PrintVariable(MediumLevelILFunction* func, const Variable& var)
+{
+ string name = func->GetFunction()->GetVariableName(var);
+ if (name.size() == 0)
+ printf("<no name>");
+ else
+ printf("%s", name.c_str());
+}
+
+
+static void PrintILExpr(const MediumLevelILInstruction& instr, size_t indent)
+{
+ PrintIndent(indent);
+ PrintOperation(instr.operation);
+ printf("\n");
+
+ indent++;
+
+ for (auto& operand : instr.GetOperands())
+ {
+ switch (operand.GetType())
+ {
+ case IntegerMediumLevelOperand:
+ PrintIndent(indent);
+ printf("int 0x%" PRIx64 "\n", operand.GetInteger());
+ break;
+
+ case IndexMediumLevelOperand:
+ PrintIndent(indent);
+ printf("index %" PRIdPTR "\n", operand.GetIndex());
+ break;
+
+ case ExprMediumLevelOperand:
+ PrintILExpr(operand.GetExpr(), indent);
+ break;
+
+ case VariableMediumLevelOperand:
+ PrintIndent(indent);
+ printf("var ");
+ PrintVariable(instr.function, operand.GetVariable());
+ printf("\n");
+ break;
+
+ case SSAVariableMediumLevelOperand:
+ PrintIndent(indent);
+ printf("ssa var ");
+ PrintVariable(instr.function, operand.GetSSAVariable().var);
+ printf("#%" PRIdPTR "\n", operand.GetSSAVariable().version);
+ break;
+
+ case IndexListMediumLevelOperand:
+ PrintIndent(indent);
+ printf("index list ");
+ for (auto i : operand.GetIndexList())
+ printf("%" PRIdPTR " ", i);
+ printf("\n");
+ break;
+
+ case VariableListMediumLevelOperand:
+ PrintIndent(indent);
+ printf("var list ");
+ for (auto& i : operand.GetVariableList())
+ {
+ PrintVariable(instr.function, i);
+ printf(" ");
+ }
+ printf("\n");
+ break;
+
+ case SSAVariableListMediumLevelOperand:
+ PrintIndent(indent);
+ printf("ssa var list ");
+ for (auto& i : operand.GetSSAVariableList())
+ {
+ PrintVariable(instr.function, i.var);
+ printf("#%" PRIdPTR " ", i.version);
+ }
+ printf("\n");
+ break;
+
+ case ExprListMediumLevelOperand:
+ PrintIndent(indent);
+ printf("expr list\n");
+ for (auto& i : operand.GetExprList())
+ PrintILExpr(i, indent + 1);
+ break;
+
+ default:
+ PrintIndent(indent);
+ printf("<invalid operand>\n");
+ break;
+ }
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2)
+ {
+ fprintf(stderr, "Expected input filename\n");
+ return 1;
+ }
+
+ // In order to initiate the bundled plugins properly, the location
+ // of where bundled plugins directory is must be set. Since
+ // libbinaryninjacore is in the path get the path to it and use it to
+ // determine the plugins directory
+ SetBundledPluginDirectory(GetPluginsDirectory());
+ InitCorePlugins();
+ InitUserPlugins();
+
+ Ref<BinaryData> bd = new BinaryData(new FileMetadata(), argv[1]);
+ Ref<BinaryView> bv;
+ for (auto type : BinaryViewType::GetViewTypes())
+ {
+ if (type->IsTypeValidForData(bd) && type->GetName() != "Raw")
+ {
+ bv = type->Create(bd);
+ break;
+ }
+ }
+
+ if (!bv || bv->GetTypeName() == "Raw")
+ {
+ fprintf(stderr, "Input file does not appear to be an exectuable\n");
+ return -1;
+ }
+
+ bv->UpdateAnalysisAndWait();
+
+ // Go through all functions in the binary
+ for (auto& func : bv->GetAnalysisFunctionList())
+ {
+ // Get the name of the function and display it
+ Ref<Symbol> sym = func->GetSymbol();
+ if (sym)
+ printf("Function %s:\n", sym->GetFullName().c_str());
+ else
+ printf("Function at 0x%" PRIx64 ":\n", func->GetStart());
+
+ // Fetch the medium level IL for the function
+ Ref<MediumLevelILFunction> il = func->GetMediumLevelIL();
+ if (!il)
+ {
+ printf(" Does not have MLIL\n\n");
+ continue;
+ }
+
+ // Loop through all blocks in the function
+ for (auto& block : il->GetBasicBlocks())
+ {
+ // Loop though each instruction in the block
+ for (size_t instrIndex = block->GetStart(); instrIndex < block->GetEnd(); instrIndex++)
+ {
+ // Fetch IL instruction
+ MediumLevelILInstruction instr = (*il)[instrIndex];
+
+ // Display core's intrepretation of the IL instruction
+ vector<InstructionTextToken> tokens;
+ il->GetInstructionText(func, func->GetArchitecture(), instrIndex, tokens);
+ printf(" %" PRIdPTR " @ 0x%" PRIx64 " ", instrIndex, instr.address);
+ for (auto& token: tokens)
+ printf("%s", token.text.c_str());
+ printf("\n");
+
+ // Generically parse the IL tree and display the parts
+ PrintILExpr(instr, 2);
+
+ // Example of using visitors to find all constants in the instruction
+ instr.VisitExprs([&](const MediumLevelILInstruction& expr) {
+ switch (expr.operation)
+ {
+ case MLIL_CONST:
+ case MLIL_CONST_PTR:
+ printf(" Found constant 0x%" PRIx64 "\n", expr.GetConstant());
+ return false; // Done parsing this
+ default:
+ break;
+ }
+ return true; // Parse any subexpressions
+ });
+
+ // Example of using the templated accessors for efficiently parsing load instructions
+ instr.VisitExprs([&](const MediumLevelILInstruction& expr) {
+ switch (expr.operation)
+ {
+ case MLIL_LOAD:
+ if (expr.GetSourceExpr<MLIL_LOAD>().operation == MLIL_CONST_PTR)
+ {
+ printf(" Loading from address 0x%" PRIx64 "\n",
+ expr.GetSourceExpr<MLIL_LOAD>().GetConstant<MLIL_CONST_PTR>());
+ return false; // Done parsing this
+ }
+ break;
+ default:
+ break;
+ }
+ return true; // Parse any subexpressions
+ });
+ }
+ }
+
+ printf("\n");
+ }
+ return 0;
+}
diff --git a/examples/x86_extension/Makefile b/examples/x86_extension/Makefile
new file mode 100644
index 00000000..1ee60891
--- /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 -Wno-unused-function
+
+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 f78096d79ccfcc5169b6e2ae0fa89e3eed5b85c
diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp
new file mode 100644
index 00000000..9efcc119
--- /dev/null
+++ b/examples/x86_extension/src/x86_extension.cpp
@@ -0,0 +1,502 @@
+#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;
+
+
+#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
+{
+ 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;
+ }
+}