PIN me if you can
Or how to escape PIN in 5 instructions, using the self-modification technique seen in the previous post. Ready ? Go:
#include <stdio.h>
main() {
asm("call foo\n\t"
"foo: pop %rax\n\t"
"movl $0x4004e7, 10(%eax)\n\t" // put @nottraced() in the next mov
"movl $0x4004fb, %eax\n\t" // @traced(), will be overwritten
// by @nottraced() if not instrumented
"call *%rax\n\t");
}
// we don't want PIN to analyse this
nottraced() {
printf("trace me if you can!\n");
}
// we want PIN to analyse this, a dummy function
traced() {
printf("you're not supposed to get here\n");
}
As usual: compile, make the .text section and the program header writable, and run.
reynaudd@lhs-2:~/test/packed$ ./escape2 trace me if you can!
reynaudd@lhs-2:~/test/packed$ pin -t ../pin-2.5-24110-gcc.4.0.0-ia32_intel64-linux/source/tools/ManualExamples/obj-intel64/inscount0.so -- ./escape2 you're not supposed to get here
‘Nuff said.
UPDATE: as the authors of PIN pointed out, this situation in handled correctly by PIN with the option -smc_strict. That’s because for performance reasons (and standards compliance), PIN makes the assumption that there is at least a taken branch between a modification of the code and its execution (i.e. no basic block modifies itself). My example violates this assumption.