-
Notifications
You must be signed in to change notification settings - Fork 203
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A LLIL C++ API Parser example with in depth build notes (#721)
* make cmake file more generic and fix missing sources * add llil cpp example * added image * fix string stream under linux * fix path under linux * Update build notes for linux * analysis sync | mac os path | lill* usage change * added path note and removed comment about mac path * use UpdateAnalysisAndWait()
- Loading branch information
1 parent
c7e1874
commit cc3755b
Showing
5 changed files
with
730 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# 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("inc/") | ||
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) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
LLIL Parser - Binary Ninja C++ API Sample | ||
=== | ||
|
||
> Robert Yates | 22nd June 2017 | ||
LLIL Parser is a simple example for demonstrating how to use the BinaryNinja C++ API | ||
|
||
![ScreenShot](https://user-images.githubusercontent.com/1876966/27665067-58d34dd0-5c6b-11e7-9361-6efd01cfa0af.JPG) | ||
|
||
Example of building under windows from scratch | ||
=== | ||
|
||
* https://cmake.org/ Required for this example | ||
* We will be using Visual Studio 2017 however if want to use a different version simply run the `cmake -G` command to find the alternative name to use in the cmake commands below, be sure to use the Win64 version. | ||
|
||
Note: if you havent installed binary ninja into a default location then you will need to edit the cmake file and also the `std::string get_plugins_directory()` function in the `.cpp` file | ||
|
||
# Building the BinaryNinja API | ||
``` | ||
git clone https://github.com/Vector35/binaryninja-api.git | ||
cd binaryninja | ||
mkdir _build | ||
cd _build | ||
cmake .. -G "Visual Studio 15 2017 Win64" | ||
cmake --build . --config Release | ||
``` | ||
|
||
The objective here is to build the `binaryninjaapi.lib` This will be placed in the `bin` folder | ||
|
||
# Building the C++ Example | ||
|
||
``` | ||
cd ../examples | ||
mkdir _build | ||
cd _build | ||
cmake ../llil_parser -G "Visual Studio 15 2017 Win64" | ||
cmake --build . --config Release | ||
cd Release | ||
copy "c:\Program Files\Vector35\BinaryNinja\binaryninjacore.dll" . | ||
``` | ||
|
||
If you get an error about `BINJA_API_LIBRARY` check the API has built properly and `binaryninjaapi.lib` is located in the `bin` folder in the root folder of the API | ||
|
||
If you get an error about `BINJA_CORE_LIBRARY` then the file C:\Program Files\Vector35\BinaryNinja\binaryninjacore.lib is missing see [Create .lib file from .dll](https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/) on details about how to create this lib file from the dll file located in that directory | ||
|
||
> Building under the linux is almost exactly the same however you need not use the `-G` parameter and you build with the `make` command instead of `cmake --build` another important note is that i had to execute `cp ~/binaryninja/libbinaryninjacore.so.1 ~/binaryninja/libbinaryninjacore.so` before linking would work | ||
Note i do not have access to a MAC so i havent tested this. | ||
|
||
Using the example | ||
=== | ||
|
||
Simply run the compiled executable with a target binary as a parameter and it will parse the LLIL from the first detected function in the target binary. | ||
|
||
The `void LlilParser::analysisInstruction(const BNLowLevelILInstruction& insn)` function is probably the most | ||
function of interest for learning. | ||
|
||
This example is only intended for learning from the source code however if you wish to turn it into something more useful then you could add callbacks in the analysis function to keep track of when certain regs, values occur etc. | ||
|
||
# Disclaimer | ||
|
||
This was mostly figured out by myself and may not be the best way to achieve the intended desire, however i hope it serves as a starting point | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
#ifndef __LOWLEVEL_IL_PARSER_H_ | ||
#define __LOWLEVEL_IL_PARSER_H_ | ||
|
||
#include "binaryninjacore.h" | ||
#include "binaryninjaapi.h" | ||
#include <map> | ||
|
||
std::string get_plugins_directory(); | ||
void ShowBanner(); | ||
|
||
using namespace BinaryNinja; | ||
|
||
enum OperandPurpose | ||
{ | ||
kDest, | ||
kSrc, | ||
kConstant, | ||
kLeft, | ||
kRight, | ||
kHi, | ||
kLow, | ||
kTargets, | ||
kCondition, | ||
kVector, | ||
kOutput, | ||
kStack, | ||
kParam, | ||
kDestMemory, | ||
kSrcMemory, | ||
kTrue, | ||
kFalse, | ||
kBit, | ||
kCarry, | ||
kFullReg, | ||
}; | ||
|
||
enum OperandType | ||
{ | ||
kReg, | ||
kExpr, | ||
kFlag, | ||
kIntList, | ||
kInt, | ||
kRegSsa, | ||
kRegSsaList, | ||
kFlagSsa, | ||
kCond, | ||
kFlagSsaList, | ||
}; | ||
|
||
struct BNLowLevelILOperationSyntax | ||
{ | ||
OperandPurpose purpose; | ||
OperandType type; | ||
}; | ||
|
||
|
||
static std::map<BNLowLevelILOperation, std::vector<BNLowLevelILOperationSyntax>> g_llilSyntaxMap = { \ | ||
{ LLIL_NOP,{} }, \ | ||
{ LLIL_SET_REG,{ { kDest, kReg },{ kSrc,kExpr } } }, \ | ||
{ LLIL_SET_REG_SPLIT,{ { kHi, kReg },{ kLow,kReg },{ kSrc,kExpr } } } , \ | ||
{ LLIL_SET_FLAG,{ { kDest, kFlag },{ kSrc,kExpr } } }, \ | ||
{ LLIL_LOAD,{ { kSrc, kExpr } } }, \ | ||
{ LLIL_STORE,{ { kDest, kExpr },{ kSrc,kExpr } } }, \ | ||
{ LLIL_PUSH,{ { kSrc, kExpr } } }, \ | ||
{ LLIL_POP,{} }, \ | ||
{ LLIL_REG,{ { kSrc, kReg } } }, \ | ||
{ LLIL_CONST,{ { kConstant, kInt } } }, \ | ||
{ LLIL_CONST_PTR,{ { kConstant, kInt } } }, \ | ||
{ LLIL_FLAG,{ { kSrc, kFlag } } }, \ | ||
{ LLIL_FLAG_BIT,{ { kSrc, kFlag },{ kBit,kInt } } }, \ | ||
{ LLIL_ADD,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_ADC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ | ||
{ LLIL_SUB,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_SBB,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ | ||
{ LLIL_AND,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_OR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_XOR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_LSL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_LSR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_ASR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_ROL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_RLC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ | ||
{ LLIL_ROR,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_RRC,{ { kLeft, kExpr },{ kRight,kExpr },{ kCarry,kExpr } } }, \ | ||
{ LLIL_MUL,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_MULU_DP,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_MULS_DP,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_DIVU,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_DIVU_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_DIVS,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_DIVS_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_MODU,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_MODU_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_MODS,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_MODS_DP,{ { kHi, kExpr },{ kLow,kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_NEG,{ { kSrc, kExpr } } }, \ | ||
{ LLIL_NOT,{ { kSrc, kExpr } } }, \ | ||
{ LLIL_SX,{ { kSrc, kExpr } } }, \ | ||
{ LLIL_ZX,{ { kSrc, kExpr } } }, \ | ||
{ LLIL_LOW_PART,{ { kSrc, kExpr } } }, \ | ||
{ LLIL_JUMP,{ { kDest, kExpr } } }, \ | ||
{ LLIL_JUMP_TO,{ { kDest, kExpr },{ kTargets,kIntList } } }, \ | ||
{ LLIL_CALL,{ { kDest, kExpr } } }, \ | ||
{ LLIL_RET,{ { kDest, kExpr } } }, \ | ||
{ LLIL_NORET,{} }, \ | ||
{ LLIL_IF,{ { kCondition, kExpr },{ kTrue,kInt },{ kFalse,kInt } } }, \ | ||
{ LLIL_GOTO,{ { kDest, kInt } } }, \ | ||
{ LLIL_FLAG_COND,{ { kCondition, kCond } } }, \ | ||
{ LLIL_CMP_E,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_CMP_NE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_CMP_SLT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_CMP_ULT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_CMP_SLE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_CMP_ULE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_CMP_SGE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_CMP_UGE,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_CMP_SGT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_CMP_UGT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_TEST_BIT,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_BOOL_TO_INT,{ { kSrc, kExpr } } }, \ | ||
{ LLIL_ADD_OVERFLOW,{ { kLeft, kExpr },{ kRight,kExpr } } }, \ | ||
{ LLIL_SYSCALL,{} }, \ | ||
{ LLIL_BP,{} }, \ | ||
{ LLIL_TRAP,{ { kVector, kInt } } }, \ | ||
{ LLIL_UNDEF,{} }, \ | ||
{ LLIL_UNIMPL,{} }, \ | ||
{ LLIL_UNIMPL_MEM,{ { kSrc, kExpr } } }, \ | ||
{ LLIL_SET_REG_SSA,{ { kDest, kRegSsa },{ kSrc,kExpr } } }, \ | ||
{ LLIL_IF,{ { kFullReg, kRegSsa },{ kDest,kReg },{ kSrc,kExpr } } }, \ | ||
{ LLIL_SET_REG_SPLIT_SSA,{ { kHi, kExpr },{ kLow,kExpr },{ kSrc,kExpr } } }, \ | ||
{ LLIL_REG_SPLIT_DEST_SSA,{ { kDest, kRegSsa } } }, \ | ||
{ LLIL_REG_SSA,{ { kSrc, kRegSsa } } }, \ | ||
{ LLIL_REG_SSA_PARTIAL,{ { kFullReg, kRegSsa },{ kSrc,kReg } } }, \ | ||
{ LLIL_SET_FLAG_SSA,{ { kDest, kFlagSsa },{ kSrc,kExpr } } }, \ | ||
{ LLIL_FLAG_SSA,{ { kSrc, kFlagSsa } } }, \ | ||
{ LLIL_FLAG_BIT_SSA,{ { kSrc, kFlagSsa },{ kBit, kInt } } }, \ | ||
{ LLIL_CALL_SSA,{ { kOutput, kExpr },{ kDest,kExpr },{ kStack,kExpr },{ kParam,kExpr } } }, \ | ||
{ LLIL_SYSCALL_SSA,{ { kOutput, kExpr },{ kStack,kExpr },{ kParam,kExpr } } }, \ | ||
{ LLIL_CALL_OUTPUT_SSA,{ { kDestMemory, kInt },{ kDest, kRegSsaList } } }, \ | ||
{ LLIL_CALL_STACK_SSA,{ { kSrc, kRegSsa },{ kSrcMemory, kInt } } }, \ | ||
{ LLIL_CALL_PARAM_SSA,{ { kSrc, kRegSsaList } } }, \ | ||
{ LLIL_LOAD_SSA,{ { kSrc, kExpr },{ kSrcMemory, kInt } } }, \ | ||
{ LLIL_STORE_SSA,{ { kDest, kExpr },{ kDestMemory,kInt },{ kSrcMemory,kInt },{ kSrc,kExpr } } }, \ | ||
{ LLIL_REG_PHI,{ { kDest, kRegSsa },{ kSrc, kRegSsaList } } }, \ | ||
{ LLIL_FLAG_PHI,{ { kDest, kFlagSsa },{ kSrc, kFlagSsaList } } }, \ | ||
{ LLIL_MEM_PHI,{ { kDestMemory, kInt },{ kSrcMemory, kIntList } } }, \ | ||
}; | ||
|
||
|
||
class LlilParser | ||
{ | ||
|
||
public: | ||
LlilParser(BinaryView *bv); | ||
const std::string getLowLevelILOperationName(const BNLowLevelILOperation id) const; | ||
void decodeIndexInFunction(uint64_t functionAddress, int indexIl); | ||
void decodeWholeFunction(uint64_t functionAddress); | ||
void decodeWholeFunction(BinaryNinja::Function *function); | ||
private: | ||
void showIndent() const; | ||
void analysisInstruction(const BNLowLevelILInstruction& insn); | ||
|
||
BinaryView *m_bv; | ||
std::vector<BinaryNinja::Ref<BinaryNinja::Function>> m_currentFunction; | ||
int m_tabs; | ||
size_t m_currentInstructionId; | ||
}; | ||
|
||
|
||
#endif /* __LOWLEVEL_IL_PARSER_H_ */ |
Oops, something went wrong.