Pintool: tracking 'CALL 0' and 'JMP 0' instruction

A nasty piece of software, resisting of analyzing, can crash itself by jumping to the address 0. And what can you do, if you can't find a function that it does? All you see in your debugger is EIP/RIP=0 and empty stack because ESP/RSP=(garbage), and there is nothing more that can help you. How distressing and frustrating is this.

There is a Pintool I wrote. It intercepts all 'CALL 0' and 'JMP 0' instructions and log their addresses. It uses excellent Intel Pin.

It can catch a code like:

int main()
{
        typedef void func(void);
        func* f = (func*)0;
        f();
};

... using:

...

VOID CALL_reg(ADDRINT ip, ADDRINT op, THREADID threadid)
{
        PIN_GetLock(&lock, threadid+1);
        log_info (ip, "CALL", op);
        PIN_ReleaseLock(&lock);
}

VOID CALL_mem(ADDRINT ip, ADDRINT *op_addr, unsigned int op_size, THREADID threadid)
{
        PIN_GetLock(&lock, threadid+1);
        ADDRINT op;
        PIN_SafeCopy(&op, op_addr, op_size);
        log_info (ip, "CALL", op);
        PIN_ReleaseLock(&lock);
};

...

// this function executed only during startup, so no need to optimize anything here:
VOID Instrument_all(INS ins, VOID* v)
{
        // CALL reg
        // N.B.: this doesn't work: if ((INS_Mnemonic(ins) == "CALL") && (INS_OperandIsReg(ins, 0)))
        if (INS_IsCall(ins) && (INS_OperandIsReg(ins, 0)))
        {
                INS_InsertCall(ins,
                        IPOINT_BEFORE,
                        AFUNPTR(CALL_reg),
                        IARG_INST_PTR,
                        IARG_REG_VALUE, REG(INS_OperandReg(ins, 0)),
                        IARG_THREAD_ID,
                        IARG_END);
        }

        // CALL mem
        if (INS_IsCall(ins) && INS_OperandIsMemory(ins, 0))
        {
                INS_InsertCall(ins,
                        IPOINT_BEFORE,
                        AFUNPTR(CALL_mem),
                        IARG_INST_PTR,
                        IARG_MEMORYREAD_EA,
                        IARG_MEMORYREAD_SIZE,
                        IARG_THREAD_ID,
                        IARG_END);
        }

...

Dunno why, but (INS_Mnemonic(ins) == "CALL") doesn't working, while (INS_Mnemonic(ins) == "JMP") does.

All the files. Both Windows and Linux.

Couple of more useful Pintools are in my book, including building manual.

UPD: At reddit


Please drop me email about bug(s) and/or suggestion(s): dennis@yurichev.com