From e47e2fb13369ff7d1c9e7728bb793ee56640afe1 Mon Sep 17 00:00:00 2001 From: Rusty Wagner Date: Tue, 1 Aug 2017 23:39:18 -0400 Subject: Refactor IL instruction access APIs --- examples/llil_parser/src/LowLevel_IL_Parser.cpp | 442 ------------------------ examples/llil_parser/src/llil_parser.cpp | 409 ++++++++++++++++++++++ 2 files changed, 409 insertions(+), 442 deletions(-) delete mode 100644 examples/llil_parser/src/LowLevel_IL_Parser.cpp create mode 100644 examples/llil_parser/src/llil_parser.cpp (limited to 'examples/llil_parser/src') diff --git a/examples/llil_parser/src/LowLevel_IL_Parser.cpp b/examples/llil_parser/src/LowLevel_IL_Parser.cpp deleted file mode 100644 index 2f61b83a..00000000 --- a/examples/llil_parser/src/LowLevel_IL_Parser.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* -LLIL Parser - Binary Ninja C++ API Sample - - Robert Yates - 22/JUN/17 - */ - -#include "LowLevel_IL_Parser.h" -#include -#include - -int main(int argc, char* argv[]) -{ - - try - { - ShowBanner(); - - - if (argc != 2) - { - printf("Usage: %s \n", argv[0]); - exit(-1); - } - - std::string inputName = argv[1]; - - SetBundledPluginDirectory(get_plugins_directory()); - InitCorePlugins(); - InitUserPlugins(); - - auto bd = BinaryData(new FileMetadata(), inputName.c_str()); - BinaryView *bv; - - for (auto type : BinaryViewType::GetViewTypes()) - { - if (type->IsTypeValidForData(&bd) && type->GetName() != "Raw") - { - bv = type->Create(&bd); - break; - } - } - - printf("[i] Starting analysis\n"); - bv->UpdateAnalysisAndWait(); - - printf("[i] Analysis done - %zd Functions\n", bv->GetAnalysisFunctionList().size()); - - if (bv->GetAnalysisFunctionList().size() < 1) - throw std::runtime_error("Error no functions found\n"); - - LlilParser myParser(bv); - myParser.decodeWholeFunction(bv->GetAnalysisFunctionList()[0]); - - /* - // Show Single LLIL in function x at index x - myParser.decodeIndexInFunction(0x407930, 0); - - // Decode a whole function by address - myParser.decodeWholeFunction(0x407930); - - // Decode all functions - for (const auto& f : bv->GetAnalysisFunctionList()) - { - // Decode a whole function by BinaryNinja::Function object - myParser.decodeWholeFunction(f); - } - */ - - } - catch (const std::exception& e) - { - printf("An Exception Occured: %s\n", e.what()); - } - - printf("[i] Finished\n"); -} - - - -LlilParser::LlilParser(BinaryView *bv) - : m_bv(bv) -{ - m_currentFunction.clear(); - m_tabs = 0; - m_currentInstructionId = 0; -} - -void LlilParser::showIndent() const -{ - for (int i = 0; i < m_tabs; i++) - printf(" "); -} - -void LlilParser::analysisInstruction(const BNLowLevelILInstruction& insn) -{ - - auto instructionSynatx = g_llilSyntaxMap.find(insn.operation); - BinaryNinja::Ref llil = m_currentFunction[0]->GetLowLevelIL(); - if (instructionSynatx == g_llilSyntaxMap.end()) - throw std::runtime_error("Error unknown LLIL\n"); - - showIndent(); - printf("Instruction: %s\n", getLowLevelILOperationName(insn.operation).c_str()); - m_tabs += 3; - - int operandId = 0; - for (const auto& operand : instructionSynatx->second) - { - if (operand.type == OperandType::kExpr) - { - // In this case the value in the operands[x] field is a new instruction & expression index value - BNLowLevelILInstruction nextInstruction = (*llil)[insn.operands[operandId]]; - - analysisInstruction(nextInstruction); // recursion begins :) - } - else if (operand.type == OperandType::kReg) - { - // In this case the register id is in the first operands field and we use Arch to translate - showIndent(); - printf("Reg: %s\n", m_bv->GetDefaultArchitecture()->GetRegisterName(static_cast(insn.operands[0])).c_str()); - m_tabs += 3; - } - else if (operand.type == OperandType::kInt) - { - // In this case the operand is simply a value - showIndent(); - printf("Value: %zX\n", insn.operands[0]); - m_tabs += 3; - } - else if (operand.type == OperandType::kFlag) - { - // In this case the operand is a flag - printf("Flag: %s\n", m_bv->GetDefaultArchitecture()->GetFlagName(static_cast(insn.operands[0])).c_str()); - m_tabs += 3; - } - else if (operand.type == OperandType::kIntList) - { - // In this case we have an array of llil targets - std::vector intList = llil->GetOperandList(llil->GetIndexForInstruction(m_currentInstructionId), operandId); - showIndent(); - printf("Target LLIL Indices: "); - for (const auto i : intList) - { - printf("%zd ", i); - } - printf("\n"); - } - else - { - printf("[e] LLIL Parser: Not Handled -> OperandPurpose: %d OperandType: %d\n", operand.purpose, operand.type); - } - - - operandId++; - } - - -} - -void LlilParser::decodeIndexInFunction(uint64_t functionAddress, int indexIl) -{ - - m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress); - if (m_currentFunction.size() < 1) - throw std::runtime_error("Error no functions at requested address\n"); - - BinaryNinja::Function *function = m_currentFunction[0]; - BinaryNinja::Ref llil = function->GetLowLevelIL(); - - m_currentInstructionId = indexIl; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(indexIl)]; - - - analysisInstruction(currentInstruction); - m_tabs = 0; - -} - -void LlilParser::decodeWholeFunction(BinaryNinja::Function *function) -{ - m_currentFunction.clear(); - m_currentFunction.push_back(function); - - BinaryNinja::Ref llil = function->GetLowLevelIL(); - - for (size_t i = 0; i < llil->GetInstructionCount(); i++) - { - - m_currentInstructionId = i; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)]; - - printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i); - - analysisInstruction(currentInstruction); - m_tabs = 0; - } - -} - -void LlilParser::decodeWholeFunction(uint64_t functionAddress) -{ - - m_currentFunction = m_bv->GetAnalysisFunctionsForAddress(functionAddress); - if (m_currentFunction.size() < 1) - throw std::runtime_error("Error no functions at requested address or possible invalid BundledPluginDirectory\n"); - - BinaryNinja::Function *function = m_currentFunction[0]; - BinaryNinja::Ref llil = function->GetLowLevelIL(); - - - - for (size_t i = 0; i < llil->GetInstructionCount(); i++) - { - m_currentInstructionId = i; - BNLowLevelILInstruction currentInstruction = (*llil)[llil->GetIndexForInstruction(i)]; - - printf("\n[%zx][%zd]---------------------------------------------------------------------------\n", currentInstruction.address, i); - - analysisInstruction(currentInstruction); - m_tabs = 0; - } - -} - -void ShowBanner() -{ - - printf (".____ .____ .___.____ __________ \n"); - printf ("| | | | | | | \\______ \\_____ _______ ______ ___________ \n"); - printf ("| | | | | | | | ___/\\__ \\\\_ __ \\/ ___// __ \\_ __ \\\n"); - printf ("| |___| |___| | |___ | | / __ \\| | \\/\\___ \\\\ ___/| | \\/\n"); - printf ("|_______ \\_______ \\___|_______ \\ |____| (____ /__| /____ >\\___ >__| \n"); - printf (" \\/ \\/ \\/ \\/ \\/ \\/ \n"); - printf("====================================================================================\n\n"); - -} - -#ifdef _WIN32 -std::string get_plugins_directory() -{ - return "C:\\Program Files\\Vector35\\BinaryNinja\\plugins\\"; -} -#elif __APPLE__ -std::string get_plugins_directory() -{ - return "/Applications/Binary Ninja.app/Contents/MacOS/plugins/"; -} -#else -std::string get_plugins_directory() -{ - return "~/binaryninja/plugins"; -} -#endif - -const std::string LlilParser::getLowLevelILOperationName(BNLowLevelILOperation id) const -{ - - switch (id) - { - case LLIL_NOP: - return "LLIL_NOP"; - case LLIL_SET_REG: - return "LLIL_SET_REG"; - case LLIL_SET_REG_SPLIT: - return "LLIL_SET_REG_SPLIT"; - case LLIL_SET_FLAG: - return "LLIL_SET_FLAG"; - case LLIL_LOAD: - return "LLIL_LOAD"; - case LLIL_STORE: - return "LLIL_STORE"; - case LLIL_PUSH: - return "LLIL_PUSH"; - case LLIL_POP: - return "LLIL_POP"; - case LLIL_REG: - return "LLIL_REG"; - case LLIL_CONST: - return "LLIL_CONST"; - case LLIL_CONST_PTR: - return "LLIL_CONST_PTR"; - case LLIL_FLAG: - return "LLIL_FLAG"; - case LLIL_FLAG_BIT: - return "LLIL_FLAG_BIT"; - case LLIL_ADD: - return "LLIL_ADD"; - case LLIL_ADC: - return "LLIL_ADC"; - case LLIL_SUB: - return "LLIL_SUB"; - case LLIL_SBB: - return "LLIL_SBB"; - case LLIL_AND: - return "LLIL_AND"; - case LLIL_OR: - return "LLIL_OR"; - case LLIL_XOR: - return "LLIL_XOR"; - case LLIL_LSL: - return "LLIL_LSL"; - case LLIL_LSR: - return "LLIL_LSR"; - case LLIL_ASR: - return "LLIL_ASR"; - case LLIL_ROL: - return "LLIL_ROL"; - case LLIL_RLC: - return "LLIL_RLC"; - case LLIL_ROR: - return "LLIL_ROR"; - case LLIL_RRC: - return "LLIL_RRC"; - case LLIL_MUL: - return "LLIL_MUL"; - case LLIL_MULU_DP: - return "LLIL_MULU_DP"; - case LLIL_MULS_DP: - return "LLIL_MULS_DP"; - case LLIL_DIVU: - return "LLIL_DIVU"; - case LLIL_DIVU_DP: - return "LLIL_DIVU_DP"; - case LLIL_DIVS: - return "LLIL_DIVS"; - case LLIL_DIVS_DP: - return "LLIL_DIVS_DP"; - case LLIL_MODU: - return "LLIL_MODU"; - case LLIL_MODU_DP: - return "LLIL_MODU_DP"; - case LLIL_MODS: - return "LLIL_MODS"; - case LLIL_MODS_DP: - return "LLIL_MODS_DP"; - case LLIL_NEG: - return "LLIL_NEG"; - case LLIL_NOT: - return "LLIL_NOT"; - case LLIL_SX: - return "LLIL_SX"; - case LLIL_ZX: - return "LLIL_ZX"; - case LLIL_LOW_PART: - return "LLIL_LOW_PART"; - case LLIL_JUMP: - return "LLIL_JUMP"; - case LLIL_JUMP_TO: - return "LLIL_JUMP_TO"; - case LLIL_CALL: - return "LLIL_CALL"; - case LLIL_RET: - return "LLIL_RET"; - case LLIL_NORET: - return "LLIL_NORET"; - case LLIL_IF: - return "LLIL_IF"; - case LLIL_GOTO: - return "LLIL_GOTO"; - case LLIL_FLAG_COND: - return "LLIL_FLAG_COND"; - case LLIL_CMP_E: - return "LLIL_CMP_E"; - case LLIL_CMP_NE: - return "LLIL_CMP_NE"; - case LLIL_CMP_SLT: - return "LLIL_CMP_SLT"; - case LLIL_CMP_ULT: - return "LLIL_CMP_ULT"; - case LLIL_CMP_SLE: - return "LLIL_CMP_SLE"; - case LLIL_CMP_ULE: - return "LLIL_CMP_ULE"; - case LLIL_CMP_SGE: - return "LLIL_CMP_SGE"; - case LLIL_CMP_UGE: - return "LLIL_CMP_UGE"; - case LLIL_CMP_SGT: - return "LLIL_CMP_SGT"; - case LLIL_CMP_UGT: - return "LLIL_CMP_UGT"; - case LLIL_TEST_BIT: - return "LLIL_TEST_BIT"; - case LLIL_BOOL_TO_INT: - return "LLIL_BOOL_TO_INT"; - case LLIL_ADD_OVERFLOW: - return "LLIL_ADD_OVERFLOW"; - case LLIL_SYSCALL: - return "LLIL_SYSCALL"; - case LLIL_BP: - return "LLIL_BP"; - case LLIL_TRAP: - return "LLIL_TRAP"; - case LLIL_UNDEF: - return "LLIL_UNDEF"; - case LLIL_UNIMPL: - return "LLIL_UNIMPL"; - case LLIL_UNIMPL_MEM: - return "LLIL_UNIMPL_MEM"; - case LLIL_SET_REG_SSA: - return "LLIL_SET_REG_SSA"; - case LLIL_SET_REG_SSA_PARTIAL: - return "LLIL_SET_REG_SSA_PARTIAL"; - case LLIL_SET_REG_SPLIT_SSA: - return "LLIL_SET_REG_SPLIT_SSA"; - case LLIL_REG_SPLIT_DEST_SSA: - return "LLIL_REG_SPLIT_DEST_SSA"; - case LLIL_REG_SSA: - return "LLIL_REG_SSA"; - case LLIL_REG_SSA_PARTIAL: - return "LLIL_REG_SSA_PARTIAL"; - case LLIL_SET_FLAG_SSA: - return "LLIL_SET_FLAG_SSA"; - case LLIL_FLAG_SSA: - return "LLIL_FLAG_SSA"; - case LLIL_FLAG_BIT_SSA: - return "LLIL_FLAG_BIT_SSA"; - case LLIL_CALL_SSA: - return "LLIL_CALL_SSA"; - case LLIL_SYSCALL_SSA: - return "LLIL_SYSCALL_SSA"; - case LLIL_CALL_PARAM_SSA: - return "LLIL_CALL_PARAM_SSA"; - case LLIL_CALL_STACK_SSA: - return "LLIL_CALL_STACK_SSA"; - case LLIL_CALL_OUTPUT_SSA: - return "LLIL_CALL_OUTPUT_SSA"; - case LLIL_LOAD_SSA: - return "LLIL_LOAD_SSA"; - case LLIL_STORE_SSA: - return "LLIL_STORE_SSA"; - case LLIL_REG_PHI: - return "LLIL_REG_PHI"; - case LLIL_FLAG_PHI: - return "LLIL_FLAG_PHI"; - case LLIL_MEM_PHI: - return "LLIL_MEM_PHI"; - } - - return "Unknown"; - //throw std::runtime_error("GetLowLevelILOperationName Failure"); - -} \ No newline at end of file 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 +#include +#include "binaryninjacore.h" +#include "binaryninjaapi.h" +#include "lowlevelilinstruction.h" + +using namespace BinaryNinja; +using namespace std; + + +#ifndef __WIN32__ +#include +#include +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("", 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(""); + 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(""); + 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(""); + 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("\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 bd = new BinaryData(new FileMetadata(), argv[1]); + Ref 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 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 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 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().operation == LLIL_CONST_PTR) + { + printf(" Loading from address 0x%" PRIx64 "\n", + expr.GetSourceExpr().GetConstant()); + return false; // Done parsing this + } + break; + default: + break; + } + return true; // Parse any subexpressions + }); + } + } + + printf("\n"); + } + return 0; +} -- cgit v1.3.1