23

Pintool: tracking 'CALL 0' and 'JMP 0' instructi...

 3 years ago
source link: https://yurichev.com/news/20200726_pintool_call0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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.

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.

Please drop me email about bug(s) and/or suggestion(s): [email protected]


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK