#include #include #include #include double func_over_signal_thrower (double, float, const char *); int signal_thrower (int); void handler (int); int func_over_mov_imm32_addr_in_prologue (int); int mov_imm32_reg_in_prologue (int); int func_under_mov_imm32_reg_in_prologue (int); double func_over_cmpl_in_prologue (double, float); int cmpl_in_prologue (void); int func_under_cmpl_in_prologue (int); char *func_over_objc_msgForward_pattern (char *); int objc_msgForward_pattern (int); int func_under_objc_msgForward_pattern (int); main (int argc, char **argv, char **envp) { int ret; char *sret; ret = func_over_signal_thrower (argc * 5.2, argc * 9999.33, argv[0]); printf ("%d\n", ret); ret = func_over_mov_imm32_addr_in_prologue (argc * 2); printf ("%d\n", ret); ret = func_over_cmpl_in_prologue (5, 10); printf ("%d\n", ret); char buf [80]; strcpy (buf, "hummingbirds are cool"); sret = func_over_objc_msgForward_pattern (buf); printf ("%s\n", sret); } /* Throw a signal while down on the stack, make sure we can find our way through _sigtramp() and get all the necessary information out of the sigcontext struct to backtrace our way out. */ double func_over_signal_thrower (double d, float f, const char *s) { int c = d * f; c += s[0]; f = f * c; c -= signal_thrower (c); return (d * f) / c; } int signal_thrower (int in) { in--; signal (SIGALRM, handler); alarm (1); sleep (2); in = in - 2; return in; } void handler (int sig) { signal (sig, handler); } /* mov imm32, reg in a prologue. e.g. mov $0xffffffce,%eax reg can be e[abcd]x. Bytes are 0xb[8-b] 4-byte-immediate value. From _ZN18MacFile_DataSource10WriteBytesEtxmPKvPm() aka MacFile_DataSource::WriteBytes(unsigned short, long long, unsigned long, void const*, unsigned long*) in /System/Library/Frameworks/AudioToolbox.framework/Versions/A/AudioToolbox */ int func_over_mov_imm32_addr_in_prologue (int in) { in *= in; in = mov_imm32_reg_in_prologue (in); return in; } asm(".text\n" " .align 8\n" "_mov_imm32_reg_in_prologue:\n" " push %ebp\n" " mov $0xffffffce,%eax\n" " mov %esp,%ebp\n" " sub $0x18,%esp\n" " mov 0x8(%ebp),%eax\n" " addl $0x99,%eax\n" " mov %eax,(%esp)\n" " call _func_under_mov_imm32_reg_in_prologue\n" " mov %eax,0x8(%ebp)\n" " leave\n" " ret\n"); int func_under_mov_imm32_reg_in_prologue (int in) { in /= 2; return in + 5; } /* `cmp imm32,m32' in a prologue, e.g. cmpl $0x0,0xc03a4254 Bytes are 0x83 4-byte-imm 4-byte-addr From Debugger() in xnu. */ double func_over_cmpl_in_prologue (double d, float f) { double c = d * f; c = c * cmpl_in_prologue (); return c; } asm(".text\n" " .align 8\n" "_cmpl_in_prologue:\n" " push %ebp\n" " cmpl $0x0,_main\n" " mov %esp,%ebp\n" " push %ebx\n" " mov $0x5,%eax\n" " push %eax\n" " call _func_under_cmpl_in_prologue\n" " pop %ebx\n" " pop %ebx\n" " pop %ebp\n" " ret\n"); int func_under_cmpl_in_prologue (int in) { in++; in++; return in + 4; } char * func_over_objc_msgForward_pattern (char * in) { int len = strlen (in); char *p; p = &in[objc_msgForward_pattern (3) % len]; return p; } /* objc_msgForward () has some hand-written assembly at the front as a little optimization. So we'll need to recognize that. cmp $0x0,%edx [ 0x83 0xfa 0x00 ] je _objc_msgForward+89 [ 0x74 0x54 ] This function is in /usr/lib/libobjc.dylib. */ asm(".text\n" " .align 8\n" "_objc_msgForward_pattern:\n" " cmp $0x0, %edx\n" " je LM1\n" "LM1:\n" " push %ebp\n" " mov %esp, %ebp\n" " sub $4, %esp\n" " movl $99, (%esp)\n" " call _func_under_objc_msgForward_pattern\n" " add $4, %esp\n" " pop %ebp\n" " ret\n"); int func_under_objc_msgForward_pattern (int in) { in += 10; return in; }