Sniffer原理实现的代码
2005-07-05 17:10
344 查看
最近写的一个程序用到了windows下面的sniffer原理。刚刚完成了原型系统的构建,现在把它写下来。感谢raphyer 的文章:使用Sniffer截获流经本机网卡的IP数据包
很多代码是直接copy过来的,现鄙视自己一下。
在project->setting->link->object/library modules:添加Ws2_32.lib 库文件
在stdafx.h文件中:
#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);
}
}
}
很多代码是直接copy过来的,现鄙视自己一下。
在project->setting->link->object/library modules:添加Ws2_32.lib 库文件
在stdafx.h文件中:
#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);
}
}
}
相关文章推荐
- java NIO原理解析和代码实现
- Java NIO原理图文分析及代码实现
- 递归实现汉诺塔原理及核心代码
- SHA1摘要算法原理以及代码实现
- 转置矩阵的分块并行乘法(C语言实现),计算矩阵C[rawn][rawn]=A[rawm][rawn]'*B[rawm][rawn],子块大小为S*T,其算法实现原理参加本代码的附件。
- 归并排序算法原理分析与代码实现
- Java NIO原理图文分析及代码实现
- 图像去雾之何凯明暗通道先验去雾算法原理及c++代码实现
- AsyncTask实现代码原理
- 归并排序的原理及java代码实现
- K-means原理与代码实现
- Java NIO原理图文分析及代码实现
- Android中悬浮窗口的实现原理和示例代码
- java线程池的原理与代码实现
- 编译原理(一) Chomsky文法的判断方法及C++代码实现
- CreateRemoteThread_远程CALL调用代码实现原理。
- .net页面访问次数统计实现原理与代码
- autolayout的使用原理及代码实现
- 快速傅里叶变换(FFT)的原理、实现及代码解析(附C#源码)