下载lib库和SDK

#include<iostream>
#include<winsock2.h>
#include <conio.h>
#include "pcap.h"
#pragma comment(lib,"wpcap.lib")
#pragma comment(lib,"packet.lib")
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)
#define LINE_LEN 16
#define IPTOSBUFFERS 12
using namespace std;
int i = 0;
/*帧首部*/
struct FrameHeader_t {
byte DesMAC[6]; //目的Mac地址
byte SrcMAC[6]; //源Mac地址
WORD FrameType; //协议(帧)类型
};
/*IP首部*/
struct IPHeader_t {
#if defined(WORDS_BIENDIAN)
byte Version : 4, HeaderLength : 4;
#else
byte HeaderLength : 4, Version : 4;
#endif
byte TOS;//服务类型
WORD TotalLen; //总长度
WORD ID;//标识
WORD Flag_Segment;//标志字段
byte TTL;//生存时间值
byte Protocol;//协议类型,是TCP/IP体系中的网络层协议
WORD Checksum;//检验和
struct in_addr SrcIP;//源IP
struct in_addr DstIP;//目的IP
};
/*IP协议首部处理函数*/
bool ip_protocol_packet_callback(const struct pcap_pkthdr* packet_header, const u_char* packet_data)
{
struct IPHeader_t* IPHeader;
IPHeader = (struct IPHeader_t*)(packet_data + 14);//MAC首部是14位的,加上14位得到IP协议首部
printf("---------IP协议----------------------------------------------------------\n");
printf("版本号:%d\n", IPHeader->Version);
printf("首部长度:%d\n", IPHeader->HeaderLength);
printf("服务类型:%d\n", IPHeader->TOS);
printf("总长度:%d\n", ntohs(IPHeader->TotalLen));
printf("标识:%d\n", ntohs(IPHeader->ID));
printf("偏移:%d\n", (ntohs(IPHeader->Flag_Segment) & 0x1fff) * 8);
printf("生存时间:%d\n", IPHeader->TTL);
printf("协议类型:%d\n", IPHeader->Protocol);
switch (IPHeader->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:printf("上层协议:Unknown\n"); break;
}
printf("检验和:%d\n", ntohs(IPHeader->Checksum));
printf("源IP地址:%s\n", inet_ntoa(IPHeader->SrcIP));
printf("目的地址:%s\n", inet_ntoa(IPHeader->DstIP));
UINT32 value = (UINT32)(IPHeader->DstIP.S_un.S_addr);
UINT32 b1, b2, b3, b4 = 0;
b1 = value >> 24;
b2 = (value & 0x00FFFFFF) >> 16;
b3 = (value & 0x0000FFFF) >> 8;
b4 = (value & 0x000000FF);
if (b4 == 172 && b3 == 16 && b2 == 30 && b1 == 30)
{
return true;
}
return false;
}
/*帧首部处理函数*/
bool ethernet_protocol_packet_callback(const struct pcap_pkthdr* packet_header, const u_char* packet_data)
{
struct FrameHeader_t* frameHeader;
frameHeader = (struct FrameHeader_t*)packet_data;//获得数据包内容
printf("---------以太网协议------------------------------------------------------\n");
printf("以太网类型:0x%04x\n", ntohs(frameHeader->FrameType));
switch (ntohs(frameHeader->FrameType))
{
case 0x0800: printf("上层协议:IP协议\n"); break;
case 0x0806: printf("上层协议:ARP协议\n"); break;
case 0x8035: printf("上层协议:RARP协议\n"); break;
default:printf("上层协议:Unknown\n"); break;
}
u_char* macS = frameHeader->SrcMAC;
u_char* macD = frameHeader->DesMAC;
printf("MAC帧源地址:%02x:%02x:%02x:%02x:%02x:%02x\n", *macS, *(macS + 1), *(macS + 2), *(macS + 3), *(macS + 4), *(macS + 5));
printf("MAC帧目的地址:%02x:%02x:%02x:%02x:%02x:%02x\n", *macD, *(macD + 1), *(macD + 2), *(macD + 3), *(macD + 4), *(macD + 5));
if (ntohs(frameHeader->FrameType) == 0x0800)//继续分析IP协议
{
return ip_protocol_packet_callback(packet_header, packet_data);
}
return false;
}
/*线程参数结构体*/
struct parame
{
pcap_t* adhandle;
struct pcap_pkthdr* packet_header;
const u_char* packet_data;
int num;
};
typedef struct _ethhdr
{
unsigned char eh_dst[6];
unsigned char eh_src[6];
unsigned short eh_type;
}ETH_HEADER;
typedef struct _psdhdr
{
unsigned long saddr;
unsigned long daddr;
char mbz; //保留,置0
char ptcl; //协议,如IPPROTO_TCP
unsigned short tcpl; //TCP报头长度
}PSD_HEADER;
typedef struct
{
UINT8 HdrLength : 4;
UINT8 Version : 4;
UINT8 TOS;
UINT16 Length;
UINT16 Id;
UINT16 FragOff0;
UINT8 TTL;
UINT8 Protocol;
UINT16 Checksum;
UINT32 SrcAddr;
UINT32 DstAddr;
} WINDIVERT_IPHDR, * PWINDIVERT_IPHDR;
typedef struct
{
UINT16 SrcPort;
UINT16 DstPort;
UINT32 SeqNum;
UINT32 AckNum;
UINT16 Reserved1 : 4;
UINT16 HdrLength : 4;
UINT16 Fin : 1;
UINT16 Syn : 1;
UINT16 Rst : 1;
UINT16 Psh : 1;
UINT16 Ack : 1;
UINT16 Urg : 1;
UINT16 Reserved2 : 2;
UINT16 Window;
UINT16 Checksum;
UINT16 UrgPtr;
} WINDIVERT_TCPHDR, * PWINDIVERT_TCPHDR;
//计算校验和
USHORT checksum( USHORT* buffer, int size)
{
unsigned long cksum = 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);
}
int SendRaw(pcap_t* handle, BYTE* _dmac, BYTE* _smac, //目的MAC,源MAC,网络顺序
USHORT _ident, //IP包标识号
ULONG _saddr, USHORT _sport, //源IP,PORT,网络顺序
ULONG _daddr, USHORT _dport, //目的IP,PORT,网络顺序
ULONG _seq, ULONG _ack) //32位序列号,应答号,网络顺序
{
//构造以太网头
ETH_HEADER eth;
memcpy(eth.eh_dst, _dmac, 6);
memcpy(eth.eh_src, _smac, 6);
// IP协议
eth.eh_type = htons(0x0800);
//构造IP头
WINDIVERT_IPHDR ip;
ip.Version = 4 << 4 | sizeof(WINDIVERT_IPHDR) / 4;
ip.TOS = 0;
ip.Length = htons(sizeof(WINDIVERT_IPHDR) + sizeof(WINDIVERT_TCPHDR));
ip.Id = _ident;
ip.FragOff0 = htons(0x4000); //禁止分片
ip.TTL = 128;
ip.Protocol = IPPROTO_TCP;
ip.Checksum = 0;
ip.SrcAddr = _saddr;
ip.DstAddr = _daddr;
//构造TCP头
WINDIVERT_TCPHDR tcp;
tcp.SrcPort = _sport;
tcp.DstPort = _dport;
tcp.SeqNum = _seq;
tcp.AckNum = _ack;
tcp.HdrLength = sizeof(WINDIVERT_TCPHDR) / 4 << 4 | 0;
tcp.Rst = 1;
tcp.Window = htons(512);
tcp.Checksum = 0;
tcp.UrgPtr = 0;
//构造PSD头
PSD_HEADER psd;
psd.saddr = ip.SrcAddr;
psd.daddr = ip.DstAddr;
psd.mbz = 0;
psd.ptcl = IPPROTO_TCP;
psd.tcpl = htons(sizeof(WINDIVERT_TCPHDR));
//开始装包并计算校验和
char szbuf[128] = { 0 };
memcpy(szbuf, &psd, sizeof(psd));
memcpy(szbuf + sizeof(psd), &tcp, sizeof(tcp));
tcp.Checksum = checksum((USHORT*)szbuf, sizeof(psd) + sizeof(tcp));
ip.Checksum = checksum((USHORT*)&ip, sizeof(ip));
memset(szbuf, 0, sizeof(szbuf));
memcpy(szbuf, ð, sizeof(eth));
memcpy(szbuf + sizeof(eth), &ip, sizeof(ip));
memcpy(szbuf + sizeof(eth) + sizeof(ip), &tcp, sizeof(tcp));
memset(szbuf + sizeof(eth) + sizeof(ip) + sizeof(tcp), 0, 4);
int bytes_out = 0;
int len = sizeof(eth) + sizeof(ip) + sizeof(tcp);
int ret = pcap_sendpacket(handle, (BYTE*)szbuf, len);
if (ret != 0) {
bytes_out = -1;
}
else {
bytes_out = len;
}
return bytes_out;
}
/*抓包线程*/
DWORD WINAPI Capturer(PVOID hWnd)
{
int res;
int packet_number = 0;
struct tm* ltime;
time_t local_tv_sec;
char timestr[16];
//将传入线程中的参数携带的数据取出
parame* Packet = (parame*)hWnd;
pcap_t* adhandle = Packet->adhandle;
struct pcap_pkthdr* packet_header = Packet->packet_header;
const u_char* packet_data = Packet->packet_data;
int num = Packet->num;
while ((res = pcap_next_ex(adhandle, &packet_header, &packet_data)) >= 0)
{
//接收数据包超时
if (res == 0)
{
continue;
}
printf("=========================================================================\n");
packet_number++;
//将时间戳转化为可识别格式
local_tv_sec = packet_header->ts.tv_sec;
ltime = localtime(&local_tv_sec);
strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);
printf("捕获第%d个网络数据包\n", packet_number);;
printf("捕获时间:%s\n", timestr);
printf("数据包长度:%d\n", packet_header->len);
printf("---------数据包内容------------------------------------------------------\n");
//输出数据包的具体内容
char temp[LINE_LEN + 1];
for (int i = 0; i < packet_header->caplen; ++i)
{
printf("%.2x ", packet_data[i]);
if (isgraph(packet_data[i]) || packet_data[i] == ' ')
temp[i % LINE_LEN] = packet_data[i];
else
temp[i % LINE_LEN] = '.';
if (i % LINE_LEN == 15)
{
temp[16] = '\0';
printf(" ");
printf("%s", temp);
printf("\n");
memset(temp, 0, LINE_LEN);
}
}
printf("\n");
//分析数据包
bool ret = ethernet_protocol_packet_callback(packet_header, packet_data);
ETH_HEADER* peth = (ETH_HEADER*)packet_data;
WINDIVERT_IPHDR* pip = (WINDIVERT_IPHDR*)(packet_data + sizeof(ETH_HEADER));
WINDIVERT_TCPHDR* ptcp = (WINDIVERT_TCPHDR*)(packet_data + sizeof(ETH_HEADER) + sizeof(WINDIVERT_IPHDR));
printf("=========================================================================\n");
if (ret)
{
// 实际测试不行
////反向发RST包
//SendRaw(adhandle,peth->eh_src, peth->eh_dst,
//htons(0),
//pip->DstAddr, ptcp->DstPort,
//pip->SrcAddr, ptcp->SrcPort,
//ptcp->Ack,
//htonl(ntohl(ptcp->SeqNum) + 1));
////正向发RST包
// //除掉IP头和TCP头后的数据长度
//int predatalen = ntohs(pip->Length) - 40;
//SendRaw(adhandle, peth->eh_dst, peth->eh_src,
// htons(ntohs(pip->Id) + 1),
// pip->SrcAddr, ptcp->SrcPort,
// pip->DstAddr, ptcp->DstPort,
// htonl(ntohl(ptcp->SeqNum) + predatalen),
// ptcp->Ack);
}
//停止数据包捕捉
if (_kbhit())
{
int ch = _getch();//使用_getch()函数获取按下的键值
if (ch == 27)//当按下ESC时退出
{
cout << "\nThe Capturer has been closed..." << endl;
return 0;
}
}
//每1秒抓一次
//Sleep(1000);
}
return 0;
}
/*IP格式转化函数*/
char* iptos(u_long in)
{
static char output[IPTOSBUFFERS][3 * 4 + 3 + 1];
static short which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
u_char* p = (u_char*)∈
sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output[which];
}
/*打印本机接口列表*/
void ifprint(pcap_if_t* d)
{
pcap_addr_t* a;//表示接口地址指针
printf("%d.%s\n", ++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");//是否是虚拟接口
//获取该网络接口设备的IP地址信息
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://判断该地址是否IP地址
printf("\tAddress Family Name:AF_INET\n");
if (a->addr)//ip地址
{
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;
}
}
}
int main()
{
pcap_if_t* alldevs;//指向设备链表首部的指针
pcap_if_t* d;
int num;
pcap_t* adhandle;//定义打开设备的返回值
char errbuf[PCAP_ERRBUF_SIZE];//错误信息缓冲区
//取得列表
if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING,//获取本机的接口设备
NULL,//无需认证
&alldevs,//指向设备列表首部
errbuf//出错信息保存缓冲区
) == -1)
{
printf("Error in pcap_findalldevs_ex!%s\n");//错误处理
return -1;
}
//输出列表
for (d = alldevs; d != NULL; d = d->next)
{
ifprint(d);
}
if (i == 0)
{
printf("\nNo interfaces found!\n");
return -1;
}
LOOP:
printf("\nEnter the interface number (1-%d):", i);
scanf("%d", &num);
if (num <1 || num >i)
{
printf("\nInterface number out of range.\n");
printf("Continue or Quit [c/q]:");
char a;
cin >> a;
if (a == 'c' || a == 'C')
{
goto LOOP;
}
else if (a == 'q' || a == 'Q')
{
pcap_freealldevs(alldevs);
return 0;
}
}
//转到选择的设备
for (d = alldevs, i = 0; i < num - 1; d = d->next, i++);
//打开失败
if ((adhandle = pcap_open_live(d->name, 65536, 1, 1000, errbuf)) == NULL)
{
fprintf(stderr, "\nUnable to open the adapter.\n");
printf("Continue or Quit [c/q]:");
char a;
cin >> a;
if (a == 'c' || a == 'C')
{
goto LOOP;
}
else if (a == 'q' || a == 'Q')
{
pcap_freealldevs(alldevs);
return 0;
}
}
//打开成功
printf("\nlistening on %s...\n\n", d->description);
//释放列表
pcap_freealldevs(alldevs);
//开始抓包,创建线程
HANDLE m_capturer;
struct pcap_pkthdr* packet_header = new pcap_pkthdr;
const u_char* packet_data = new u_char;
parame* m_pam = new parame;
m_pam->adhandle = adhandle;
m_pam->packet_header = packet_header;
m_pam->packet_data = packet_data;
m_pam->num = num;
m_capturer = CreateThread(NULL, NULL, &Capturer, (PVOID*)m_pam, 0, NULL);
CloseHandle(m_capturer);
while (1);
return 0;
}