NT下的SNIFFER

来源:互联网 发布:网站后台制作软件 编辑:程序博客网 时间:2024/04/28 09:27
include <winsock2.h>
#include <ws2tcpip.h> //用于IP_HDRINCL标记
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
#define BUFFER_SIZE 65535

typedef struct _TCP{ WORD SrcPort; // 源端口
WORD DstPort; // 目的端口
DWORD SeqNum; // 顺序号
DWORD AckNum; // 确认号
BYTE DataOff; // TCP头长
BYTE Flags; // 标志(URG、ACK等)
WORD Window; // 窗口大小
WORD Chksum; // 校验和
WORD UrgPtr; // 紧急指针
} TCP;
typedef TCP *LPTCP;
typedef TCP UNALIGNED * ULPTCP;
typedef struct _IP{
union{ BYTE Version; // 版本
BYTE HdrLen; // IHL
};
BYTE ServiceType; // 服务类型
WORD TotalLen; // 总长
WORD ID; // 标识
union{ WORD Flags; // 标志
WORD FragOff; // 分段偏移
};
BYTE TimeToLive; // 生命期
BYTE Protocol; // 协议
WORD HdrChksum; // 头校验和
DWORD SrcAddr; // 源地址
DWORD DstAddr; // 目的地址
BYTE Options; // 选项
} IP;
typedef IP * LPIP;
typedef IP UNALIGNED * ULPIP;
#define PROTOCOL_STRING_ICMP_TXT "ICMP"
#define PROTOCOL_STRING_TCP_TXT "TCP"
#define PROTOCOL_STRING_UDP_TXT "UDP"
#define PROTOCOL_STRING_SPX_TXT "SPX"
#define PROTOCOL_STRING_NCP_TXT "NCP"
#define PROTOCOL_STRING_UNKNOW_TXT "UNKNOW"

一个辅助函数,得到每一种协议的名字:

CString CABCDlg::GetProtocolTxt(int Protocol)
{
    switch (Protocol){
           case IPPROTO_ICMP : //1 /* control message protocol */
                return PROTOCOL_STRING_ICMP_TXT;
           case IPPROTO_TCP : //6 /* tcp */
                return PROTOCOL_STRING_TCP_TXT;
           case IPPROTO_UDP : //17 /* user datagram protocol */
                return PROTOCOL_STRING_UDP_TXT;
           default:
                return PROTOCOL_STRING_UNKNOW_TXT;

   }
}

监听的函数及过程:

void CABCDlg::OnButton1()
{
 // 检查 Winsock 版本号,WSAData为WSADATA结构对象
 WSADATA WSAData;
 WSAStartup(MAKEWORD(2, 2), &WSAData);
 // 创建原始套接字
 //SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
 SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);//第三个参数必须设置成IPPROTO_IP
 // 设置IP头操作选项,其中flag 设置为ture,亲自对IP头进行处理
 bool flag = true;
 setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag));
 // 获取本机名
 char LocalName[50];
 gethostname((char*)LocalName, sizeof(LocalName)-1);
 // 获取本地 IP 地址
 hostent* pHost = gethostbyname((char*)LocalName);
 // 填充SOCKADDR_IN结构
 sockaddr_in addr_in;
 addr_in.sin_addr = *(in_addr *)pHost->h_addr_list[0]; //IP
 addr_in.sin_family = AF_INET;
 addr_in.sin_port = htons(57274);
 // 把原始套接字sock 绑定到本地网卡地址上
 bind(sock, (PSOCKADDR)&addr_in, sizeof(addr_in));
 // dwValue为输入输出参数,为1时执行,0时取消
 DWORD dwValue = 1;
 // 设置 SOCK_RAW 为SIO_RCVALL,以便接收所有的IP包。其中SIO_RCVALL
 // 的定义为: #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
 ioctlsocket(sock, SIO_RCVALL, &dwValue);
 char RecvBuf[65535]={'0'};
 while (true)
 {
  // 接收原始数据包信息
  int ret = recv(sock, RecvBuf, BUFFER_SIZE, 0);
  if (ret > 0)
  {
   // 对数据包进行分析,并输出分析结果
   IP ip;
   TCP tcp;
   ip = *(IP*)RecvBuf;
   tcp = *(TCP*)(RecvBuf + ip.HdrLen);
   CString a;
   a.Format("协议:%s",GetProtocolTxt(ip.Protocol));
   AfxMessageBox(a);
   m_list.InsertString(-1,a);
   a.Format("IP源地址:%s",inet_ntoa(*(in_addr*)&ip.SrcAddr));
   AfxMessageBox(a);
   m_list.InsertString(-1,a);
   a.Format("IP目标地址:%s",inet_ntoa(*(in_addr*)&ip.DstAddr));
   AfxMessageBox(a);
   m_list.InsertString(-1,a);
   a.Format("源端口号:%d",tcp.SrcPort);
   AfxMessageBox(a);
   m_list.InsertString(-1,a);
   a.Format("目标端口号:%d",tcp.DstPort);
   AfxMessageBox(a);
   m_list.InsertString(-1,a);
   a.Format("数据包长度:%d",ntohs(ip.TotalLen));
    AfxMessageBox(a);
   m_list.InsertString(-1,a);   
  }
 }

}

原创粉丝点击