Saustin
Saustin

Reputation: 1147

Retrieve ack after syn

I've coded a small tool which just throws a syn packet at any ip and port number you give it -- and when I popped up Wireshark, the sent packet appears fine, no errors or anything, it looks just like your typical TCP SYN packet.

For some reason, the ACK isn't sent by the server. So, there's two problems; one, no ACK response. Two, I don't even know how to receive the ack response via my program (bind()?).

I modified some code from a syn flooder I found online because it seemed like to me some script-kiddie code would be easy to follow, but I'm afraid it may be missing something, and may be the result of the server's ACK denial. The code has been modified so the syn request is sent from the legitimate IP address. The following code shows my ip+tcp headers:

 iph->ihl = 5;
 iph->version = 4;
 iph->tos = 0;
 iph->tot_len = sizeof (struct ip) + sizeof (struct tcphdr);
 iph->id = htonl (54321); //Id of this packet
 iph->frag_off = 0;
 iph->ttl = 255;
 iph->protocol = 6;
 iph->check = 0;  //Set to 0 before calculating checksum
 iph->saddr = 0; //Source ip filled in by kernel
 iph->daddr = sin.sin_addr.s_addr;

 //TCP Header
 tcph->source = htons (9999);
 tcph->dest = htons (atoi(argv[2]));
 tcph->seq = random ();
// tcph->ack_seq = 0;
 tcph->doff = 5;  /* first and only tcp segment */
 tcph->syn = 1;
 tcph->window = htonl (65555); /* maximum allowed window size */
 tcph->check = 0;/* if you set a checksum to zero, your kernel's IP stack
    should fill in the correct checksum during transmission */
 tcph->urg_ptr = 0;
 //Now the IP checksum
 iph->check = csum ((unsigned short *) datagram, iph->tot_len >> 1);

So, I send that, no ack back. What am I missing?

Upvotes: 1

Views: 786

Answers (2)

shubendrak
shubendrak

Reputation: 2068

you have not written the whole code. there may be area which you would be missing something.

this code will help you.

#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<errno.h>
#include<netinet/tcp.h>
#include<netinet/ip.h>

struct pseudo_header
{
u_int32_t source_address;
u_int32_t dest_address;
u_int8_t placeholder;
u_int8_t protocol;
u_int16_t tcp_length;
};

unsigned short csum(unsigned short *ptr,int nbytes) 
{
register long sum;
unsigned short oddbyte;
register short answer;

sum=0;
while(nbytes>1) {
    sum+=*ptr++;
    nbytes-=2;
}
if(nbytes==1) {
    oddbyte=0;
    *((u_char*)&oddbyte)=*(u_char*)ptr;
    sum+=oddbyte;
}

sum = (sum>>16)+(sum & 0xffff);
sum = sum + (sum>>16);
answer=(short)~sum;

return(answer);
}

int main (void)
{
int s = socket (AF_INET, SOCK_RAW, IPPROTO_TCP);

if(s == -1) {
    perror("Failed to create socket");
    exit(1);
}
char datagram[4096] , source_ip[32] , *data , *pseudogram;
char buffer[4096];

memset (datagram, 0, 4096);

struct iphdr *iph = (struct iphdr *) datagram;
struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct iphdr));

struct sockaddr_in sin;
struct pseudo_header psh;

data = datagram + sizeof(struct iphdr) + sizeof(struct tcphdr);
strcpy(data , "ABCDEFGHIJKLMNOPQRSTUVWXYZ");

strcpy(source_ip , "127.0.0.1");

sin.sin_family = AF_INET;
sin.sin_port = htons(55559);
sin.sin_addr.s_addr = inet_addr ("127.0.0.1");

iph->ihl = 5;
iph->version = 4;
iph->tos = 0;
iph->tot_len = sizeof (struct iphdr) + sizeof (struct tcphdr) + strlen(data);
iph->id = htonl (54351);
iph->frag_off = 0;
iph->ttl = 255;
iph->protocol = IPPROTO_TCP;
iph->check = 0;
iph->saddr = inet_addr ( source_ip );
iph->daddr = sin.sin_addr.s_addr;
iph->check = csum ((unsigned short *) datagram, iph->tot_len);

tcph->source = htons (55554);
tcph->dest = sin.sin_port;
tcph->seq = htonl(4362);
tcph->ack_seq = htonl(0);
tcph->doff = 5;
tcph->fin=0;
tcph->syn=1;
tcph->rst=0;
tcph->psh=0;
tcph->ack=0;
tcph->urg=0;
tcph->window = 1;
tcph->check = 0;    
tcph->urg_ptr = 0;

psh.source_address = inet_addr( source_ip );
psh.dest_address = sin.sin_addr.s_addr;
psh.placeholder = 0;
psh.protocol = IPPROTO_TCP;
psh.tcp_length = htons(sizeof(struct tcphdr) + strlen(data) );

int psize = sizeof(struct pseudo_header) + sizeof(struct tcphdr) + strlen(data);
pseudogram = malloc(psize);

memcpy(pseudogram , (char*) &psh , sizeof (struct pseudo_header));
memcpy(pseudogram + sizeof(struct pseudo_header) , tcph , sizeof(struct tcphdr) + strlen(data));

tcph->check = csum( (unsigned short*) pseudogram , psize);

int one = 1;
const int *val = &one;

if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0)
{
    perror("Error setting IP_HDRINCL");
    exit(0);
}
sendto (s, datagram, iph->tot_len , 0, (struct sockaddr *) &sin, sizeof (sin));
return 0;

}

Upvotes: 0

SKi
SKi

Reputation: 8476

The line:

   tcph->window = htonl (65555);

may cause problems. Because 65555 is bigger than 0xFFFF. The window field size is 16 bits.

So this could be better:

   tcph->window = htons (65535);

Notice: htonl was changed to htons.

Edit:

Or even more better (if the contant is available):

   tcph->window = htons (TCP_MAXWIN);

Problem can be also in lack of TCP checksum counting. Your code assumes that lower layers updates the TCP checksum field. Because all network interface cards does not support TCP checksum offload, the code may not work in every host.

Upvotes: 3

Related Questions