SmipleSniffer代码学习

0.1 实现基本框架

// HexView.cpp : implementation file
//

#include "stdafx.h"
#include "SimpleSniffer.h"
#include "HexView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CHexView

IMPLEMENT_DYNCREATE(CHexView, CEditView)

CHexView::CHexView()
{
}

CHexView::~CHexView()
{
}


BEGIN_MESSAGE_MAP(CHexView, CEditView)
	//{{AFX_MSG_MAP(CHexView)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CHexView drawing

void CHexView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
	// TODO: add draw code here
}

/
// CHexView diagnostics

#ifdef _DEBUG
void CHexView::AssertValid() const
{
	CEditView::AssertValid();
}

void CHexView::Dump(CDumpContext& dc) const
{
	CEditView::Dump(dc);
}
#endif //_DEBUG

/
// CHexView message handlers

void CHexView::ShowHexText(char *data, int len)
{
}

2.1.4 删除所有 TODO 注释

// DevSelector.cpp : implementation file
//

#include "stdafx.h"
#include "SimpleSniffer.h"
#include "DevSelector.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CDevSelector dialog


CDevSelector::CDevSelector(CWnd* pParent /*=NULL*/)
	: CDialog(CDevSelector::IDD, pParent)
{
	//{{AFX_DATA_INIT(CDevSelector)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
}


void CDevSelector::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDevSelector)
	DDX_Control(pDX, IDC_DEVS, m_devsName);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CDevSelector, CDialog)
	//{{AFX_MSG_MAP(CDevSelector)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CDevSelector message handlers

// CDevSelector 初始化的时候获取设备列表
void CDevSelector::InitWinPcap()
{
	pcap_if_t *alldevs;
	pcap_if_t *d;
	char errbuf[PCAP_ERRBUF_SIZE];

	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1){
		::AfxMessageBox("获取设备列表失败");
		return;
	}

	for (d = alldevs; d; d = d->next){
		this->m_devsName.AddString(d->description);
		this->m_devsArray.push_back(d);
	}

	this->UpdateData(false);

	// 默认选中第一个设备, 如果只有一个设备, 直接点确认就可以了
	this->m_devsName.SetCurSel(0);
}

// 析构的时候释放设备列表
CDevSelector::~CDevSelector()
{
	// 如果获取设备失败, m_devArray 为空, 释放就会出问题
	// 因此判断不空之后才调用 pcap_freealldevs
	if(!this->m_devsArray.empty())
		pcap_freealldevs(*(this->m_devsArray.begin()));
}

// 初始化
BOOL CDevSelector::OnInitDialog() 
{
	CDialog::OnInitDialog();

	this->InitWinPcap();

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

// 点击了对话框的"确定"按钮, pcap_open 选中的设备
void CDevSelector::OnOK() 
{
	char errbuf[PCAP_ERRBUF_SIZE];

	pcap_if_t *d = this->m_devsArray[this->m_devsName.GetCurSel()];
	if ((theApp.m_curDev = pcap_open(d->name, /* name of the device */
		65536,/* portion of the packet to capture , 65535 guarantees that the whole packet will be captured on all the link layers */
		PCAP_OPENFLAG_PROMISCUOUS,/* promiscuous mode */
		1000,/* read timeout */
		NULL,/* authentication on the remote machine */
		errbuf/* error buffer */)) == NULL)
	{
		::AfxMessageBox("打开适配器失败!");
		theApp.m_curDev = NULL;
		return;
	}

	CDialog::OnOK();
}

1.2.9 实现了IPv6的扩展首部 分析

#include "stdafx.h"
#include <iostream>
#include <string.h>
#include "Head.h"

using namespace std;

extern int packet_kind;
extern unsigned char m_SIP[4];
extern unsigned char m_DIP[4];
extern unsigned char m_SIPv6[16];
extern unsigned char m_DIPv6[16];
extern int ipv6;	
extern int remain_len;

const CString sign_ip="0800";
const CString sign_arp="0806";
const CString sign_ipv6="86DD";

void Head_Ethernet::analysis(u_char *pkt_data)
{
	CString m_kind;

	memcpy(D_Mac,pkt_data,6);
	memcpy(S_Mac,pkt_data+6,6);
	memcpy(kind,pkt_data+12,2);
	m_kind.Format("%02X%02X",kind[0],kind[1]);
	//判断下一层协议
	remain_len=remain_len-14;
	if(m_kind.Compare(sign_ip) == 0)
	{
		next=new Head_IP();
		next->analysis(pkt_data+14);
	}
	else if(m_kind.Compare(sign_arp) == 0)
	{
		next=new Head_ARP();
		next->analysis(pkt_data+14);
	}
	else if(m_kind.Compare(sign_ipv6) == 0)
	{
		next=new Head_IPv6();
		next->analysis(pkt_data+14);
	}
	else
	{
		next=NULL;
		packet_kind=0;
	}
}

CString Head_Ethernet::my_print()
{
	CString m_SMac;
	CString m_DMac;
	CString m_Kind;

	m_SMac.Format("源MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",S_Mac[0],S_Mac[1],S_Mac[2],S_Mac[3],S_Mac[4],S_Mac[5]);
	m_DMac.Format("目的MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",D_Mac[0],D_Mac[1],D_Mac[2],D_Mac[3],D_Mac[4],D_Mac[5]);
	m_Kind.Format("类型: %02X%02X\r\n",kind[0],kind[1]);

	return "Ethernet首部\r\n"+m_SMac+m_DMac+m_Kind;
}

void Head_802_3::analysis(u_char *pkt_data)
{
	CString m_kind;

	memcpy(D_Mac,pkt_data,6);
	memcpy(S_Mac,pkt_data+6,6);
	memcpy(kind,pkt_data+20,2);
	m_kind.Format("%02X%02X",kind[0],kind[1]);
	//判断下一层协议
	remain_len=remain_len-22;
	if(m_kind.Compare(sign_ip) == 0)
	{
		next=new Head_IP();
		next->analysis(pkt_data+22);
	}
	else if(m_kind.Compare(sign_arp) == 0)
	{
		next=new Head_ARP();
		next->analysis(pkt_data+22);
	}
	else if(m_kind.Compare(sign_ipv6) == 0)
	{
		next=new Head_IPv6();
		next->analysis(pkt_data+22);
	}
	else
	{
		next=NULL;
		packet_kind=1;
	}
}

CString Head_802_3::my_print()
{
	CString m_SMac;
	CString m_DMac;
	CString m_Kind;

	m_SMac.Format("源MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",S_Mac[0],S_Mac[1],S_Mac[2],S_Mac[3],S_Mac[4],S_Mac[5]);
	m_DMac.Format("目的MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",D_Mac[0],D_Mac[1],D_Mac[2],D_Mac[3],D_Mac[4],D_Mac[5]);
	m_Kind.Format("类型: %02X%02X\r\n",kind[0],kind[1]);

	return "802.3帧首部\r\n"+m_SMac+m_DMac+m_Kind;
}

void Head_ARP::analysis(u_char *pkt_data)
{
	memcpy(op,pkt_data+6,2);
	memcpy(S_Mac,pkt_data+8,6);
	memcpy(S_IP,pkt_data+14,4);
	
	memcpy(D_Mac,pkt_data+18,6);
	memcpy(D_IP,pkt_data+24,4);

	memcpy(m_SIP,pkt_data+14,4);
	memcpy(m_DIP,pkt_data+24,4);
	ipv6=0;
	next=NULL;						//ARP就到头了
	packet_kind=2;
}

CString Head_ARP::my_print()
{
	CString m_OP;
	CString m_SMac;
	CString m_SIP;
	CString m_DMac;
	CString m_DIP;
	int mOP=0;
	mOP=op[0]<<8 | op[1];
	m_OP.Format("操作字段:%d\r\n",mOP);
	m_SMac.Format("源MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",S_Mac[0],S_Mac[1],S_Mac[2],S_Mac[3],S_Mac[4],S_Mac[5]);
	m_DMac.Format("目的MAC: %02X-%02X-%02X-%02X-%02X-%02X\r\n",D_Mac[0],D_Mac[1],D_Mac[2],D_Mac[3],D_Mac[4],D_Mac[5]);
	m_SIP.Format("源IP: %u.%u.%u.%u\r\n",S_IP[0],S_IP[1],S_IP[2],S_IP[3]);
	m_DIP.Format("目的IP: %u.%u.%u.%u\r\n",D_IP[0],D_IP[1],D_IP[2],D_IP[3]);
	
	return "ARP首部\r\n"+m_OP+m_SMac+m_SIP+m_DMac+m_DIP;
}

void Head_IP::analysis(u_char *pkt_data)
{
	version=(pkt_data[0] & 0xf0) >> 4;
	len=pkt_data[0] & 0x0f;
	memcpy(sign,pkt_data+4,2);
	TTL=pkt_data[8];
	//memcpy(TTl,pkt_date+8,1);
	protocol=pkt_data[9] & 0xff;
	memcpy(S_IP,pkt_data+12,4);
	memcpy(D_IP,pkt_data+16,4);
	//设置全局变量
	memcpy(m_SIP,pkt_data+12,4);
	memcpy(m_DIP,pkt_data+16,4);
	ipv6=0;

	//下一层协议判断
	remain_len=remain_len-len*4;
	if(remain_len == 0)
	{
		next=NULL;
		packet_kind=3;
	}
	else if(protocol == 1)
	{
		next=new Head_ICMP();
		next->analysis(pkt_data+len*4);
	}
	else if(protocol == 2)
	{
		next=new Head_IGMP();
		next->analysis(pkt_data+len*4);
	}
	else if(protocol == 6)
	{
		next=new Head_TCP();
		next->analysis(pkt_data+len*4);
	}
	else if(protocol == 17)
	{
		next=new Head_UDP();
		next->analysis(pkt_data+len*4);
	}
	else
	{
		next=NULL;
		packet_kind=3;
	}
}

CString Head_IP::my_print()
{
	CString m_version_len;
	CString m_sign;
	CString m_TTL;
	CString m_SIP;
	CString m_DIP;
	int mSign=0;
	mSign=sign[0]<<8 | sign[1];
	m_version_len.Format("版本: %d   长度: %d\r\n",version,len);
	m_sign.Format("标识符: %d\r\n",mSign);
	m_TTL.Format("存活时间: %u\r\n",TTL);
	m_SIP.Format("源IP: %u.%u.%u.%u\r\n",S_IP[0],S_IP[1],S_IP[2],S_IP[3]);
	m_DIP.Format("目的IP: %u.%u.%u.%u\r\n",D_IP[0],D_IP[1],D_IP[2],D_IP[3]);

	return "IP首部\r\n"+m_version_len+m_sign+m_TTL+m_SIP+m_DIP;
}

void Head_ICMP::analysis(u_char *pkt_data)
{
	kind=pkt_data[0] & 0xff;
	code=pkt_data[1] & 0xff;

	next=NULL;  //ICMP就到头了
	packet_kind=4;
}

CString Head_ICMP::my_print()
{
	CString m_kind;
	CString m_code;

	m_kind.Format("类型: %d\r\n",kind);
	m_code.Format("代码: %d\r\n",code);

	return "ICMP首部\r\n"+m_kind+m_code;
}

void Head_UDP::analysis(u_char *pkt_data)
{
	memcpy(S_Port,pkt_data,2);
	memcpy(D_Port,pkt_data+2,2);
	
	int sPort=S_Port[0]<<8 | S_Port[1];
	int dPort=D_Port[0]<<8 | D_Port[1];
	if(sPort == 53 || dPort == 53)
	{
		next=new Head_DNS();
		next->analysis(pkt_data+8);
	}
	else
	{
		next=NULL; 
		packet_kind=5;
	}
}

CString Head_UDP::my_print()
{
	CString m_SPort;
	CString m_DPort;
	int sPort=0,dPort=0;
	sPort=S_Port[0]<<8 | S_Port[1];
	dPort=D_Port[0]<<8 | D_Port[1];
	//m_SPort.Format("源端口: %02X%02X\r\n",S_Port[0],S_Port[1]);
	//m_DPort.Format("目的端口: %02X%02X\r\n",D_Port[0],D_Port[1]);
	m_SPort.Format("源端口: %d\r\n",sPort);
	m_DPort.Format("目的端口: %d\r\n",dPort);

	return "UDP首部\r\n"+m_SPort+m_DPort;
}

void Head_IGMP::analysis(u_char *pkt_data)
{
	version=3;						//抓到的好像都是IGMPv3
	type=pkt_data[0];
	memcpy(Multicast,pkt_data+4,4);

	next=NULL;						//到头了
	packet_kind=6;
}

CString Head_IGMP::my_print()
{
	CString m_version;
	CString m_type;
	CString m_Multicast;

	m_version.Format("版本: %d\r\n",version);
	m_type.Format("类型: %u\r\n",type);
	m_Multicast.Format("D类IP地址: %u.%u.%u.%u\r\n",Multicast[0],Multicast[1],Multicast[2],Multicast[3]);
	
	return "IGMP首部\r\n"+m_version+m_type+m_Multicast;
}

void Head_TCP::analysis(u_char *pkt_data)
{
	memcpy(S_Port,pkt_data,2);
	memcpy(D_Port,pkt_data+2,2);
	memcpy(SYN,pkt_data+4,4);
	memcpy(ACK,pkt_data+8,4);
	memcpy(Size_Window,pkt_data+14,2);
	
	int sPort=S_Port[0]<<8 | S_Port[1];
	int dPort=D_Port[0]<<8 | D_Port[1];
	len=(pkt_data[12]& 0xf0) >> 4;
	remain_len=remain_len-len*4;
	if(remain_len == 0)
	{
		next=NULL;
		packet_kind=7;
	}
	else if(sPort == 80 || dPort == 80)
	{
		next=new Head_HTTP();
		next->analysis(pkt_data+len*4);
	}
	else if(sPort == 21 || dPort == 21)
	{
		next=new Head_FTP();
		next->analysis(pkt_data+len*4);
	}
	else
	{
		next=NULL;
		packet_kind=7;
	}
}

CString Head_TCP::my_print()
{
	CString m_SPort;
	CString m_DPort;
	CString m_SYN;
	CString m_ACK;
	CString m_Size_Window;
	CString m_len;

	int sPort=0,dPort=0;
	int mSYN=0,mACK=0;
	int mSize_Window;
	sPort=S_Port[0]<<8 | S_Port[1];
	dPort=D_Port[0]<<8 | D_Port[1];
	mSYN=SYN[0]<<24 | SYN[1]<<16 | SYN[2]<<8 | SYN[3];
	mACK=ACK[0]<<24 | ACK[1]<<16 | ACK[2]<<8 | ACK[3];
	mSize_Window=Size_Window[0]<<8 | Size_Window[1];
	
	
	m_SPort.Format("源端口: %d\r\n",sPort);
	m_DPort.Format("目的端口: %d\r\n",dPort);
	//m_SYN.Format("SYN: %d\r\n",mSYN);
	//m_ACK.Format("ACK: %d\r\n",mACK);
	m_len.Format("长度: %d\r\n",len*4);
	m_Size_Window.Format("窗口大小: %d\r\n",mSize_Window);

	return "TCP首部\r\n"+m_SPort+m_DPort+m_SYN+m_ACK+m_Size_Window+m_len;
}

void Head_IPv6 :: analysis(u_char *pkt_data)
{
	version=(pkt_data[0] & 0xf0) >> 4;
	protocol=pkt_data[6] & 0xff;
	memcpy(S_IPv6,pkt_data+8,16);
	memcpy(D_IPv6,pkt_data+24,16);
	//设置全局变量
	memcpy(m_SIPv6,pkt_data+8,16);
	memcpy(m_DIPv6,pkt_data+24,16);
	ipv6=1;
	sign=0;								//用于标记是否有扩展首部 0:没有 1:有

	//处理可选首部
	if(protocol == 0)					//IPv6中下一个首部是0时有扩展首部
	{
		protocol=pkt_data[40] & 0xff;
		extern_len=pkt_data[41] & 0xff;	//扩展首部长度,不包括开始的8个字符
		sign=1;
	}
	//下一层协议判断
	remain_len=remain_len-40;
	if(remain_len == 0)
	{
		next=NULL;
		packet_kind=8;
	}
	else if(protocol == 6)
	{
		next= new Head_TCP();
		if(sign ==1)
			next->analysis(pkt_data+40+8+extern_len*8);
		else
			next->analysis(pkt_data+40);
	}
	else if(protocol == 17)
	{
		next= new Head_UDP();
		if(sign == 1)
			next->analysis(pkt_data+40+8+extern_len*8);
		else
			next->analysis(pkt_data+40);
	}
	else if(protocol == 58 )
	{
		next= new Head_ICMP();
		if(sign == 1)
			next->analysis(pkt_data+40+8+extern_len*8);
		else
			next->analysis(pkt_data+40);
	}
	else if(protocol == 2)
	{
		next=new Head_IGMP();
		if(sign == 1)
			next->analysis(pkt_data+40+8+extern_len*8);
		else
			next->analysis(pkt_data+40);
	}
	else if(protocol ==89)
	{
		next=new Head_OSPF();
		if(sign == 1)
			next->analysis(pkt_data+40+8+extern_len*8);
		else
			next->analysis(pkt_data+40);
	}
	else
	{
		next=NULL;
		packet_kind=8;
	}
}

CString Head_IPv6:: my_print()
{
	CString m_version;
	CString m_protocol;
	CString m_SIP;
	CString m_DIP;

	m_version.Format("版本: %d\r\n",version);
	m_protocol.Format("协议层协议值: %d\r\n",protocol);
	m_SIP.Format("源地址:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\r\n",S_IPv6[0],S_IPv6[1],S_IPv6[2],S_IPv6[3],S_IPv6[4],S_IPv6[5],S_IPv6[6],S_IPv6[7],S_IPv6[8],S_IPv6[9],S_IPv6[10],S_IPv6[11],S_IPv6[12],S_IPv6[13],S_IPv6[14],S_IPv6[15]);
	m_DIP.Format("目的地址:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\r\n",D_IPv6[0],D_IPv6[1],D_IPv6[2],D_IPv6[3],D_IPv6[4],D_IPv6[5],D_IPv6[6],D_IPv6[7],D_IPv6[8],D_IPv6[9],D_IPv6[10],D_IPv6[11],D_IPv6[12],D_IPv6[13],D_IPv6[14],D_IPv6[15]);
	
	return "IPv6首部\r\n"+m_version+m_protocol+m_SIP+m_DIP;
}

void Head_OSPF::analysis(u_char *pkt_data)
{
	version=pkt_data[0] & 0xff;
	type=pkt_data[1] & 0xff;
	memcpy(Router_ID,pkt_data+4,4);
	memcpy(Area_ID,pkt_data+8,4);

	next=NULL;
	packet_kind=9;
}

CString Head_OSPF::my_print()
{
	CString m_version;
	CString m_type;
	CString m_RouterID;
	CString m_AreaID;

	m_version.Format("版本: %d\r\n",version);
	m_type.Format("类型: %d\r\n",type);
	m_RouterID.Format("路由器ID: %u.%u.%u.%u\r\n",Router_ID[0],Router_ID[1],Router_ID[2],Router_ID[3]);
	m_AreaID.Format("区域ID: %u.%u.%u.%u\r\n",Area_ID[0],Area_ID[1],Area_ID[2],Area_ID[3]);

	return "OSPF首部\r\n"+m_version+m_type+m_RouterID+m_AreaID;
}

void Head_DNS::analysis(u_char *pkt_data)
{
	memcpy(ID,pkt_data,2);
	Question=pkt_data[0]<<8 ||pkt_data[1];

	next=NULL;
	packet_kind=10;
}

CString Head_DNS::my_print()
{
	CString m_ID;
	CString m_Question;

	m_ID.Format("标识: 0x%02x%02x\r\n",ID[0],ID[1]);
	m_Question.Format("问题数: %d\r\n",Question);

	return "DNS首部\r\n"+m_ID+m_Question;
}

void Head_HTTP::analysis(u_char *pkt_data)
{
	next=NULL;
	packet_kind=11;
}

CString Head_HTTP::my_print()
{
	return "HTTP首部\r\n";
}

void Head_FTP::analysis(u_char *pkt_data)
{
	next=NULL;
	packet_kind=12;
}

CString Head_FTP::my_print()
{
	return "FTP首部\r\n";
}

2.1.4 删除所有 TODO 注释

// HexView.cpp : implementation file
//

#include "stdafx.h"
#include "SimpleSniffer.h"
#include "HexView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CHexView

IMPLEMENT_DYNCREATE(CHexView, CEditView)

CHexView::CHexView()
{
	// CHexView 用于显示十六进制信息
	// 初始化 theApp 中的 Hex 指针为 this
	theApp.m_editor = dynamic_cast<Hex*>(this);
}

CHexView::~CHexView()
{
}


BEGIN_MESSAGE_MAP(CHexView, CEditView)
	//{{AFX_MSG_MAP(CHexView)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CHexView drawing

void CHexView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
}

/
// CHexView diagnostics

#ifdef _DEBUG
void CHexView::AssertValid() const
{
	CEditView::AssertValid();
}

void CHexView::Dump(CDumpContext& dc) const
{
	CEditView::Dump(dc);
}
#endif //_DEBUG

/
// CHexView message handlers

// 实现十六进制的显示, 是 Hex 的纯虚函数
void CHexView::ShowHexText(char *data, int len)
{
	CString result; // 存储最终结果
	CString temp; // 临时存储中间结果
	int lineHead; // 行首的偏移

	for(lineHead = 0; lineHead < len; lineHead += 16)
	{
		// 打印行首偏移
		temp.Format("%04X: ", lineHead);
		result += temp;

		CString hex; // 一行的16进制字符串形式
		CString asc; // 一行的ASCII码形式
		int pos; // 行内偏移
		int lineLength = len - lineHead >= 16 ? 16 : len - lineHead; // 这行要打印的字节个数

		for(pos = 0; pos < lineLength; ++pos)
		{
			unsigned char c = (unsigned char)data[lineHead + pos];

			// 16进制格式
			if(pos != 8)
				temp.Format(" %02X", c);
			else
				temp.Format("-%02X", c);
			hex += temp;

			// ASCII格式
			asc += _istprint(c) ? c : '.';
		}

		result += hex;
		if(pos < 16)
		{
			CString sPad(' ', 3 * (16 - pos));
			result += sPad;
		}
		result += "  ";
		result += asc;
		result += "\r\n";
	}

	// 显示出来吧!
	this->SetWindowText(result);
}

// 初始化, 设置编辑区只读、更改字体
void CHexView::OnInitialUpdate() 
{
	CEditView::OnInitialUpdate();
	
	static BOOL inited = FALSE;
	if(inited) return;
	inited = TRUE;
	// 以下代码只在首次调用 OnInitialUpdate 时执行

	CEdit& control = this->GetEditCtrl();
	control.SetReadOnly();// 编辑区只读, 不允许手动更改

	// 设置字体为"宋体" 以达到 空格与字母等宽的效果
	this->m_Font.CreatePointFont(120, "宋体");
	this->SetFont(&this->m_Font, false);
}

全部完成

// InfoView.cpp : implementation file
//

#include "stdafx.h"
#include "SimpleSniffer.h"
#include "InfoView.h"
#include "Thread.h"
#include "Info.h"
#include "Head.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern int count;
extern int packet_kind;
extern unsigned char m_SIP[4];
extern unsigned char m_DIP[4];
extern unsigned char m_SIPv6[16];
extern unsigned char m_DIPv6[16];
extern int ipv6;	
extern int remain_len;

/
// CInfoView

IMPLEMENT_DYNCREATE(CInfoView, CListView)

CInfoView::CInfoView()
{
	theApp.m_infoView = this;
}

CInfoView::~CInfoView()
{
}


BEGIN_MESSAGE_MAP(CInfoView, CListView)
	//{{AFX_MSG_MAP(CInfoView)
	ON_MESSAGE(WM_TCATCH, OnTCatch)
	ON_NOTIFY_REFLECT(NM_CLICK, OnClick)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CInfoView drawing

void CInfoView::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
}

/
// CInfoView diagnostics

#ifdef _DEBUG
void CInfoView::AssertValid() const
{
	CListView::AssertValid();
}

void CInfoView::Dump(CDumpContext& dc) const
{
	CListView::Dump(dc);
}
#endif //_DEBUG

/
// CInfoView message handlers

// 处理抓包线程抓到包的事件, pkt_data 是抓到的包
void CInfoView::OnTCatch(struct pcap_pkthdr *header, u_char *pkt_data)
{
	struct tm *ltime;
	char timestr[16];						//用于存储时间
	CString line_num,m_len,m_smac,m_dmac;	//用于输出格式转化
	CString m_kind;							//用于记录类型
	CString m_cntl;							//用于测试是不是802.3帧
	CString m_packetkind;					//用于显示数组包类型
	CString m_s_ip;							//用于显示源ip
	CString m_d_ip;							//用于显示目的ip
	Info temp_info;							//用于添加所捕获的数据包
	u_char S_mac[6];						//存源MAC
	u_char D_mac[6];						//存目的MAC
	u_char Kind[2];							//存以太帧类型
	u_char Cntl[1];							//如果是802.3帧,就应该是03
	remain_len=header->len;					//初始化
	//存储数据包
	temp_info.header=header;
	temp_info.pkt_data=pkt_data;
	

	//处理header获得时间,长度信息
	ltime = localtime(&header->ts.tv_sec);
	strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);
	line_num.Format("%d", count++);                           //count是一个全局变量用于记录行号
	m_len.Format("%d",header->len);

	//处理pkt_data得到详细信息
	memcpy(D_mac,pkt_data,6);
	memcpy(S_mac,pkt_data+6,6);
	memcpy(Kind,pkt_data+12,2);
	memcpy(Cntl,pkt_data+16,1);
	m_dmac.Format("%02X-%02X-%02X-%02X-%02X-%02X",D_mac[0],D_mac[1],D_mac[2],D_mac[3],D_mac[4],D_mac[5]);
	m_smac.Format("%02X-%02X-%02X-%02X-%02X-%02X",S_mac[0],S_mac[1],S_mac[2],S_mac[3],S_mac[4],S_mac[5]);
	m_kind.Format("%02X%02X",Kind[0],Kind[1]);
	m_cntl.Format("%02X",Cntl[0]);

	//第二步详细分析
	
	if(m_kind.Compare("0800")==0 || m_kind.Compare("0806")==0 || m_kind.Compare("86DD")==0)
	{
		temp_info.m_Head=new Head_Ethernet();
		temp_info.m_Head->analysis(pkt_data);
	}
	else
	{
		temp_info.m_Head=new Head_802_3();
		temp_info.m_Head->analysis(pkt_data);
	}
	
	m_info.push_back(temp_info);
	if(ipv6==0)
	{
		m_s_ip.Format("%u.%u.%u.%u",m_SIP[0],m_SIP[1],m_SIP[2],m_SIP[3]);
		m_d_ip.Format("%u.%u.%u.%u",m_DIP[0],m_DIP[1],m_DIP[2],m_DIP[3]);
	}
	else
	{
		ipv6_normal_print(m_SIPv6,m_s_ip);
		ipv6_normal_print(m_DIPv6,m_d_ip);
	}
	switch(packet_kind){
	case 0:m_packetkind="Ethernet";break;
	case 1:m_packetkind="802.3";break;
	case 2:m_packetkind="ARP";break;
	case 3:m_packetkind="IP";break;
	case 4:m_packetkind="ICMPv6";break;
	case 5:m_packetkind="UDP";break;
	case 6:m_packetkind="IGMPv3";break;
	case 7:m_packetkind="TCP";break;
	case 8:m_packetkind="IPv6";break;
	case 9:m_packetkind="OSPF";break;
	case 10:m_packetkind="DNS";break;
	case 11:m_packetkind="HTTP";break;
	case 12:m_packetkind="FTP";break;
	}
	//在列表中显示
	CListCtrl& ctr = this->GetListCtrl();
	
	int row = ctr.InsertItem(ctr.GetItemCount(), line_num);   //获得当前所要输出的行号
	ctr.SetItemText(row, 1, timestr);
	ctr.SetItemText(row, 2, m_len);
	ctr.SetItemText(row, 3, m_s_ip);
	ctr.SetItemText(row, 4, m_d_ip);
	ctr.SetItemText(row, 5, m_packetkind);

	// 抓到包后设置文档已修改, 退出的时候就会提醒用户保存 dump 文件
	if(theApp.m_dumper)
		this->GetDocument()->SetModifiedFlag();
	else// 当前是抓pcap文件中的包, 不需要设置已修改标志
		;
}

// CInfoView 继承自列表视图(CListView), 这里设置好各个列
void CInfoView::OnInitialUpdate() 
{
	CListView::OnInitialUpdate();
	
	static BOOL inited = FALSE;
	if(inited) return;
	inited = TRUE;
	// 以下代码只在首次调用 OnInitialUpdate 时执行
	
	theApp.m_display = this->GetSafeHwnd();
	CListCtrl& m_list = GetListCtrl();
	LONG lStyle;
	lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);
	lStyle &= ~LVS_TYPEMASK;
	lStyle |= LVS_REPORT;
	SetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle); 
	DWORD dwStyle = m_list.GetExtendedStyle();
	dwStyle |= LVS_EX_FULLROWSELECT;
	dwStyle |= LVS_EX_GRIDLINES;
	m_list.SetExtendedStyle(dwStyle);
	m_list.SetBkColor(RGB(200, 200, 200));
	m_list.SetTextBkColor(RGB(200, 200, 200));
	m_list.SetTextColor(RGB(10, 10, 80));
	
	m_list.InsertColumn( 0, "序号", LVCFMT_CENTER, 50);
	m_list.InsertColumn( 1, "时间", LVCFMT_CENTER, 100); 
	m_list.InsertColumn( 2, "长度", LVCFMT_CENTER,100 );
	
	//第二步详细分析显示
	m_list.InsertColumn( 3,"源IP",LVCFMT_CENTER, 300 );
	m_list.InsertColumn( 4,"目的IP",LVCFMT_CENTER, 300 );
	m_list.InsertColumn( 5,"包类型",LVCFMT_CENTER, 150 );
}

// 点击列表中某行后, 显示它的包类型、16进制形式的包数据
void CInfoView::OnClick(NMHDR* pNMHDR, LRESULT* pResult) 
{	
	NMLISTVIEW* pList = (NMLISTVIEW*)pNMHDR;
	CString m_message;						//初始化就是空的
	Head_Super* head_temp;
    int iItem = pList->iItem;
    if(iItem != -1)
    {
        theApp.m_editor->ShowHexText((char*)m_info[iItem].pkt_data, m_info[iItem].header->len);
		head_temp=m_info[iItem].m_Head;
		while(head_temp!=NULL)
		{
			m_message=m_message+head_temp->my_print()+"\r\n";
			head_temp=head_temp->next;
		}
		theApp.m_packInfo->ShowPackInfo(m_message);
    }
    *pResult = 0;
}

// 清空列表, 开始新的抓包前调用这个这个函数
void CInfoView::clearList()
{
	count = 0;
	this->m_info.clear();
	this->GetListCtrl().DeleteAllItems();
}

// 用于标准化ipv6的ip地址
void CInfoView::ipv6_normal_print(unsigned char *ipv6,CString &out)
{
	CString ip_temp[8];
	int sign_temp[8];
	int i,j;
	int count=0;				//用于标识,只能有一次格式缩进,一般取第一次连续多个零进行缩进

	for(i=0,j=0;i<16;i=i+2,j++)
	{
		ip_temp[j].Format("%02X%02X",ipv6[i],ipv6[i+1]);
		if(ip_temp[j].Compare("0000")==0)
			sign_temp[j]=0;
		else
			sign_temp[j]=1;
	}
	for(i=0;i<8;i++)
	{
		if(sign_temp[i]==0 && count==0)
		{
			for(j=i;j<8;j++)
			{
				if(sign_temp[j]!=0)
					break;
			}
			if(j==8)
				out=out+"::";
			else
				out=out+":";
			i=j-1;
			count=1;
		}
		else
		{
			if(i==0)
				out=ip_temp[i];
			else
				out=out+":"+ip_temp[i];
		}
	}
}

2.1.4 删除所有 TODO 注释

// MainFrm.cpp : implementation of the CMainFrame class
//

#include "stdafx.h"
#include "SimpleSniffer.h"

#include "MainFrm.h"
#include "InfoView.h"
#include "HexView.h"
#include "PackInfo.h"
#include "DevSelector.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CMainFrame

IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
	//{{AFX_MSG_MAP(CMainFrame)
	ON_WM_CREATE()
	ON_COMMAND(ID_SELECTSTART, OnSelectstart)
	ON_COMMAND(ID_ENDCATCH, OnEndcatch)
	ON_UPDATE_COMMAND_UI(ID_SELECTSTART, OnUpdateSelectstart)
	ON_UPDATE_COMMAND_UI(ID_ENDCATCH, OnUpdateEndcatch)
	ON_MESSAGE(WM_TEXIT, OnTExit)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
	ON_UPDATE_COMMAND_UI(ID_FILE_OPEN, OnUpdateFileOpen)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

static UINT indicators[] =
{
	ID_SEPARATOR,           // status line indicator
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
	ID_INDICATOR_SCRL,
};

/
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
}

CMainFrame::~CMainFrame()
{
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
		| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
		!m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
	{
		TRACE0("Failed to create toolbar\n");
		return -1;      // fail to create
	}

	if (!m_wndStatusBar.Create(this) ||
		!m_wndStatusBar.SetIndicators(indicators,
		  sizeof(indicators)/sizeof(UINT)))
	{
		TRACE0("Failed to create status bar\n");
		return -1;      // fail to create
	}

	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
	EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar(&m_wndToolBar);

	return 0;
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
	if( !CFrameWnd::PreCreateWindow(cs) )
		return FALSE;
	return TRUE;
}

/
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CFrameWnd::Dump(dc);
}

#endif //_DEBUG

/
// CMainFrame message handlers

// 在这里创建3行1列分割窗体
BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
	theApp.m_control = this->GetSafeHwnd();// CMainFrame 控制线程启动和终止

	CRect rc;

    // 获取框架窗口客户区的CRect对象
    GetClientRect(&rc);

    // 创建静态分割窗口,三行一列
    if (!m_wndSplitter.CreateStatic(this, 3, 1, WS_CHILD | WS_VISIBLE))
        return FALSE;

	if (!m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(CInfoView), CSize(rc.Width(), rc.Height()/3), pContext))
        return FALSE;
	if (!m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(CPackInfo), CSize(rc.Width(), rc.Height()/4), pContext))
        return FALSE;
    if (!m_wndSplitter.CreateView(2, 0, RUNTIME_CLASS(CHexView), CSize(rc.Width(), rc.Height()/2), pContext))
        return FALSE;

    return TRUE;
}

// 点击了"开始"工具栏按钮, 弹出 CDevSelector 选中设备进行抓包
void CMainFrame::OnSelectstart() 
{
	CDevSelector selector;

	if(IDOK == selector.DoModal() && theApp.m_curDev)
	{
		// 打开 tmp.pcap 接收包数据
		theApp.m_dumper = pcap_dump_open(theApp.m_curDev, theApp.m_tempDumpFilePath);
		theApp.startCatch(); // 启动线程抓包了
	}
}

// 点击了"终止"工具栏按钮, pcap_breakloop 正在监听的设备
void CMainFrame::OnEndcatch() 
{
	pcap_breakloop(theApp.m_curDev);
}

// 得到线程退出前发出的 WM_TEXIT 消息, 可以安全地释放各种资源了
void CMainFrame::OnTExit(int exitNum)
{
	// 关闭 网卡设备 和 dump文件
	pcap_close(theApp.m_curDev);
	if(theApp.m_dumper)
		pcap_dump_close(theApp.m_dumper);

	// 现在开始不再是"正在抓包"了
	theApp.m_iscatching = FALSE;
}

// "开始"按钮的使能控制
void CMainFrame::OnUpdateSelectstart(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(!theApp.m_iscatching);
}

// "终止"按钮的使能控制
void CMainFrame::OnUpdateEndcatch(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(theApp.m_iscatching);
}

// "保存"按钮的使能控制
void CMainFrame::OnUpdateFileSave(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(!theApp.m_iscatching);	
}

// "另存为"按钮的使能控制
void CMainFrame::OnUpdateFileSaveAs(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(!theApp.m_iscatching);	
}

// "打开"按钮的使能控制
void CMainFrame::OnUpdateFileOpen(CCmdUI* pCmdUI) 
{
	pCmdUI->Enable(!theApp.m_iscatching);	

2.1.4 删除所有 TODO 注释

2.1.4 删除所有 TODO 注释
…
Latest commit 324d7bf on 24 Dec 2012

2.1.4 删除所有 TODO 注释

// PackInfo.cpp : implementation file
//

#include "stdafx.h"
#include "SimpleSniffer.h"
#include "PackInfo.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CPackInfo

IMPLEMENT_DYNCREATE(CPackInfo, CEditView)

CPackInfo::CPackInfo()
{
	// CPackInfo 是用来显示抓到的包的各层PDU详细信息的
	theApp.m_packInfo = this;
}

CPackInfo::~CPackInfo()
{
}


BEGIN_MESSAGE_MAP(CPackInfo, CEditView)
	//{{AFX_MSG_MAP(CPackInfo)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CPackInfo drawing

void CPackInfo::OnDraw(CDC* pDC)
{
	CDocument* pDoc = GetDocument();
}

/
// CPackInfo diagnostics

#ifdef _DEBUG
void CPackInfo::AssertValid() const
{
	CEditView::AssertValid();
}

void CPackInfo::Dump(CDumpContext& dc) const
{
	CEditView::Dump(dc);
}
#endif //_DEBUG

/
// CPackInfo message handlers


// 初始化中设置编辑区为只读
void CPackInfo::OnInitialUpdate()
{
	CEditView::OnInitialUpdate();

	static BOOL inited = FALSE;
	if(inited) return;
	inited = TRUE;
	// 以下代码只在首次调用 OnInitialUpdate 时执行

	CEdit& control = this->GetEditCtrl();
	control.SetReadOnly();// 编辑区只读, 不允许手动更改
}

// 在编辑区中显示一段字符串
void CPackInfo::ShowPackInfo(const CString& info)
{
	this->SetWindowText(info);
}

2.1.10 启动新一次抓包前清空列表, 避免混乱


// SimpleSniffer.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "SimpleSniffer.h"

#include "MainFrm.h"
#include "SimpleSnifferDoc.h"
#include "InfoView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CSimpleSnifferApp

BEGIN_MESSAGE_MAP(CSimpleSnifferApp, CWinApp)
	//{{AFX_MSG_MAP(CSimpleSnifferApp)
	ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
	// Standard file based document commands
	ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
	ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
	// Standard print setup command
	ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup)
END_MESSAGE_MAP()

/
// CSimpleSnifferApp construction

// CSimpleSnifferApp 构造的时候初始化 tmp.pcap 文件的路径, 设置"正在抓包"标志为 FALSE
CSimpleSnifferApp::CSimpleSnifferApp()
{
	char buf[1024];
	GetCurrentDirectory(sizeof(buf),buf);
	this->m_tempDumpFilePath.Format("%s\\tmp.pcap", buf);

	this->m_iscatching = FALSE;
}

/
// The one and only CSimpleSnifferApp object

CSimpleSnifferApp theApp;
int count=1;
unsigned char m_SIP[4];
unsigned char m_DIP[4];
unsigned char m_SIPv6[16];
unsigned char m_DIPv6[16];
int ipv6=0;								//如果不是ipv6值为0 如果是值为1
int packet_kind=0;						//用于记录数据包分析到的最高层类型,0:Ethernet 1:802.3 2:ARP 3:IP 4:ICMP 5:UDP 6:IGMP 7:TCP
int remain_len;							//剩余的数据包长度,用于识别端口号为80的http

/
// CSimpleSnifferApp initialization

BOOL CSimpleSnifferApp::InitInstance()
{
	AfxEnableControlContainer();

	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	// Change the registry key under which our settings are stored.
	SetRegistryKey(_T("Local AppWizard-Generated Applications"));

	LoadStdProfileSettings();  // Load standard INI file options (including MRU)

	// Register the application's document templates.  Document templates
	//  serve as the connection between documents, frame windows and views.

	CSingleDocTemplate* pDocTemplate;
	pDocTemplate = new CSingleDocTemplate(
		IDR_MAINFRAME,
		RUNTIME_CLASS(CSimpleSnifferDoc),
		RUNTIME_CLASS(CMainFrame),       // main SDI frame window
		RUNTIME_CLASS(CInfoView));
	AddDocTemplate(pDocTemplate);

	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;
	ParseCommandLine(cmdInfo);

	// Dispatch commands specified on the command line
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;

	// The one and only window has been initialized, so show and update it.
	m_pMainWnd->ShowWindow(SW_SHOW);
	m_pMainWnd->UpdateWindow();

	return TRUE;
}

// 启动线程, 开始抓包
void CSimpleSnifferApp::startCatch()
{
	this->m_iscatching = TRUE;	// 设置"正在抓包"标志为 TRUE
	this->m_infoView->clearList();	// 清空之前抓到的包
	::AfxBeginThread(ThreadProc, new ThreadParam(m_curDev, m_dumper));// 启动抓包线程
}


/
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	CString	m_email;
	CString	m_github;
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	virtual BOOL OnInitDialog();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	m_email = _T("");
	m_github = _T("");
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	DDX_Text(pDX, IDC_EMAIL, m_email);
	DDX_Text(pDX, IDC_GITHUB, m_github);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

// App command to run the dialog
void CSimpleSnifferApp::OnAppAbout()
{
	CAboutDlg aboutDlg;
	aboutDlg.DoModal();
}

/
// CSimpleSnifferApp message handlers

// 关于对话框的初始化, 显示 github地址 和 我们的邮箱
BOOL CAboutDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();

	this->m_github = "https://github.com/1184893257/SimpleSniffer/tree/master/SimpleSniffer";
	this->m_email = "1184893257@qq.com";
	this->UpdateData(false);

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

2.1.4 删除所有 TODO 注释

// SimpleSnifferDoc.cpp : implementation of the CSimpleSnifferDoc class
//

#include "stdafx.h"
#include "SimpleSniffer.h"

#include "SimpleSnifferDoc.h"
#include "Thread.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/
// CSimpleSnifferDoc

IMPLEMENT_DYNCREATE(CSimpleSnifferDoc, CDocument)

BEGIN_MESSAGE_MAP(CSimpleSnifferDoc, CDocument)
	//{{AFX_MSG_MAP(CSimpleSnifferDoc)
		// NOTE - the ClassWizard will add and remove mapping macros here.
		//    DO NOT EDIT what you see in these blocks of generated code!
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/
// CSimpleSnifferDoc construction/destruction

CSimpleSnifferDoc::CSimpleSnifferDoc()
{
}

CSimpleSnifferDoc::~CSimpleSnifferDoc()
{
}

BOOL CSimpleSnifferDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	return TRUE;
}

// 将 src 文件的内容复制到 dest 文件
void copyFile(CFile *src, CFile *dest)
{
	char buf[1024];
	int n;

	while((n = src->Read(buf, sizeof(buf))) > 0)
		dest->Write(buf, n);
}

/
// CSimpleSnifferDoc serialization

//串行化中实现 保存/打开 逻辑
void CSimpleSnifferDoc::Serialize(CArchive& ar)
{
	CFile *f = ar.GetFile();

	// 如果是 tmp.pcap, 报错
	if(theApp.m_tempDumpFilePath.Compare(f->GetFilePath()) == 0)
	{
		CString s;
		s.Format("%s 文件用于存储当前抓到的包, 不作他用!", theApp.m_tempDumpFilePath);
		::AfxMessageBox(s);
		return;
	}

	// 如果是保存, 将 tmp.pcap 中的内容复制到 f 中
	if (ar.IsStoring())
	{
		CFile src(theApp.m_tempDumpFilePath, CFile::modeRead);
		copyFile(&src, f);
		src.Close();
	}

	// 如果是打开, 将该文件中的内容复制到 tmp.pcap, 启动线程从 tmp.pcap 读取包
	else
	{
		// 复制到 tmp.pcap
		CFile dest(theApp.m_tempDumpFilePath, CFile::modeWrite | CFile::modeCreate);
		copyFile(f, &dest);
		dest.Close();

		// 打开 tmp.pcap, 侦听, TExit 事件中关闭 tmp.pcap 文件
		FILE *fp = fopen(theApp.m_tempDumpFilePath, "rb");
		char errbuf[PCAP_ERRBUF_SIZE];
		theApp.m_curDev = pcap_fopen_offline(fp, errbuf);
		theApp.m_dumper = NULL;
		theApp.startCatch(); // 开始抓包, 还设置"正在抓包"标志
	}
}

/
// CSimpleSnifferDoc diagnostics

#ifdef _DEBUG
void CSimpleSnifferDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CSimpleSnifferDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/
// CSimpleSnifferDoc commands

2.1.2 将所有我们改动过的函数加一行总结性注释

#include "stdafx.h"
#include "SimpleSniffer.h"
#include "thread.h"
#include <pcap.h>

// pcap_loop 捕获到一个包后将包数据复制一份 并 发出WM_TCATCH消息
static void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
	struct pcap_pkthdr *new_header = new struct pcap_pkthdr;
	u_char *new_data = new u_char[header->len];

	if(param) // param 不是 NULL, 就存入文件
		pcap_dump(param, header, pkt_data);

	// 复制数据, 发出消息
	*new_header = *header;
	memcpy(new_data, pkt_data, header->len);
	::PostMessage(theApp.m_display, WM_TCATCH, (WPARAM)new_header, (LPARAM)new_data);
}

// 抓包线程的实现
UINT ThreadProc(LPVOID param)
{
	ThreadParam *p = (ThreadParam*)param;

	// 循环捕获包, 循环可以被 pcap_breakloop 终止
	int loopreturn = pcap_loop(p->m_dev, 0, packet_handler, (unsigned char*)p->m_dumper);
	delete p;

	// 退出前发出 WM_TEXIT 消息
	::PostMessage(theApp.m_control, WM_TEXIT, loopreturn, NULL);

	return 0;
}
P2P文件共享 前面有人文嗅探器的问题,我在这里做个详细的解释: 嗅探器(snifffer)就是能够捕获网络报文的设备。嗅探器的正当用处在于分析网络的流量,以便找出所关心的网络中潜在的问题。例如,假设网络的某一段运行得不是很好,报文的发送比较慢,而我们又不知道问题出在什么地方,此时就可以用嗅探器来作出精确的问题判断。 嗅探器在功能和设计方面有很多不同。有些只能分析一种协议,而另一些可能能够分析几百种协议。一般情况下,大多数的嗅探器至少能够分析下面的协议: ■标准以太网 ■TCP/IP ■IPX ■DECNet 嗅探器通常是软硬件的结合。专用的嗅探器价格非常昂贵。另一方面,免费的嗅探器虽然不需要花什么钱,但得不到什么支持。 嗅探器与一般的键盘捕获程序不同。键盘捕获程序捕获在终端上输入的键值,而嗅探器则捕获真实的网络报文。嗅探器通过将其置身于网络接口来达到这个目的——例如将以太网卡设置成杂收模式。(为了理解杂收模式是怎么回事,先解释局域网是怎么工作的)。 数据在网络上是以很小的称为帧(Ftame)的单位传输的帧由好几部分组成,不同的部分执行不同的功能。(例如,以太网的前12个字节存放的是源和目的的地址,这些位告诉网络:数据的来源和去处。以太网帧的其他部分存放实际的用户数据、TCP/IP的报文头或IPX报文头等等)。 帧通过特定的称为网络驱动程序的软件进行成型,然后通过网卡发送到网线上。通过网线到达它们的目的机器,在目的机器的一端执行相反的过程。接收端机器的以太网卡捕获到这些帧,并告诉操作系统帧的到达,然后对其进行存储。就是在这个传输和接收的过程中,嗅探器会造成安全方面的问题。 每一个在LAN上的工作站都有其硬件地址。这些地址唯一地表示着网络上的机器(这一点于Internet地址系统比较相似)。当用户发送一个报文时,这些报文就会发送到LAN上所有可用的机器。 在一般情况下,网络上所有的机器都可以“听”到通过的流量,但对不属于自己的报文则不予响应(换句话说,工作站A不会捕获属于工作站B的数据,而是简单的忽略这些数据)。 如果某在工作站的网络接口处于杂收模式,那么它就可以捕获网络上所有的报文和帧,如果一个工作站被配置成这样的方式,它(包括其软件)就是一个嗅探器。 嗅探器可能造成的危害: ■嗅探器能够捕获口令 ■能够捕获专用的或者机密的信息 ■可以用来危害网络邻居的安全,或者用来获取更高级别的访问权限 事实上,如果你在网络上存在非授权的嗅探器就以为着你的系统已经暴露在别人面前了。(大家可以试试天行2的嗅探功能) 一般我们只嗅探每个报文的前200到300个字节。用户名和口令都包含在这一部分中,这是我们关心的真正部分。工人,也可以嗅探给定接口上的所有报文,如果有足够的空间进行存储,有足够的那里进行处理的话,将会发现另一些非常有趣的东西…… 简单的放置一个嗅探器宾将其放到随便什么地方将不会起到什么作用。将嗅探器放置于被攻击机器或网络附近,这样将捕获到很多口令,还有一个比较好的方法就是放在网关上。如果这样的话就能捕获网络和其他网络进行身份鉴别的过程。这样的方式将成倍地增加我们能够攻击的范围。 关于怎么抵御嗅探器的攻击我就不说了,那是网管们的事儿,有三种方法可能会有所作用: ■检测和消灭嗅探器 ■将数据隐藏,使嗅探器无法发现。 ■会话加密
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值