网络层代码
针对IP协议以及网络层其他协议的攻击繁多。由于属于无连接协议,不提供认证功能,因此比较容易受到攻击。IP不是唯一受攻击目标,ICMP是另一个潜在的攻击目标。
用winpcap发送syn数据包
函数说明
Mktcphrd函数用于构造TCP头。
入参为发送数据的结构体,源IP,目的IP,源端口和目的端口。
构造tcp报头中的相关参数。和ip报头中的相关值。
Mkiphrd函数用于构造IP头。入参为IP头结构,源IP和目的IP。
Checksum函数用于生成校验和。把IP头自己都加起来,然后右移16位, 与0xffff得到计算值后再加上右移16位。
主函数逻辑过程:
创建一个素组大小1024个字节,创建一个结构体SYN_DATA,包含TCP和IP头。
(在以太网发送,所以必须有以太网头的,结构体为ETHER_HEADER)
发送端IP为 192.168.1.4,接收端IP为192.168.1.5
通过pcap_findalldevs函数来寻找网卡。
然后将以太网头加入到要发送的字符串中,
接着将SYN_DATA(TCP和IP头)加入到要发送的字符串中。
最后将一个字符串“Just a Test!”复制到要发送的字符串中。
答应要发送的总字节数量为66.
以太网头:14自己
IP头: 20字节
TCP头:20字节
字符串:12字节
合计刚好是66个字节。
源码
如下:
#include<stdlib.h>
#include<stdio.h>
#include<winsock2.h>
#include<pcap.h>
#pragmacomment(lib,"wpcap.lib")
#pragmacomment(lib,"ws2_32.lib")
typedefstruct _ETHER_HEADER{
u_char ether_dhost[6];
u_char ether_shost[6];
u_short ether_type; //如果上一层为IP协议。则ether_type的值就是0x0800
} ETHER_HEADER;
//IP报头格式 ,共20个字节
typedefstruct_IP_HEADER
{
unsignedchar h_lenver;
unsignedchar tos;
unsignedshort total_len;
unsignedshort ident;
unsignedshort frag_and_flags;
unsignedchar ttl;
unsignedchar proto;
unsignedshort checksum;
unsignedint sourceIP;
unsignedint destIP;
} IP_HEADER;
//TCP报头格式
typedefstruct_TCP_HEADER
{
USHORT th_sport;
USHORT th_dport;
unsignedintth_seq;
unsignedintth_ack;
unsignedcharth_lenres;
unsignedcharth_flag;
USHORT th_win;
USHORT th_sum;
USHORT th_urp;
} TCP_HEADER;
//发送数据格式
typedefstruct_SYN_DATA
{
IP_HEADER iphrd;
TCP_HEADER tcphrd;
}SYN_DATA;
//校验和算法
USHORTchecksum(USHORT *buffer, intsize)
{
unsignedlongcksum = 0;
while (size > 1)
{
cksum+= *buffer++;
size -= sizeof(USHORT);
}
if (size)
{
cksum+= *(UCHAR*)buffer;
}
cksum= (cksum >> 16) + (cksum & 0xffff);
cksum+= (cksum >>16);
return (USHORT)(~cksum);
}
//构造IP头
intmkiphrd(IP_HEADER*ip, unsignedlongsip, unsignedlongdip)
{
ip->h_lenver = (4<<4|5);
ip->tos = 0;
ip->total_len = sizeof(SYN_DATA);
ip->ident = 0;
ip->frag_and_flags = 0;
ip->ttl = 64;
ip->proto = 6;
ip->checksum = 0;
ip->destIP = dip;
ip->sourceIP = sip;
ip->checksum = checksum((USHORT *)&ip, sizeof(IP_HEADER));
return 1;
}
//构造TCP头
intmktcphrd(SYN_DATA*syndata, unsignedlongsip, unsignedlongdip, intsport, intdport)
{
syndata->tcphrd.th_sport = sport;
syndata->tcphrd.th_dport = dport;
syndata->tcphrd.th_seq = 1001;
syndata->tcphrd.th_ack = 0;
syndata->tcphrd.th_lenres = 5<<4;
syndata->tcphrd.th_flag = 2;
syndata->tcphrd.th_win = htons(16384);
syndata->tcphrd.th_sum = 0;
syndata->tcphrd.th_urp = 0;
//构造伪报头---关键,以此生成TCP校验和
syndata->iphrd.ttl = 0;
syndata->iphrd.proto =6;
syndata->iphrd.sourceIP = sip;
syndata->iphrd.destIP = dip;
syndata->iphrd.checksum = htons(sizeof(TCP_HEADER));
syndata->tcphrd.th_sum = checksum((USHORT *)(&(syndata->iphrd.ttl)), sizeof(TCP_HEADER)+12);
return 1;
}
intmain(intargc, char **argv)
{
pcap_t *fp;
char errbuf[1024] = {0};
u_char packet[1024];
SYN_DATA sendbuf; //将要发送的数据包(TCP\IP头)
ETHER_HEADER ethbuf;
int sendsize=0;
int iSendNum ;
char data[20] = "Just a Test!";
pcap_if_t *alldevs;
pcap_if_t *d;
int nSendByte;
char *destip = "192.168.1.5";
int destport = 2988;
char *sourceip = "192.168.1.4";
int sourceport = 2987;
memset(&packet, 0, sizeofpacket );
//构造发送数据
memset((void *)&sendbuf, 0, sizeof sendbuf);
mktcphrd(&sendbuf, inet_addr(sourceip), inet_addr(destip), htons(sourceport), htons(destport));
mkiphrd(&(sendbuf.iphrd), inet_addr(sourceip), inet_addr(destip));
sendbuf.iphrd.checksum= checksum((USHORT *)&sendbuf, sizeof(IP_HEADER)+sizeof(TCP_HEADER));
/* Retrieve the device list */
if(pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs:%s\n", errbuf);
exit(1);
}
/* Scan the list printing every entry */
//每个网卡都发送
for(d=alldevs;d;d=d->next)
{
/* Open the adapter */
if ((fp = pcap_open_live(d->name, // name of the device
65536,// portion of the packet to capture. It doesn't matter in this case
1,// promiscuous mode (nonzero means promiscuous)
1000,// read timeout
errbuf// error buffer
))== NULL)
{
fprintf(stderr,"\nUnable to open theadapter. %s is not supported by WinPcap\n",sourceip);
break;
}
//目的主机Mac地址,是我本机MAC
ethbuf.ether_dhost[0]= 0x00;
ethbuf.ether_dhost[1]= 0xff;
ethbuf.ether_dhost[2]= 0xde;
ethbuf.ether_dhost[3]= 0x28;
ethbuf.ether_dhost[4]= 0x57;
ethbuf.ether_dhost[5]= 0x6d;
//源主机Mac,也是我本机mac
ethbuf.ether_shost[0]= 0x00;
ethbuf.ether_shost[1]= 0xff;
ethbuf.ether_shost[2]= 0xde;
ethbuf.ether_shost[3]= 0x28;
ethbuf.ether_shost[4]= 0x57;
ethbuf.ether_shost[5]= 0x6d;
ethbuf.ether_type= htons(0x0800);
memcpy(packet,ðbuf, sizeof(ethbuf)) ;
sendsize+= sizeof(ethbuf) ;
memcpy(packet+sendsize,&sendbuf, sizeof(sendbuf)) ;
sendsize+= sizeof(sendbuf) ;
memcpy(packet+sendsize,data, sizeof(data)) ;
/* Send down the packet */
nSendByte= sendsize + strlen( data );
printf("%d\n", nSendByte );
for(iSendNum = 0; iSendNum <1; ++iSendNum)
{
if (pcap_sendpacket(fp, //Adapter
packet,// buffer with the packet
100// size
)!= 0)
{
pcap_close(fp);
break;
}
}
printf("send sucess!\n");
pcap_close(fp);
}
system("pause");
return 0;
}
抓包
使用Wireshark抓包内容如下:
发现直接数据其实是46个字节,这是因为归档至少46个字节。