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

Yes, I know about these lousy Disqus ads. Please use adblocker. I would consider to subscribe to 'pro' version of Disqus if the signal/noise ratio in comments would be good enough.