Jurriaan Bremer has published a very interesting article titled "Abusing Forced Inline in C".
Here's his "Inserting Garbage" sample with some minor changes for GCC compatibility:
#include <stdio.h> int foo(int a, int b) { return a + b; } __attribute__((always_inline)) int foo_obfuscated(int a, int b) { __asm__ ("jmp 1f"); __asm__ (".byte 0xb8"); __asm__ ("1:"); int ret = foo(a, b); __asm__ ("jmp 2f"); __asm__ (".byte 0xb8"); __asm__ ("2:"); return ret; } #define foo foo_obfuscated int main(void) { printf("foo(2, 3): %d\n", foo(2, 3)); }And it's effect on the assembly (i386 binary disassembled using otx) :
With "evil" opcode (0xb8) | With NOP |
_foo_obfuscated: 00001ec0 pushl %ebp 00001ec1 movl %esp,%ebp 00001ec3 subl $0x28,%esp 00001ec6 movl 0x0c(%ebp),%eax 00001ec9 movl 0x08(%ebp),%ecx 00001ecc movl %ecx,0xfc(%ebp) 00001ecf movl %eax,0xf8(%ebp) 00001ed2 jmp 0x00001ed5 ======= opcode insertion point 00001ed4 movl $0x8bfc458b,%eax 00001ed9 decl %ebp 00001eda clc 00001edb movl %eax,(%esp) 00001ede movl %ecx,0x04(%esp) 00001ee2 calll 0x00001e90 00001ee7 movl %eax,0xec(%ebp) 00001eea jmp 0x00001eed 00001eec movl $0x89ec458b,%eax 00001ef1 incl %ebp 00001ef2 lock/movl 0xf0(%ebp),%eax 00001ef6 movl %eax,0xf4(%ebp) 00001ef9 movl 0xf4(%ebp),%eax 00001efc addl $0x28,%esp 00001eff popl %ebp 00001f00 ret 00001f01 nopl 0x00000000(%eax) 00001f08 nopl 0x00000000(%eax,%eax) |
_foo_obfuscated: 00001ec0 pushl %ebp 00001ec1 movl %esp,%ebp 00001ec3 subl $0x28,%esp 00001ec6 movl 0x0c(%ebp),%eax 00001ec9 movl 0x08(%ebp),%ecx 00001ecc movl %ecx,0xfc(%ebp) 00001ecf movl %eax,0xf8(%ebp) 00001ed2 jmp 0x00001ed5 ======= opcode insertion point 00001ed4 nop 00001ed5 movl 0xfc(%ebp),%eax 00001ed8 movl 0xf8(%ebp),%ecx 00001edb movl %eax,(%esp) 00001ede movl %ecx,0x04(%esp) 00001ee2 calll 0x00001e90 00001ee7 movl %eax,0xec(%ebp) 00001eea jmp 0x00001eed return; 00001eec nop 00001eed movl 0xec(%ebp),%eax 00001ef0 movl %eax,0xf0(%ebp) 00001ef3 movl 0xf0(%ebp),%eax 00001ef6 movl %eax,0xf4(%ebp) 00001ef9 movl 0xf4(%ebp),%eax 00001efc addl $0x28,%esp 00001eff popl %ebp 00001f00 ret 00001f01 nopl 0x00000000(%eax) 00001f08 nopl 0x00000000(%eax,%eax) |