1.课程设计要求:
发送和接收TCP数据包:TCP是一种面向连接的、可靠的传输层协议。TCP协议工作在网络层IP协议的基础上。本课程设计的目的是设计一个发送和接收TCP数据包的程序,其功能是填充一个TCP数据包,发送给目的主机,并在目的主机接收此TCP数据包,将数据字段显示在标准输出上。
2.设计原理
TCP位于IP层之上,应用层之下的传输层。不同主机的应用层之间经常需要可靠的、像管道一样的连接。而面向连接、提供可靠传输的TCP协议则正好能够满足这一需求。因此被广泛利用。ARP的发送和接收数据包利用winpcap实现编程,先获得本机设备列表,然后打开选中的适配器进行抓包,并获取获取IP和子网掩码,通过对ARP和以太网的首部进行填充来构建一个ARP请求报文,然后再将其捕获并解析,来获得本机的MAC物理地址。当于构造了一个外来的ARP请求,本机捕获到了请求,然后发送回应给对方的数据包也被本机捕获到了并解析出来了,解析了自己发出去的数据包。获取到了自身的MAC地址之后,就可以在本机上构建ARP广播请求,向局域网内的所有主机发送ARP请求,得到回应之后接收回应的数据包并进行解析,得到对方的MAC地址。
接下来进行发送和接收TCP数据包,让用户输入要发送的IP地址和要发送的数据,然后需要声明各种结构体,我们发送的是TCP数据,这样,TCP的TcpData 就作为真正的内容,然后在前面加上TCP头,IP头,帧头,还有校验和要正确,对各种结构体的数据进行初始化赋值,并计算校验和。最后构成一个完整的帧。使用winpcap中自带的pcap_sendpacket()函数将其发送出去,编写接收TCP程序,将其接收并解析出来。
3.主程序流程图
(1)发送和捕获ARP数据包流程图:

(2)发送和接收TCP数据包流程图:

4.核心代码:
1)发送和捕获ARP数据包:
①构建APR请求报文并自己捕获,获得主机的MAC地址:
int GetSelfMac(pcap_t *adhandle, const char *ip_addr, unsigned char *ip_mac) {
unsigned char sendbuf[42];
int i = -1;
int res;
EthernetHeader eh;
Arpheader ah;
struct pcap_pkthdr * pkt_header;
const u_char * pkt_data;
memset(eh.DestMAC, 0xff, 6);
memset(eh.SourMAC, 0x0f, 6);
memset(ah.DestMacAdd, 0x0f, 6);
memset(ah.SourceMacAdd, 0x00, 6);
eh.EthType = htons(ETH_ARP);
ah.HardwareType= htons(ARP_HARDWARE);
ah.ProtocolType = htons(ETH_IP);
ah.HardwareAddLen = 6;
ah.ProtocolAddLen = 4;
ah.SourceIpAdd = inet_addr("100.100.100.100");
ah.OperationField = htons(ARP_REQUEST);
ah.DestIpAdd = inet_addr(ip_addr);
memset(sendbuf, 0, sizeof(sendbuf));
memcpy(sendbuf, &eh, sizeof(eh));
memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
printf("%s",sendbuf);
if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
printf("\nPacketSend succeed\n");
} else {
printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
return 0;
}
while ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
if (*(unsigned short *) (pkt_data + 12) == htons(ETH_ARP)
&& *(unsigned short*) (pkt_data + 20) == htons(ARP_REPLY)
&& *(unsigned long*) (pkt_data + 38)
== inet_addr("100.100.100.100")) {
for (i = 0; i < 6; i++) {
ip_mac[i] = *(unsigned char *) (pkt_data + 22 + i);
}
printf("获取自己主机的MAC地址成功!\n");
break;
}
}
if (i == 6) {
return 1;
} else {
return 0;
}
}
②向局域网内所有可能的IP地址发送ARP请求包线程:
DWORD WINAPI SendArpPacket(LPVOID lpParameter)
{
sparam *spara = (sparam *) lpParameter;
pcap_t *adhandle = spara->adhandle;
char *ip = spara->ip;
unsigned char *mac = spara->mac;
char *netmask = spara->netmask;
printf("ip_mac:%02x-%02x-%02x-%02x-%02x-%02x\n", mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
printf("自身的IP地址为:%s\n", ip);
printf("地址掩码NETMASK为:%s\n", netmask);
printf("\n");
unsigned char sendbuf[42];
EthernetHeader eh;
Arpheader ah;
memset(eh.DestMAC, 0xff, 6);
memcpy(eh.SourMAC, mac, 6);
memcpy(ah.SourceMacAdd, mac, 6);
memset(ah.DestMacAdd, 0x00, 6);
eh.EthType = htons(ETH_ARP);
ah.HardwareType = htons(ARP_HARDWARE);
ah.ProtocolType = htons(ETH_IP);
ah.HardwareAddLen = 6;
ah.ProtocolAddLen = 4;
ah.SourceIpAdd = inet_addr(ip);
ah.OperationField = htons(ARP_REQUEST);
unsigned long myip = inet_addr(ip);
unsigned long mynetmask = inet_addr(netmask);
unsigned long hisip = htonl((myip & mynetmask));
for (int i = 0; i < HOSTNUM; i++) {
ah.DestIpAdd = htonl(hisip + i);
memset(sendbuf, 0, sizeof(sendbuf));
memcpy(sendbuf, &eh, sizeof(eh));
memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
} else {
printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
}
Sleep(50);
}
Sleep(1000);
flag = TRUE;
return 0;
}
③分析截留的数据包获取活动的主机IP地址
DWORD WINAPI GetLivePC(LPVOID lpParameter)
{
gparam *gpara = (gparam *) lpParameter;
pcap_t *adhandle = gpara->adhandle;
int res;
unsigned char Mac[6];
struct pcap_pkthdr * pkt_header;
const u_char * pkt_data;
while (true) {
if (flag) {
printf("获取MAC地址完毕,请输入你要发送对方的IP地址:\n");
break;
}
if ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
if (*(unsigned short *) (pkt_data + 12) == htons(ETH_ARP)) {
ArpPacket *recv = (ArpPacket *) pkt_data;
if (*(unsigned short *) (pkt_data + 20) == htons(ARP_REPLY)) {
printf("-------------------------------------------\n");
printf("IP地址:%d.%d.%d.%d MAC地址:",
recv->ah.SourceIpAdd & 255,
recv->ah.SourceIpAdd >> 8 & 255,
recv->ah.SourceIpAdd >> 16 & 255,
recv->ah.SourceIpAdd >> 24 & 255);
for (int i = 0; i < 6; i++) {
Mac[i] = *(unsigned char *) (pkt_data + 22 + i);
printf("%02x", Mac[i]);
}
printf("\n");
}
}
}
Sleep(10);
}
return 0;
}
2)发送和捕获ARP数据包:
①初始化TCP发送数据包并将其发送出去:
memset(ðernet, 0, sizeof(ethernet));
BYTE destmac[8];
destmac[0] = 0x00;
destmac[1] = 0x11;
destmac[2] = 0x22;
destmac[3] = 0x33;
destmac[4] = 0x44;
destmac[5] = 0x55;
memcpy(ethernet.DestMAC, destmac, 6);
BYTE hostmac[8];
hostmac[0] = 0x00;
hostmac[1] = 0x1a;
hostmac[2] = 0x4d;
hostmac[3] = 0x70;
hostmac[4] = 0xa3;
hostmac[5] = 0x89;
memcpy(ethernet.SourMAC, hostmac, 6);
ethernet.EthType = htons(0x0800);
memcpy(&SendBuffer, ðernet, sizeof(struct EthernetHeader));
ip.Version_HLen = 0x45;
ip.TOS = 0;
ip.Length = htons(sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
ip.Ident = htons(1);
ip.Flags_Offset = 0;
ip.TTL = 128;
ip.Protocol = 6;
ip.Checksum = 0;
ip.SourceAddr.byte1 = 127;
ip.SourceAddr.byte2 = 0;
ip.SourceAddr.byte3 = 0;
ip.SourceAddr.byte4 = 1;
ip.DestinationAddr.byte1 = ip1;
ip.DestinationAddr.byte2 = ip2;
ip.DestinationAddr.byte3 = ip3;
ip.DestinationAddr.byte4 = ip4;
memcpy(&SendBuffer[sizeof(struct EthernetHeader)], &ip, 20);
tcp.DstPort = htons(102);
tcp.SrcPort = htons(1000);
tcp.SequenceNum = htonl(11);
tcp.Acknowledgment = 0;
tcp.HdrLen = 0x50;
tcp.Flags = 0x18;
tcp.AdvertisedWindow = htons(512);
tcp.UrgPtr = 0;
tcp.Checksum = 0;
memcpy(&SendBuffer[sizeof(struct EthernetHeader) + 20], &tcp, 20);
ptcp.SourceAddr = ip.SourceAddr;
ptcp.DestinationAddr = ip.DestinationAddr;
ptcp.Zero = 0;
ptcp.Protcol = 6;
ptcp.TcpLen = htons(sizeof(struct TcpHeader) + strlen(TcpData));
char TempBuffer[65535];
memcpy(TempBuffer, &ptcp, sizeof(struct PsdTcpHeader));
memcpy(TempBuffer + sizeof(struct PsdTcpHeader), &tcp, sizeof(struct TcpHeader));
memcpy(TempBuffer + sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
tcp.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader), &tcp, sizeof(struct TcpHeader));
memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
memset(TempBuffer, 0, sizeof(TempBuffer));
memcpy(TempBuffer, &ip, sizeof(struct IpHeader));
ip.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct IpHeader));
memcpy(SendBuffer + sizeof(struct EthernetHeader), &ip, sizeof(struct IpHeader));
int size = sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData);
int result = pcap_sendpacket(adhandle, SendBuffer,size);
if (result != 0)
{
printf("Send Error!\n");
}
else
{
printf("发送TCP数据包.\n");
printf("目的端口:%d\n", ntohs(tcp.DstPort));
printf("源端口:%d\n", ntohs(tcp.SrcPort));
printf("序号:%d\n", ntohl(tcp.SequenceNum));
printf("确认号:%d\n", ntohl(tcp.Acknowledgment));
printf("首部长度:%d*4\n", tcp.HdrLen >> 4);
printf("标志位:0x%0x\n", ntohs(tcp.Flags));
printf("窗口大小:%d\n", ntohs(tcp.AdvertisedWindow));
printf("紧急指针:%d\n", ntohs(tcp.UrgPtr));
printf("检验和:%u\n", ntohs(tcp.Checksum));
printf("发送成功!\n");
}
free(TcpData);
}
return 0;
}
②捕获TCP数据包并将数据内容显示出来:
void ip_protool_packet_callback(u_char *argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
{
struct ip_header *ip_protocol;
u_int header_length = 0;
u_int offset;
u_char tos;
u_int16_t checksum;
u_int ip_len;
u_int ip_version;
TcpHeader *tcp;
u_short sport,dport;
ip_protocol = (struct ip_header *) (packet_content+14);
ip_len = (ip_protocol->Version_HLen & 0xf) *4;
ip_version = ip_protocol->Version_HLen>>4;
tcp = (TcpHeader *)((u_char *)ip_protocol+ip_len);
checksum =ntohs(ip_protocol->ip_checksum);
tos = ip_protocol->ip_tos;
offset = ntohs(ip_protocol->ip_off);
if(*(unsigned long*)(packet_content+30)==inet_addr("100.100.100.100")){
printf("检验和:%d\n",checksum);
printf("源IP地址:%s\n", inet_ntoa(ip_protocol->ip_souce_address));
printf("目的地址:%s\n", inet_ntoa(ip_protocol->ip_destination_address));
printf("---------TCP协议---------\n");
sport = ntohs( tcp->SrcPort );
dport = ntohs( tcp->DstPort );
printf("源端口:%d 目的端口:%d\n",sport,dport);
printf("序号:%d\n",ntohl(tcp->SequenceNum));
printf("确认号:%d\n",ntohl(tcp->Acknowledgment));
printf("偏移地址(首部长度):%d\n",(tcp->HdrLen>>4)*4);
printf("标志位:%d\n",tcp->Flags);
printf("紧急UGR:%d\n",(tcp->Flags & 0x20)/32);
printf("确认ACK:%d\n",(tcp->Flags & 0x10)/16);
printf("推送PSH:%d\n",(tcp->Flags & 0x08)/8);
printf("复位RST:%d\n",(tcp->Flags & 0x04)/4);
printf("同步SYN:%d\n",(tcp->Flags & 0x02)/2);
printf("终止FIN:%d\n",tcp->Flags & 0x01);
printf("窗口大小:%d\n",ntohs(tcp->AdvertisedWindow));
printf("校验和:%d\n",ntohs(tcp->Checksum));
printf("紧急指针:%d\n",ntohs(tcp->UrgPtr));
char * data;
data = (char *)((u_char *)tcp+20);
printf("---------数据部分---------\n");
printf("数据部分:%s\n",data);
}
}
5.结果及分析
1、运行结果:
获得本地网卡并选择适配器:

发送ARP请求报文并将其捕获,获取本地MAC地址:

在本机上构建ARP广播请求,向局域网内的所有主机发送ARP请求,得到回应之后解析回应的数据包并进行解析,得到本局域网内所有的MAC地址:

输入要发送的IP地址和数据内容,发送成功:

在接收程序端捕获该数据报内容并显示出来:

2.分析
通过观察实验结果可以发现发送ARP请求报文并被自己捕获到后得到了正确的本机MAC地址,在本机上构建ARP广播请求,向局域网内的所有主机发送ARP请求,得到回应之后解析回应的数据包并进行解析,得到本局域网内所有的MAC地址。在发送端输入要发送的IP地址和数据内容后TCP报文发送成功,并可在接收端显示出来,成功达到实验目的。
6.完整代码如下:
6.1发送与接收ARP包发送TCP数据
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#define ETH_ARP 0x0806
#define ARP_HARDWARE 1
#define ETH_IP 0x0800
#define ARP_REQUEST 1
#define ARP_REPLY 2
#define HOSTNUM 255
char *iptos(u_long in);
void ifget(pcap_if_t *d, char *ip_addr, char *ip_netmask);
int GetSelfMac(pcap_t *adhandle, const char *ip_addr, unsigned char *ip_mac);
unsigned short checksum(unsigned short *data, int length);
DWORD WINAPI SendArpPacket(LPVOID lpParameter);
DWORD WINAPI GetLivePC(LPVOID lpParameter) ;
bool flag;
HANDLE sendthread;
HANDLE recvthread;
#pragma pack(1)
struct EthernetHeader
{
u_char DestMAC[6];
u_char SourMAC[6];
u_short EthType;
};
struct Arpheader {
unsigned short HardwareType;
unsigned short ProtocolType;
unsigned char HardwareAddLen;
unsigned char ProtocolAddLen;
unsigned short OperationField;
unsigned char SourceMacAdd[6];
unsigned long SourceIpAdd;
unsigned char DestMacAdd[6];
unsigned long DestIpAdd;
};
struct ArpPacket {
EthernetHeader ed;
Arpheader ah;
};
struct sparam {
pcap_t *adhandle;
char *ip;
unsigned char *mac;
char *netmask;
};
struct gparam {
pcap_t *adhandle;
};
struct sparam sp;
struct gparam gp;
struct IpAddress
{
u_char byte1;
u_char byte2;
u_char byte3;
u_char byte4;
};
struct IpHeader
{
unsigned char Version_HLen;
unsigned char TOS;
short Length;
short Ident;
short Flags_Offset;
unsigned char TTL;
unsigned char Protocol;
short Checksum;
IpAddress SourceAddr;
IpAddress DestinationAddr;
};
struct TcpHeader
{
unsigned short SrcPort;
unsigned short DstPort;
unsigned int SequenceNum;
unsigned int Acknowledgment;
unsigned char HdrLen;
unsigned char Flags;
unsigned short AdvertisedWindow;
unsigned short Checksum;
unsigned short UrgPtr;
};
struct PsdTcpHeader
{
IpAddress SourceAddr;
IpAddress DestinationAddr;
char Zero;
char Protcol;
unsigned short TcpLen;
};
int main(){
char *ip_addr;
char *ip_netmask;
unsigned char *ip_mac;
ip_addr = (char *) malloc(sizeof(char) * 16);
if (ip_addr == NULL)
{
printf("申请内存存放IP地址失败!\n");
return -1;
}
ip_netmask = (char *) malloc(sizeof(char) * 16);
if (ip_netmask == NULL)
{
printf("申请内存存放NETMASK地址失败!\n");
return -1;
}
ip_mac = (unsigned char *) malloc(sizeof(unsigned char) * 6);
if (ip_mac == NULL)
{
printf("申请内存存放MAC地址失败!\n");
return -1;
}
pcap_if_t * alldevs;
pcap_if_t *d;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t *adhandle;
int i = 0;
if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errbuf) == -1){
fprintf(stderr,"Error in pcap_findalldevs_ex:\n",errbuf);
exit(1);
}
for(d = alldevs;d !=NULL;d = d->next){
printf("-----------------------------------------------------------------\nnumber:%d\nname:%s\n",++i,d->name);
if(d->description){
printf("description:%s\n",d->description);
}else{
printf("description:%s","no description\n");
}
printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
pcap_addr_t *a;
for(a = d->addresses;a;a = a->next){
switch (a->addr->sa_family)
{
case AF_INET:
printf("Address Family Name:AF_INET\n");
if(a->addr){
printf("Address:%s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
}
if (a->netmask){
printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
}
if (a->broadaddr){
printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
}
if (a->dstaddr){
printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
}
break;
case AF_INET6:
printf("Address Family Name:AF_INET6\n");
printf("this is an IPV6 address\n");
break;
default:
break;
}
}
}
if(i == 0){
printf("interface not found,please check winpcap installation");
}
int num;
printf("Enter the interface number(1-%d):",i);
scanf("%d",&num);
printf("\n");
if(num<1||num>i){
printf("number out of range\n");
pcap_freealldevs(alldevs);
return -1;
}
for(d=alldevs, i=0; i< num-1 ; d=d->next, i++);
if((adhandle = pcap_open(d->name,
65535,
PCAP_OPENFLAG_PROMISCUOUS,
1000,
NULL,
errbuf
)) == NULL){
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
pcap_freealldevs(alldevs);
return -1;
}
ifget(d, ip_addr, ip_netmask);
GetSelfMac(adhandle,ip_addr,ip_mac);
sp.adhandle = adhandle;
sp.ip = ip_addr;
sp.mac = ip_mac;
sp.netmask = ip_netmask;
gp.adhandle = adhandle;
sendthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SendArpPacket,
&sp, 0, NULL);
recvthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) GetLivePC, &gp,
0, NULL);
printf("\nlistening on 网卡%d ...\n", i);
pcap_freealldevs(alldevs);
getchar();
getchar();
while(true){
char *TcpData;
TcpData= (char *) malloc(sizeof(char) * 50);
if (TcpData== NULL)
{
printf("申请内存存放NETMASK地址失败!\n");
return -1;
}
struct EthernetHeader ethernet;
struct IpHeader ip;
struct TcpHeader tcp;
struct PsdTcpHeader ptcp;
unsigned char SendBuffer[200];
u_int ip1,ip2,ip3,ip4;
scanf("%d.%d.%d.%d",&ip1,&ip2,&ip3,&ip4);
printf("请输入你要发送的内容:\n");
getchar();
gets(TcpData);
printf("要发送的内容:%s\n",TcpData);
memset(ðernet, 0, sizeof(ethernet));
BYTE destmac[8];
destmac[0] = 0x00;
destmac[1] = 0x11;
destmac[2] = 0x22;
destmac[3] = 0x33;
destmac[4] = 0x44;
destmac[5] = 0x55;
memcpy(ethernet.DestMAC, destmac, 6);
BYTE hostmac[8];
hostmac[0] = 0x00;
hostmac[1] = 0x1a;
hostmac[2] = 0x4d;
hostmac[3] = 0x70;
hostmac[4] = 0xa3;
hostmac[5] = 0x89;
memcpy(ethernet.SourMAC, hostmac, 6);
ethernet.EthType = htons(0x0800);
memcpy(&SendBuffer, ðernet, sizeof(struct EthernetHeader));
ip.Version_HLen = 0x45;
ip.TOS = 0;
ip.Length = htons(sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
ip.Ident = htons(1);
ip.Flags_Offset = 0;
ip.TTL = 128;
ip.Protocol = 6;
ip.Checksum = 0;
ip.SourceAddr.byte1 = 127;
ip.SourceAddr.byte2 = 0;
ip.SourceAddr.byte3 = 0;
ip.SourceAddr.byte4 = 1;
ip.DestinationAddr.byte1 = ip1;
ip.DestinationAddr.byte2 = ip2;
ip.DestinationAddr.byte3 = ip3;
ip.DestinationAddr.byte4 = ip4;
memcpy(&SendBuffer[sizeof(struct EthernetHeader)], &ip, 20);
tcp.DstPort = htons(102);
tcp.SrcPort = htons(1000);
tcp.SequenceNum = htonl(11);
tcp.Acknowledgment = 0;
tcp.HdrLen = 0x50;
tcp.Flags = 0x18;
tcp.AdvertisedWindow = htons(512);
tcp.UrgPtr = 0;
tcp.Checksum = 0;
memcpy(&SendBuffer[sizeof(struct EthernetHeader) + 20], &tcp, 20);
ptcp.SourceAddr = ip.SourceAddr;
ptcp.DestinationAddr = ip.DestinationAddr;
ptcp.Zero = 0;
ptcp.Protcol = 6;
ptcp.TcpLen = htons(sizeof(struct TcpHeader) + strlen(TcpData));
char TempBuffer[65535];
memcpy(TempBuffer, &ptcp, sizeof(struct PsdTcpHeader));
memcpy(TempBuffer + sizeof(struct PsdTcpHeader), &tcp, sizeof(struct TcpHeader));
memcpy(TempBuffer + sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
tcp.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader), &tcp, sizeof(struct TcpHeader));
memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
memset(TempBuffer, 0, sizeof(TempBuffer));
memcpy(TempBuffer, &ip, sizeof(struct IpHeader));
ip.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct IpHeader));
memcpy(SendBuffer + sizeof(struct EthernetHeader), &ip, sizeof(struct IpHeader));
int size = sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData);
int result = pcap_sendpacket(adhandle, SendBuffer,size);
if (result != 0)
{
printf("Send Error!\n");
}
else
{
printf("发送TCP数据包.\n");
printf("目的端口:%d\n", ntohs(tcp.DstPort));
printf("源端口:%d\n", ntohs(tcp.SrcPort));
printf("序号:%d\n", ntohl(tcp.SequenceNum));
printf("确认号:%d\n", ntohl(tcp.Acknowledgment));
printf("首部长度:%d*4\n", tcp.HdrLen >> 4);
printf("标志位:0x%0x\n", ntohs(tcp.Flags));
printf("窗口大小:%d\n", ntohs(tcp.AdvertisedWindow));
printf("紧急指针:%d\n", ntohs(tcp.UrgPtr));
printf("检验和:%u\n", ntohs(tcp.Checksum));
printf("发送成功!\n");
}
free(TcpData);
}
return 0;
}
#define IPTOSBUFFERS 12
char *iptos(u_long in)
{
static char output[IPTOSBUFFERS][3*4+3+1];
static short which;
u_char *p;
p = (u_char *)∈
which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output[which];
}
void ifget(pcap_if_t *d, char *ip_addr, char *ip_netmask) {
pcap_addr_t *a;
for (a = d->addresses; a; a = a->next) {
switch (a->addr->sa_family) {
case AF_INET:
if (a->addr) {
char *ipstr;
ipstr = iptos(((struct sockaddr_in *) a->addr)->sin_addr.s_addr);
printf("ipstr:%s\n",ipstr);
memcpy(ip_addr, ipstr, 16);
}
if (a->netmask) {
char *netmaskstr;
netmaskstr = iptos(((struct sockaddr_in *) a->netmask)->sin_addr.s_addr);
printf("netmask:%s\n",netmaskstr);
memcpy(ip_netmask, netmaskstr, 16);
}
case AF_INET6:
break;
}
}
}
int GetSelfMac(pcap_t *adhandle, const char *ip_addr, unsigned char *ip_mac) {
unsigned char sendbuf[42];
int i = -1;
int res;
EthernetHeader eh;
Arpheader ah;
struct pcap_pkthdr * pkt_header;
const u_char * pkt_data;
memset(eh.DestMAC, 0xff, 6);
memset(eh.SourMAC, 0x0f, 6);
memset(ah.DestMacAdd, 0x0f, 6);
memset(ah.SourceMacAdd, 0x00, 6);
eh.EthType = htons(ETH_ARP);
ah.HardwareType= htons(ARP_HARDWARE);
ah.ProtocolType = htons(ETH_IP);
ah.HardwareAddLen = 6;
ah.ProtocolAddLen = 4;
ah.SourceIpAdd = inet_addr("100.100.100.100");
ah.OperationField = htons(ARP_REQUEST);
ah.DestIpAdd = inet_addr(ip_addr);
memset(sendbuf, 0, sizeof(sendbuf));
memcpy(sendbuf, &eh, sizeof(eh));
memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
printf("%s",sendbuf);
if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
printf("\nPacketSend succeed\n");
} else {
printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
return 0;
}
while ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
if (*(unsigned short *) (pkt_data + 12) == htons(ETH_ARP)
&& *(unsigned short*) (pkt_data + 20) == htons(ARP_REPLY)
&& *(unsigned long*) (pkt_data + 38)
== inet_addr("100.100.100.100")) {
for (i = 0; i < 6; i++) {
ip_mac[i] = *(unsigned char *) (pkt_data + 22 + i);
}
printf("获取自己主机的MAC地址成功!\n");
break;
}
}
if (i == 6) {
return 1;
} else {
return 0;
}
}
/* 向局域网内所有可能的IP地址发送ARP请求包线程 */
DWORD WINAPI SendArpPacket(LPVOID lpParameter)
{
sparam *spara = (sparam *) lpParameter;
pcap_t *adhandle = spara->adhandle;
char *ip = spara->ip;
unsigned char *mac = spara->mac;
char *netmask = spara->netmask;
printf("ip_mac:%02x-%02x-%02x-%02x-%02x-%02x\n", mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
printf("自身的IP地址为:%s\n", ip);
printf("地址掩码NETMASK为:%s\n", netmask);
printf("\n");
unsigned char sendbuf[42];
EthernetHeader eh;
Arpheader ah;
memset(eh.DestMAC, 0xff, 6);
memcpy(eh.SourMAC, mac, 6);
memcpy(ah.SourceMacAdd, mac, 6);
memset(ah.DestMacAdd, 0x00, 6);
eh.EthType = htons(ETH_ARP);
ah.HardwareType = htons(ARP_HARDWARE);
ah.ProtocolType = htons(ETH_IP);
ah.HardwareAddLen = 6;
ah.ProtocolAddLen = 4;
ah.SourceIpAdd = inet_addr(ip);
ah.OperationField = htons(ARP_REQUEST);
unsigned long myip = inet_addr(ip);
unsigned long mynetmask = inet_addr(netmask);
unsigned long hisip = htonl((myip & mynetmask));
for (int i = 0; i < HOSTNUM; i++) {
ah.DestIpAdd = htonl(hisip + i);
memset(sendbuf, 0, sizeof(sendbuf));
memcpy(sendbuf, &eh, sizeof(eh));
memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
} else {
printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
}
Sleep(50);
}
Sleep(1000);
flag = TRUE;
return 0;
}
DWORD WINAPI GetLivePC(LPVOID lpParameter)
{
gparam *gpara = (gparam *) lpParameter;
pcap_t *adhandle = gpara->adhandle;
int res;
unsigned char Mac[6];
struct pcap_pkthdr * pkt_header;
const u_char * pkt_data;
while (true) {
if (flag) {
printf("获取MAC地址完毕,请输入你要发送对方的IP地址:\n");
break;
}
if ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0) {
if (*(unsigned short *) (pkt_data + 12) == htons(ETH_ARP)) {
ArpPacket *recv = (ArpPacket *) pkt_data;
if (*(unsigned short *) (pkt_data + 20) == htons(ARP_REPLY)) {
printf("-------------------------------------------\n");
printf("IP地址:%d.%d.%d.%d MAC地址:",
recv->ah.SourceIpAdd & 255,
recv->ah.SourceIpAdd >> 8 & 255,
recv->ah.SourceIpAdd >> 16 & 255,
recv->ah.SourceIpAdd >> 24 & 255);
for (int i = 0; i < 6; i++) {
Mac[i] = *(unsigned char *) (pkt_data + 22 + i);
printf("%02x", Mac[i]);
}
printf("\n");
}
}
}
Sleep(10);
}
return 0;
}
unsigned short checksum(unsigned short *data, int length)
{
unsigned long temp = 0;
while (length > 1)
{
temp += *data++;
length -= sizeof(unsigned short);
}
if (length)
{
temp += *(unsigned short*)data;
}
temp = (temp >> 16) + (temp &0xffff);
temp += (temp >> 16);
return (unsigned short)(~temp);
}
6.2 接收TCP数据包
#include "pcap.h"
#include<winsock2.h>
#pragma comment(lib,"wpcap.lib")
#pragma comment(lib,"packet.lib")
#pragma comment(lib,"ws2_32.lib")
void packet_handler(u_char *param,const struct pcap_pkthdr *header,const u_char *pcap_data);
#define IPTOSBUFFERS 12
void ifprint(pcap_if_t *d);
char * iptos(u_long in);
int i = 0;
struct ether_header
{
u_int8_t ether_dhost[6];
u_int8_t ether_shost[6];
u_int16_t ether_type;
};
struct ip_header
{
unsigned char Version_HLen;
u_int8_t ip_tos;
u_int16_t ip_length;
u_int16_t ip_id;
u_int16_t ip_off;
u_int8_t ip_ttl;
u_int8_t ip_protocol;
u_int16_t ip_checksum;
struct in_addr ip_souce_address;
struct in_addr ip_destination_address;
};
struct TcpHeader
{
unsigned short SrcPort;
unsigned short DstPort;
unsigned int SequenceNum;
unsigned int Acknowledgment;
unsigned char HdrLen;
unsigned char Flags;
unsigned short AdvertisedWindow;
unsigned short Checksum;
unsigned short UrgPtr;
};
void ip_protool_packet_callback(u_char *argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
{
struct ip_header *ip_protocol;
u_int header_length = 0;
u_int offset;
u_char tos;
u_int16_t checksum;
u_int ip_len;
u_int ip_version;
TcpHeader *tcp;
u_short sport,dport;
ip_protocol = (struct ip_header *) (packet_content+14);
ip_len = (ip_protocol->Version_HLen & 0xf) *4;
ip_version = ip_protocol->Version_HLen>>4;
tcp = (TcpHeader *)((u_char *)ip_protocol+ip_len);
checksum =ntohs(ip_protocol->ip_checksum);
tos = ip_protocol->ip_tos;
offset = ntohs(ip_protocol->ip_off);
if(*(unsigned long*)(packet_content+30)==inet_addr("100.100.100.100")){
printf("---------IP协议---------\n");
printf("版本号:%d\n", ip_version);
printf("首部长度:%d\n",ip_len);
printf("服务质量:%d\n",tos);
printf("总长度:%d\n",ntohs(ip_protocol->ip_length));
printf("标识:%d\n",ntohs(ip_protocol->ip_id));
printf("偏移:%d\n",(offset & 0x1fff) * 8);
printf("生存时间:%d\n",ip_protocol->ip_ttl);
printf("协议类型:%d\n",ip_protocol->ip_protocol);
switch (ip_protocol->ip_protocol)
{
case 1: printf("上层协议是ICMP协议\n");break;
case 2: printf("上层协议是IGMP协议\n");break;
case 6: printf("上层协议是TCP协议\n");break;
case 17: printf("上层协议是UDP协议\n");break;
default:break;
}
printf("检验和:%d\n",checksum);
printf("源IP地址:%s\n", inet_ntoa(ip_protocol->ip_souce_address));
printf("目的地址:%s\n", inet_ntoa(ip_protocol->ip_destination_address));
printf("---------TCP协议---------\n");
sport = ntohs( tcp->SrcPort );
dport = ntohs( tcp->DstPort );
printf("源端口:%d 目的端口:%d\n",sport,dport);
printf("序号:%d\n",ntohl(tcp->SequenceNum));
printf("确认号:%d\n",ntohl(tcp->Acknowledgment));
printf("偏移地址(首部长度):%d\n",(tcp->HdrLen>>4)*4);
printf("标志位:%d\n",tcp->Flags);
printf("紧急UGR:%d\n",(tcp->Flags & 0x20)/32);
printf("确认ACK:%d\n",(tcp->Flags & 0x10)/16);
printf("推送PSH:%d\n",(tcp->Flags & 0x08)/8);
printf("复位RST:%d\n",(tcp->Flags & 0x04)/4);
printf("同步SYN:%d\n",(tcp->Flags & 0x02)/2);
printf("终止FIN:%d\n",tcp->Flags & 0x01);
printf("窗口大小:%d\n",ntohs(tcp->AdvertisedWindow));
printf("校验和:%d\n",ntohs(tcp->Checksum));
printf("紧急指针:%d\n",ntohs(tcp->UrgPtr));
char * data;
data = (char *)((u_char *)tcp+20);
printf("---------数据部分---------\n");
printf("数据部分:%s\n",data);
}
}
void ethernet_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
{
u_short ethernet_type;
struct ether_header *ethernet_protocol;
u_char *mac_string;
static int packet_number = 1;
ethernet_protocol=(struct ether_header*)packet_content;
ethernet_type=ntohs(ethernet_protocol->ether_type);
if(ethernet_type==0x0800)
{
ip_protool_packet_callback (argument,packet_header,packet_content);
}
packet_number++;
}
int main()
{
pcap_if_t * alldevs;
pcap_if_t * d;
int inum;
pcap_t * adhandle;
char errbuf[PCAP_ERRBUF_SIZE];
if(pcap_findalldevs(&alldevs,errbuf) == -1)
{
exit(1);
}
for(d=alldevs;d != NULL;d=d->next)
{
ifprint(d);
}
if(i==0)
{
printf("\nNo interfaces found!Make sure WinPcap is installed.\n");
char c = getchar();
return -1;
}
printf("Enter the interface number (1-%d):",i);
scanf("%d",&inum);
if(inum <1 || inum >i)
{
printf("\nInterface number out of range.\n");
pcap_freealldevs(alldevs);
char c = getchar();
return -1;
}
for (d = alldevs,i=0;i <inum-1;d=d->next,i++);
if ((adhandle=pcap_open_live(d->name,65536,1,1000,errbuf))==NULL)
{
fprintf(stderr,"\nUnable to open the adapter.%s is not supported by WinPcap\n");
pcap_freealldevs(alldevs);
char c = getchar();
return -1;
}
printf("\nlistening on %s...\n",d->description);
pcap_freealldevs(alldevs);
pcap_loop(adhandle,0,ethernet_protocol_packet_callback,NULL);
char c = getchar();
return 0;
}
void ifprint(pcap_if_t *d)
{
pcap_addr_t *a;
printf("%d.%s",++i,d->name);
if(d->description)
{
printf("\tDescription:(%s)\n",d->description);
}else{
printf("\t(No description available)\n");
}
printf("\tLoopback:%s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
for (a=d->addresses;a != NULL;a=a->next)
{
printf("\tAddress Family:#%d\n",a->addr->sa_family);
switch (a->addr->sa_family)
{
case AF_INET:
printf("\tAddress Family Name:AF_INET\n");
if(a->addr)
{
printf("\tAddress:%s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
}
if(a->netmask)
{
printf("\tNetmask:%s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
}
if(a->broadaddr)
{
printf("\tBroadcast Address:%s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
}
if(a->dstaddr)
{
printf("\tDestination Address:%s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
}
break;
default:
printf("\tAddressFamilyName:Unknown\n");
break;
}
}
}
char * iptos(u_long in)
{
static char output[IPTOSBUFFERS][3*4+3+1];
static short which;
u_char *p;
p = (u_char *)∈
which=(which+1==IPTOSBUFFERS?0:which+1);
sprintf(output[which],"%d.%d.%d.%d",p[0],p[1],p[2],p[3]);
return output[which];
}
void packet_handler(u_char *param,const struct pcap_pkthdr *header,const u_char *pcap_data)
{
struct tm * ltime;
char timestr[16];
ltime = localtime(&header->ts.tv_sec);
strftime(timestr,sizeof(timestr),"%H:%M:%S",ltime);
printf("%s, %.6d len:%d\n",timestr,header->ts.tv_usec,header->len);
}
程序说明
代码实现需要配置winpcap环境 发送TCP数据包时输入目的IP地址为100.100.100.100 然后输入要发送的数据,即可在接收TCP数据包中收到数据 如果没有收到,把接收TCP数据包关掉重开一下,再试一次就可以了 如果将接受TCP数据包代码中的if判断去掉,即可接受所有TCP数据包