【WinPcap】自制抓包+分析+ARP攻击(一)

【WinPcap】自制抓包+分析+ARP攻击

开篇

刚学习WinPcap,所以想练练手,做一个抓包的,不是很好玩么,或许还可以写一下自己的ARP包,来个LAN欺骗~于是乎,花了5天的时间,把TCP/IP的几个协议格式大致整理了一下,思考了整个软件的布局之后,决定动手写一个,再也不靠WireShark(当然还没那么厉害大笑)抓包,自给自足才好嘛。这就是所谓的“最初动机”吧。然后就有了整个小玩意儿。今天下午想了想,为了今后有个记录(面试什么的能证明自己是吧,哈哈),自己可以查一查,于是打算再花大把时间来把整个过程,每个功能写清楚。

功能

①扫描并显示适配器;
②扫描LAN内活动主机;
③设置过滤格式;
④捕获数据包;
⑤分析包格式;
⑥自制包(目前只有ARP包……)

基础知识

这里,我是在windows下写的,所以用到了WinPcap开发者工具包,用了MFC类库,所以这两者还是要知道下。
第一步,就是环境的配置了,遇见问题的同学请看【WinPcap】编程环境搭建——VC++2013,里面有工具包下载地址什么的。
第二步,请先对TCP/IP中的ARP、IP、TCP、UDP、ICMP(我就囊括了这几个而已)有一定的了解。不知道的同学请看【网络编程】——IP、TCP、UDP、ARP、ICMP结构
那么我们接下来就开始,得贴一段头文件的代码……

Datagram.h

/*
*装着各种协议头的头文件
*/
#include "AdapterDlg.h"
#include "caputrerDlg.h"
#include <pcap.h>

#pragma	once

/* 以太网协议类型 */
#define ETHERTYPE_IP            0x0800          /* IP */
#define ETHERTYPE_ARP           0x0806          /* Address resolution */
#define ETHERTYPE_REVARP        0x8035          /* Reverse ARP */

/* IP协议类型 */
#define IPTYPE_UPD				17
#define IPTYPE_TCP				6
#define IPTYPE_ICMP				1
#define IPTYPE_IGMP				2

//自定义结构体,将数据包转换为需要的格式
struct ListData
{
	char ID[10];
	char Protocol[20];
	char sIP[16], sMac[19], sPort[10];
	char dIP[16], dMac[19], dPort[10];
	char Len[10];
	char Text[50];
};
//list control的自定义消息
#define WM_UPDATE_LIST (WM_USER+2)

//注意内存对齐的影响
#pragma	pack(push,1)
// little_endian.  
#ifndef LITTLE_ENDIAN  
#define LITTLE_ENDIAN   (1)   //BYTE ORDER  
#else  
#error Redefine LITTLE_ORDER  
#endif  

//Ethernet header
typedef	struct Ehr
{
	u_char	ehr_tha[6];		//以太网源MAC
	u_char	ehr_sha[6];		//以太网目的MAC
	u_short	ehr_ftp;		//以太网帧类型
}EHR;

//UDP header
typedef	struct ARP_hr
{
	u_short	arp_hrp;		//ARP硬件类型
	u_short	arp_ptp;		//ARP协议类型
	u_char	arp_hln;		//ARP硬件地址长度
	u_char	arp_pln;		//ARP协议地址长度
	u_short	arp_op;			//ARP操作码
}ARP_HR;

//ARP header
typedef	struct ARP_st
{
	EHR		ehr_hdr;		//以太网头部
	ARP_HR	arp_hdr;		//ARP头部
	u_char	arp_sha[6];		//ARP源mac
	u_char	arp_spa[4];		//ARP源IP
	u_char	arp_tha[6];		//ARP目的MAC
	u_char	arp_tpa[4];		//ARP目的IP
	u_char	padding[18];	//ARP填充
}ARP;

//IPv4 header
typedef struct ip_header{
	u_char  ver_ihl;        // 版本 (4 bits) + 首部长度 (4 bits)
	u_char  tos;            // 服务类型(Type of service) 
	u_short tlen;           // 总长(Total length) 
	u_short identification; // 标识(Identification)
	u_short flags_fo;       // 标志位(Flags) (3 bits) + 段偏移量(Fragment offset) (13 bits)
	u_char  ttl;            // 存活时间(Time to live)
	u_char  proto;          // 协议(Protocol)
	u_short crc;            // 首部校验和(Header checksum)
	u_char  saddr[4];		// 源地址(Source address)
	u_char  daddr[4];		// 目的地址(Destination address)
	u_int   op_pad;         // 选项与填充(Option + Padding)
}IP_HDR;

//TCP header
typedef struct _tcp_hdr
{
	unsigned short src_port;    //源端口号  
	unsigned short dst_port;    //目的端口号  
	unsigned int seq_no;        //序列号  
	unsigned int ack_no;        //确认号  
#if LITTLE_ENDIAN  
	unsigned char reserved_1 : 4; //保留6位中的4位首部长度  
	unsigned char thl : 4;        //tcp头部长度  
	unsigned char flag : 6;       //6位标志  
	unsigned char reseverd_2 : 2; //保留6位中的2位  
#else  
	unsigned char thl : 4;        //tcp头部长度  
	unsigned char reserved_1 : 4; //保留6位中的4位首部长度  
	unsigned char reseverd_2 : 2; //保留6位中的2位  
	unsigned char flag : 6;       //6位标志   
#endif  
	unsigned short wnd_size;    //16位窗口大小  
	unsigned short chk_sum;     //16位TCP检验和  
	unsigned short urgt_p;      //16为紧急指针  
} TCP_HDR;

/* UDP header*/
typedef struct udp_header{
	u_short sport;          // 源端口(Source port)
	u_short dport;          // 目的端口(Destination port)
	u_short len;            // UDP数据包长度(Datagram length)
	u_short crc;            // 校验和(Checksum)
}UDP_HDR;

//ICMP header
typedef struct _ICMPHeader
{
	u_char icmp_type; //消息类型
	u_char icmp_code; //代码
	u_short icmp_checksum; //校验和
	//下面是回显头
	u_short icmp_id; //用来惟一标识此请求的ID号,通常设置为进程ID
	u_short icmp_sequence; //序列号
	u_long icmp_timestamp; //时间戳
}ICMP_HDR;


#pragma	pack(pop)

//过滤条件
typedef struct _filter{
	bool	protocol_all:1;
	bool	ARP : 1;
	bool	ICMP : 1;
	bool	UDP : 1;
	bool	TCP : 1;
	bool	IP_all : 1;
	u_char	IP_src[16];
}FILTER;

//适配器信息类
class AdpInfo
{
public:
	AdpInfo();
	~AdpInfo();
	bool	getError();						//获取错误信息
	bool	showAllDevs(CAdapterDlg*);		//显示网卡
	bool	scanHostMAC_IP();				//扫描本网段的主机

	struct pcap_pkthdr *header;				//数据包信息
	const u_char *pkt_data;					//数据包数据

	pcap_if_t	*allDevs;					//所有设适配器述符
	pcap_if_t	*usedDevs;					//当前选中的适配器
	pcap_t		*ahandler;					//适配器描述符
	FILTER		filter;						//过滤选择
	char		errBuf[PCAP_BUF_SIZE];		//错误消息
	bool		isCapturing;				//决定是否捕捉数据包

private:
	bool		fatal;						//出现了无法挽回的错误
	u_int		devsNum;					//设备总数量

};


typedef	unsigned(WINAPI *THREAD_PROC)(LPVOID);

//数据包分析类
class CAnalyse{
public:
	CAnalyse();
	~CAnalyse();

	bool analyseData(CString &, const u_char*, pcap_pkthdr*);	//分析入口
	virtual void AnalyseARP(CString &, const u_char*);			//分析ARP包
	virtual void AnalyseIP(CString &, const u_char*);			//分析IP包
	virtual void AnalyseICMP(CString &, const u_char*);			//分析ICMP协议
	virtual void AnalyseTCP(CString &, const u_char*);			//分析TCP协议
	virtual void AnalyseUDP(CString &, const u_char*);			//分析UDP协议

private:
	EHR			*eth_hdr;
	IP_HDR		*ip_hdr;
	ARP			*arp;
	TCP_HDR		*tcp_hdr;
	UDP_HDR		*udp_hdr;
	CString		tmp;
};



其内容就是我接下来都要用到的,其中包括了几个协议的首部结构,几个宏来定义协议类型,几个自己实现的类分别完成各个网卡扫描、协议分析等。我觉得也没什么可以多说的。只得注意的是位域和内存对齐问题,在协议结构体前最好加上#pragma pack(1)来达到自己想要的对齐方式,防止协议在读取时出错。期间还要注意主机序和网络序,也就是常说的大端小端字节序。还有疑惑的同学请看【操作系统】大小端+位域+内存对齐
头文件只做了解,后面会慢慢用到的,我个人的读代码经验就是:先扫一眼头文件中的类和结构,立马看实现过程,等用到了再查找一下。如此反复也就明白一些变量的作用了。

【未完待续】(源码见最后篇)
阅读更多
版权声明:Pain is just in your mind. https://blog.csdn.net/yzt33/article/details/45169797
文章标签: winpcap 抓包 协议
个人分类: MFC WinPcap 网络协议
想对作者说点什么? 我来说一句
相关热词

没有更多推荐了,返回首页

关闭
关闭
关闭