话不多说,先上一张运行时候的图:
![](https://img-blog.csdnimg.cn/20190110191724137.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhbmdmYWhlMQ==,size_16,color_FFFFFF,t_70)
直接上源码:
头文件声明:
class RawSniffer
{
public:
/* @接口 默认构造函数
* @邮箱 575814050@qq.com
* @时间 2018年12月5号
*/
RawSniffer();
/* @接口 默认析构函数
* @邮箱 575814050@qq.com
* @时间 2018年12月5号
*/
~RawSniffer();
/* @接口 停止嗅探
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年12月19号
*/
virtual void stopSniffer();
/* @接口 开始嗅探
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年12月6号
*/
virtual bool beginSniffer();
/* @接口 设置源IP地址
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setSrcIPs(const ULongArr &);
/* @接口 设置目的IP地址
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setDesIPs(const ULongArr &);
/* @接口 设置源端口
* @返回 bool 成功返回值为true,否则返回值为false
* @作者 杨发荷
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setSrcPorts(const UIntArr &);
/* @接口 设置目的端口
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setDesPorts(const UIntArr &);
/* @接口 设置嗅探的网卡
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年12月19号
*/
virtual void setSnifferNIC(DoxNetworkCard);
/* @接口 设置源IP地址
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setSrcIPs(const QStringList &);
/* @接口 设置目的IP地址
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setDesIPs(const QStringList &);
/* @接口 设置过滤IP
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setFilterIPs(const ULongArr &);
/* @接口 设置过滤端口
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setFilterPorts(const UIntArr &);
/* @接口 设置嗅探类型
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年12月6号
*/
virtual void setSnifferType(DoxProtocolType);
/* @接口 设置源端口
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setSrcPorts(const QStringList &);
/* @接口 设置目标端口
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setDesPorts(const QStringList &);
/* @接口 设置过滤IP地址
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setFilterIPs(const QStringList &);
/* @接口 设置过滤端口
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setFilterPorts(const QStringList &);
/* @接口 设置回调函数
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
virtual void setCallbackFunc(const DoxExtraFunc &);
private:
/* @接口 初始化套接字
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年12月6号
*/
bool initSocket();
/* @接口 过滤IP
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
bool filterIP(IPHeader *);
/* @接口 过滤端口
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
bool filterPort(uint, uint);
/* @接口 嗅探线程
* @邮箱 575814050@qq.com
* @时间 2018年12月6号
*/
static ulong snifferThread(void *);
/* @接口 分析IP数据
* @邮箱 575814050@qq.com
* @时间 2018年12月8号
*/
void purgeIPHeader(const IPHeader *, DoxSnifferInfo &);
/* @接口 分析TCP数据
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年10月26号
*/
bool purgeTCPProtocol(const TCPHeader *, DoxSnifferInfo &);
/* @接口 分析UPD数据
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
bool purgeUDPProtocol(const UDPHeader *, DoxSnifferInfo &);
/* @接口 分析ICMP数据
* @返回 bool 成功返回值为true,否则返回值为false
* @邮箱 575814050@qq.com
* @时间 2018年2018月12号
*/
bool purgeICMPProtocol(const ICMPHeader *, DoxSnifferInfo &);
public:
ulong m_rawSock;
ULongArr m_desIP;
ULongArr m_srcIP;
UIntArr m_desPort;
UIntArr m_srcPort;
ULongArr m_filterIP;
ULongArr m_rawSocks;
UIntArr m_filterPort;
DoxNetworkCard m_card;
DoxProtocolType m_type;
DoxExtraFunc m_callback;
};
源文件定义:
#define _WSAIOW(x,y) (IOC_IN|(x)|(y))
#define DOX_RCVALL _WSAIOW(IOC_VENDOR,1)
RawSniffer::RawSniffer()
: IRawSniffer()
, m_rawSock(INVALID_SOCKET)
{
WSADATA WSAData;
if(0 != WSAStartup(MAKEWORD(2, 2), &WSAData))
{
DoxLogger("初始化套接字失败");
}
else
{
DoxLogger("初始化套接字成功");
}
}
RawSniffer::~RawSniffer()
{
closesocket(m_rawSock);
WSACleanup();
}
bool RawSniffer::initSocket()
{
char *paddr, localName[256] = { 0 }; struct hostent *pHost;
if(SOCKET_ERROR == gethostname(localName, sizeof(localName)))
{
int ret = WSAGetLastError();
DoxLogger("获取本机名失败");
closesocket(m_rawSock); return false;
}
if(NULL == (pHost = gethostbyname(localName)))
{
int ret = WSAGetLastError();
DoxLogger("获取本机IP地址失败");
return false;
}
int index = 0;
while(NULL != (paddr = *(pHost->h_addr_list + m_card + index++ )))
{
ulong rawSock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
int ret = WSAGetLastError();
if(rawSock == INVALID_SOCKET || ret != 0)
{
DoxLogger("创建套接字失败");
closesocket(rawSock); continue;
}
SOCKADDR_IN addr_in;
addr_in.sin_family = AF_INET;
addr_in.sin_port = htons(57274);
memcpy(&(addr_in.sin_addr), paddr, pHost->h_length);
if(0 != bind(rawSock, (struct sockaddr *)&addr_in, sizeof(addr_in)))
{
DoxLogger("绑定套接字失败");
closesocket(rawSock); return false;
}
ulong dwValue = 0; ulong sioarg = 1;
if(SOCKET_ERROR == WSAIoctl(rawSock, DOX_RCVALL, &sioarg, sizeof(sioarg), NULL, 0, &dwValue, NULL, NULL))
{
DoxLogger("为流经绑定的IP的所有网卡数据失败.");
closesocket(rawSock); return false;
}
m_rawSocks.append(rawSock);
if(m_card != doxAllNetCard) break;
}
return true;
}
void RawSniffer::stopSniffer()
{
}
bool RawSniffer::beginSniffer()
{
if(!initSocket()) return false;
int len = m_rawSocks.length();
SnifferThread *sniffer = new SnifferThread[len];
for(int idx = 0; idx < len; ++idx)
{
sniffer[idx]._idx = idx; sniffer[idx]._raw = this;
HANDLE handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)snifferThread, &sniffer[idx], 0, NULL);
if(handle == INVALID_HANDLE_VALUE)
{
DoxLogger("创建线程失败");
return false;
}
CloseHandle(handle);
}
return true;
}
bool RawSniffer::filterIP(IPHeader *ipHeader)
{
ulong srcip = ipHeader->m_ulSrcIP, desip = ipHeader->m_ulDesIP;
if(m_srcIP.length() != 0 && !m_srcIP.contains(srcip)) return true;
if(m_desIP.length() != 0 && !m_desIP.contains(desip)) return true;
if(m_filterIP.length() != 0)
{
if(m_filterIP.contains(srcip)) return true;
if(m_filterIP.contains(desip)) return true;
}
return false;
}
ulong RawSniffer::snifferThread(void *lpParam)
{
SnifferThread param = *(SnifferThread *)lpParam;
RawSniffer *sniffer = param._raw; QString info;
char recvBuf[65536] = { 0 }, logInfo[65536] = { 0 };
char msg[65536] = { 0 }, *szPtr; Object<IDoxPointer> ptr(NIL);
while(true)
{
int ret = recv(sniffer->m_rawSocks[param._idx], recvBuf, 65536, 0);
if(ret == SOCKET_ERROR || ret < 0) DoxLogger("接受信息失败");
IPHeader *ipHeader = (IPHeader *)recvBuf;
if(sniffer->filterIP(ipHeader)) continue;
DoxSnifferInfo info;
sniffer->purgeIPHeader(ipHeader, info);
int ipHLen = sizeof(ulong) * (ipHeader->m_byVerHLen & 0xf);
if((ipHeader->m_byProtocol == IPPROTO_TCP))
{
TCPHeader *tcp = (TCPHeader *)(recvBuf + ipHLen);
if(!sniffer->purgeTCPProtocol(tcp, info)) continue;
}
else if(ipHeader->m_byProtocol == IPPROTO_UDP)
{
UDPHeader *udp = (UDPHeader *)(recvBuf + ipHLen);
if(!sniffer->purgeUDPProtocol(udp, info)) continue;
}
else if(ipHeader->m_byProtocol == IPPROTO_ICMP)
{
ICMPHeader *icmp = (ICMPHeader *)(recvBuf + ipHLen);
if(!sniffer->purgeICMPProtocol(icmp, info)) continue;
}
int cpysize = ntohs(ipHeader->m_usTotalLen) - ipHLen - 8;
szPtr = recvBuf + ipHLen + 8; memcpy(msg, szPtr, cpysize);
info.m_dataPack = QS("%1").arg(msg);
ptr->setPtr(&info, sizeof(info));
sniffer->m_callback.pfnMessage(ptr);
Sleep(5);
}
}
void RawSniffer::setSrcIPs(const ULongArr &ips)
{
m_srcIP.append(ips);
}
void RawSniffer::setDesIPs(const ULongArr &ips)
{
m_desIP.append(ips);
}
void RawSniffer::setSrcPorts(const UIntArr &ports)
{
m_srcPort.append(ports);
}
void RawSniffer::setDesPorts(const UIntArr &ports)
{
m_desPort.append(ports);
}
void RawSniffer::setSrcIPs(const QStringList &ips)
{
for(int idx = 0; idx < ips.length(); ++idx)
{
QString ip = ips[idx];
ulong lip = inet_addr(ip.toLocal8Bit().constData());
m_srcIP.append(lip);
}
}
void RawSniffer::setDesIPs(const QStringList &ips)
{
for(int idx = 0; idx < ips.length(); ++idx)
{
QString ip = ips[idx];
ulong lip = inet_addr(ip.toLocal8Bit().constData());
m_desIP.append(lip);
}
}
void RawSniffer::setFilterIPs(const ULongArr &ips)
{
m_filterIP.append(ips);
}
void RawSniffer::setSnifferNIC(DoxNetworkCard card)
{
m_card = card;
}
void RawSniffer::setFilterPorts(const UIntArr &ports)
{
m_filterPort.append(ports);
}
void RawSniffer::setFilterIPs(const QStringList &ips)
{
for(int idx = 0; idx < ips.length(); ++idx)
{
QString ip = ips[idx];
ulong lip = inet_addr(ip.toLocal8Bit().constData());
m_filterIP.append(lip);
}
}
void RawSniffer::setSnifferType(DoxProtocolType type)
{
m_type = type;
}
void RawSniffer::setSrcPorts(const QStringList &ports)
{
for(int idx = 0; idx < ports.length(); ++idx)
{
uint port = ports[idx].toUInt();
if(!m_srcPort.contains(port)) m_srcPort.append(port);
}
}
void RawSniffer::setDesPorts(const QStringList &ports)
{
for(int idx = 0; idx < ports.length(); ++idx)
{
uint port = ports[idx].toUInt();
if(!m_desPort.contains(port)) m_desPort.append(port);
}
}
bool RawSniffer::filterPort(uint srcPort, uint desPort)
{
if(m_desPort.length() != 0 && !m_desPort.contains(desPort)) return true;
if(m_srcPort.length() != 0 && !m_srcPort.contains(srcPort)) return true;
if(m_filterPort.length() != 0)
{
if(m_filterPort.contains(desPort)) return true;
if(m_filterPort.contains(srcPort)) return true;
}
return false;
}
void RawSniffer::setFilterPorts(const QStringList &ports)
{
for(int idx = 0; idx < ports.length(); ++idx)
{
uint port = ports[idx].toUInt();
if(!m_filterPort.contains(port)) m_filterPort.append(port);
}
}
void RawSniffer::setCallbackFunc(const DoxExtraFunc &_fun)
{
m_callback = _fun;
}
bool RawSniffer::purgeTCPProtocol(const TCPHeader *tcp, DoxSnifferInfo &info)
{
if(filterPort(tcp->sport, tcp->dport)) return false;
info.m_src.m_Port = tcp->sport;
info.m_des.m_Port = tcp->dport;
return true;
}
bool RawSniffer::purgeUDPProtocol(const UDPHeader *udp, DoxSnifferInfo &info)
{
if(filterPort(udp->sport, udp->dport)) return false;
info.m_src.m_Port = udp->sport;
info.m_des.m_Port = udp->dport;
return true;
}
void RawSniffer::purgeIPHeader(const IPHeader *ipHeader, DoxSnifferInfo &info)
{
info.m_src.m_IP = QS(inet_ntoa(*(in_addr*)&ipHeader->m_ulSrcIP));
info.m_des.m_IP = QS(inet_ntoa(*(in_addr*)&ipHeader->m_ulDesIP));
info.m_TTL = ipHeader->m_byTTL;
info.m_packLength = ipHeader->m_usTotalLen;
info.m_Protocol = QS(getProtocol(ipHeader->m_byProtocol));
}
bool RawSniffer::purgeICMPProtocol(const ICMPHeader *icmp, DoxSnifferInfo &info)
{
return true;
}
下面是IP、ICMP、UDP、TCP数据声明:
struct IPHeader
{
byte m_byVerHLen; // 4位首部长度,4位IP版本号
byte m_byTOS; // 8位服务类型TOS
ushort m_usTotalLen; // 16位总长度(字节)
ushort m_usID; // 16位标识
ushort m_usFlagFragOffset; // 3位标志位
byte m_byTTL; // 8位生存时间 TTL
byte m_byProtocol; // 8位协议 (TCP, UDP 或其他)
ushort m_usHChecksum; // 16位IP首部校验和
ulong m_ulSrcIP; // 32位源IP地址
ulong m_ulDesIP; // 32位目的IP地址
};
struct ICMPHeader
{
byte m_byType; //类型
byte m_byCode; //代码
ushort m_usChecksum; //检验和
ushort m_usID; //标识符
ushort m_usSeq; //序号
ulong m_ulTimeStamp; //时间戳(非标准ICMP头部)
};
struct TCPHeader
{
ushort sport; //16为源端口
ushort dport; //16位目标端口
uint seq; //32位序列号
uint ack; //32为确认号
uchar lenres; //4位首部长度/6位保留字
uchar flag; //6位标志位
ushort win; //16位窗口大小
ushort sum; //16位校验和
ushort urp; //16位紧急数据偏移量
};
struct UDPHeader
{
ushort sport; //16为源端口
ushort dport; //16位目的端口
ushort len; //4位首部长度/6位保留字
ushort sum; //16位检验和
};
源程序下载地址:https://download.csdn.net/download/yangfahe1/10909507
示例程序运行方式:https://blog.csdn.net/yangfahe1/article/details/84028318