Alex Balgavy

Just some stuff about me.

Here's my dotfiles repository.

Check out my blog.

My keys: PGP, SSH

My crypto wallets (BTC, XMR)


What links here:

Analysis with Intel Pin

Analysis with Intel Pin

First you need to install Intel Pin under $PIN_ROOT.

Then, create a makefile like

ifdef PIN_ROOT
CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config
else
CONFIG_ROOT := ../Config
endif

include $(CONFIG_ROOT)/makefile.config
TOOL_CXXFLAGS := $(filter-out -Werror, $(TOOL_CXXFLAGS))
TOOL_CXXFLAGS += -g
TEST_TOOL_ROOTS := analyzer
TEST_ROOTS :=
TOOL_ROOTS :=
SA_TOOL_ROOTS :=
APP_ROOTS :=
OBJECT_ROOTS :=
DLL_ROOTS :=
LIB_ROOTS :=
SANITY_SUBSET := $(TEST_TOOL_ROOTS) $(TEST_ROOTS)

include $(TOOLS_ROOT)/Config/makefile.default.rules

To make and run:

make
$PIN_ROOT/pin -t obj-intel64/analyzer.so -- ./binary somearg

Adding functions:

#include "pin.H"
int main (int argc, char *argv[]) {
    PIN_InitSymbolsAlt(IFUNC_SYMBOLS);
    if (PIN_Init(argc, argv))
        return 1;

    // Add an instrumentation function on trace level (e.g. to instrument instructions)
    TRACE_AddInstrumentFunction(Trace, 0);

    // Add instrumentation function in image level (e.g. to instrument library calls)
    IMG_AddInstrumentFunction(ImageLoad, 0);

    // Hook syscall entry and exit
    PIN_AddSyscallEntryFunction(&syscall_entry, NULL);
    PIN_AddSyscallExitFunction(&syscall_exit, NULL);

    // Add a function to run at the very end
    PIN_AddFiniFunction(Fini, 0);

    // Run the tool
    PIN_StartProgram();
}

Hooking library function calls at image load:

// Callback for memset
static inline void before_memset(char *dest, int c, size_t n) {
    printf("Setting %d bytes at %p to %x\n", n, dest, c);
}

// Callback for strcmp
static inline void before_strcmp(char *s1, char *s2) {
    printf("Comparing %s to %s\n", s1, s2);
}


void ImageLoad(IMG img, void *) {
    RTN rtn = RTN_FindByName(img, "memset");
    if (RTN_Valid(rtn)) {
        RTN_Open(rtn);
        // Add a call before the function
        RTN_InsertCall(rtn, IPOINT_BEFORE,
                       (AFUNPTR)before_memset,
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 0, // dst
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 1, // source constant
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 2, // size
                       IARG_END);
        RTN_Close(rtn);
    }

    rtn = RTN_FindByName(img, "strcmp");
    if (RTN_Valid(rtn)) {
        RTN_Open(rtn);
        RTN_InsertCall(rtn, IPOINT_BEFORE,
                       (AFUNPTR)before_strcmp,
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 0, // string s1
                       IARG_FUNCARG_ENTRYPOINT_VALUE, 1, // string s2
                       IARG_END);
        RTN_Close(rtn);
    }
}

Instrumenting instructions:

static inline void handle_indirect_call(ADDRINT ip, ADDRINT value, std::string ass) {
    printf("%lx: call to %lx. asm %s", ip, value, ass.c_str());
}

// Process an instruction
void Instrument(INS ins, void *) {
    if (INS_IsCall(ins) && INS_IsIndirectControlFlow(ins)) {
        // If it's an indirect call, print out the actual branch target
        INS_InsertCall(ins, IPOINT_BEFORE,
                       (AFUNPTR) handle_indirect_call,
                       IARG_INST_PTR,
                       IARG_BRANCH_TARGET_ADDR,
                       IARG_PTR, new std::string(INS_Disassemble(ins)),
                       IARG_END);
    }

    // Act based on opcode
    xed_iclass_enum_t ins_opcode = (xed_iclass_enum_t)INS_Opcode(ins);
    switch (ins_opcode) {
    case XED_ICLASS_CMP:
        // cmp CONSTANT,val
        if (INS_OperandIsImmediate(ins, 0)) {
            if (INS_OperandIsMemory(ins, 1)) {
                INS_InsertCall(ins, IPOINT_BEFORE,
                               (AFUNPTR)handle_cmp_mem_imm,
                               IARG_UINT32, INS_OperandWidth(ins, 1)/8,
                               IARG_MEMORYREAD_EA,
                               IARG_UINT64, INS_OperandImmediate(ins, 0),
                               IARG_PTR, new std::string(INS_Disassemble(ins)),
                               IARG_INST_PTR,
                               IARG_END);
            }
            else if (INS_OperandIsReg(ins, 1)) {
                INS_InsertCall(ins, IPOINT_BEFORE,
                               (AFUNPTR)handle_cmp_reg_imm,
                               IARG_UINT32, getRegSize(INS_OperandReg(ins, 1)),
                               IARG_UINT32, getTaintReg(INS_OperandReg(ins, 1)),
                               IARG_REG_VALUE, INS_OperandReg(ins, 1),
                               IARG_UINT64, INS_OperandImmediate(ins, 0),
                               IARG_PTR, new std::string(INS_Disassemble(ins)),
                               IARG_INST_PTR,
                               IARG_END);
            }
        }
        break;
    }
}

void Trace(TRACE trace, void *) {
    /* Iterate through the basic blocks which PIN wants to instrument right now. */
    for (BBL bbl = TRACE_BblHead(trace); BBL_Valid(bbl); bbl = BBL_Next(bbl)) {
        IMG img = IMG_FindByAddress(BBL_Address(bbl));
        if (!IMG_Valid(img) || !IMG_IsMainExecutable(img))
            continue;

        /* Instrument every instruction in this basic block. */
        for (INS ins = BBL_InsHead(bbl); INS_Valid(ins); ins = INS_Next(ins)) {
            Instrument(ins, 0);
        }
    }
}

Useful resources: