//将ARPFrame.SendIP设置为本机网卡上绑定的IP地址,若获取本机MAC,则伪造发送IP和MAC ARPFrame.SendIP = inet_addr(ip[0]); //ipprint(ARPFrame.SendIP); //将ARPFrame.RecvHa设置为0 for (int i = 0; i < 6; i++) ARPFrame.RecvHa[i] = 0; //将ARPFrame.RecvIP设置为请求的IP地址 ARPFrame.RecvIP = ip_;
u_char* h = (u_char*)&ARPFrame; int len = sizeof(ARPFrame_t);
if (ahandle == nullptr) printf("网卡接口打开错误\n"); else { if (pcap_sendpacket(ahandle, (u_char*)&ARPFrame, sizeof(ARPFrame_t)) != 0) { //发送错误处理 printf("senderror\n"); } else { //发送成功 while (1) { pcap_pkthdr* pkt_header; const u_char* pkt_data; int rtn = pcap_next_ex(ahandle, &pkt_header, &pkt_data);//捕获数据报 if (rtn == 1)//捕获到数据报 { ARPFrame_t* IPPacket = (ARPFrame_t*)pkt_data; if (ntohs(IPPacket->FrameHeader.FrameType) == 0x806)//筛选ARP类型的消息进行处理 { if (!compare(IPPacket->FrameHeader.SrcMAC, ARPFrame.FrameHeader.SrcMAC) && compare(IPPacket->FrameHeader.DesMAC, ARPFrame.FrameHeader.SrcMAC) && IPPacket->SendIP == ip_)//消息筛选 { ltable.write2log_arp(IPPacket); //源MAC地址即为所需MAC地址 for (int i = 0; i < 6; i++) { mac[i] = IPPacket->FrameHeader.SrcMAC[i]; } break;//已经捕获到MAC,可以退出函数 }
} } } } } }
==setchecksum和checkchecesum设置校验和和检验校验和==
voidsetchecksum(Data_t* temp)//设置校验和 { temp->IPHeader.Checksum = 0; unsignedint sum = 0; WORD* t = (WORD*)&temp->IPHeader;//每16位为一组 for (int i = 0; i < sizeof(IPHeader_t)/2; i++) { sum += t[i]; while (sum >= 0x10000)//如果溢出,则进行回卷 { int s = sum >> 16; sum -= 0x10000; sum += s; } } temp->IPHeader.Checksum = ~sum;//结果取反 }
boolcheckchecksum(Data_t* temp)//检验 { unsignedint sum = 0; WORD* t = (WORD*)&temp->IPHeader; for (int i = 0; i < sizeof(IPHeader_t) / 2; i++) { sum += t[i]; while (sum >= 0x10000)//包含原有校验和一起进行相加 { int s = sum >> 16; sum -= 0x10000; sum += s; } } if (sum == 65535)//源码+反码-》全1 return1;//校验和正确 return0; }
==接收和处理线程函数==
为使消息转发和路由表添加、删除、打印等操作可以同时进行,使用线程函数进行消息内容处理
DWORD WINAPI handlerRequest(LPVOID lparam) { routetable rtable = *(routetable*)(LPVOID)lparam; while (1) { pcap_pkthdr* pkt_header; const u_char* pkt_data; while (1) { int rtn = pcap_next_ex(ahandle, &pkt_header, &pkt_data); if (rtn)break;//接收到消息 } FrameHeader_t* header = (FrameHeader_t*)pkt_data; if (compare(header->DesMAC, selfmac))//目的mac是自己的mac { elseif (ntohs(header->FrameType) == 0x800)//IP格式的数据报 { Data_t* data = (Data_t*)pkt_data; ltable.write2log_ip("接收", data);//将接收内容写入日志
DWORD ip1_ = data->IPHeader.DstIP; DWORD ip_ = rtable.lookup(ip1_);//查找路由表中是否有对应表项 if(ip_==-1)continue;//如果没有则直接丢弃或直接递交至上层 if (checkchecksum(data))//如果校验和不正确,则直接丢弃不进行处理 { if (data->IPHeader.DstIP != inet_addr(ip[0]) && data->IPHeader.DstIP != inet_addr(ip[1])) { //不是广播消息 int t1 = compare(data->FrameHeader.DesMAC, broadcast); int t2 = compare(data->FrameHeader.SrcMAC, broadcast); if (!t1 && !t2) { //ICMP报文包含IP数据包报头和其它内容 ICMP_t* temp_ = (ICMP_t*)pkt_data; ICMP_t temp = *temp_; BYTE mac[6]; if(ip_==0)//直接投递,查找目的IP的MAc { //如果ARP表中没有所需内容,则需要获取ARP if (!arptable::lookup(ip1_, mac)) arptable::insert(ip1_, mac); resend(temp, mac);//转发 }