⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arp.h

📁 枚举主机网络设备
💻 H
字号:
/*
 *	Copyleft Abelworkshop.	
 *	文件名称:arp.h
 *	摘    要:抓包程序,通过向局域网上发送ARP请求来获得活动主机的IP地址与MAC对应关系
 *	单    位:信息学院
 *	作    者:罗涛,2120060434
 *	完成日期:2006年10月25日
 */

#include <stdlib.h>
#include <stdio.h>

//#include <pcap.h>
#include "pcap.h"

#include <fstream>

using namespace std;

#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "wpcap.lib")

#define BROADMAC		{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF} //广播MAC
#define EH_TYPE			0x0806							//ARP类型
#define ARP_HRD			0X0001							//硬件类型:以太网接口类型为1		
#define ARP_PRO			0x0800							//协议类型:IP协议类型为0X0800
#define ARP_HLN			0x06							//硬件地址长度:MAC地址长度为6B
#define ARP_PLN			0x04							//协议地址长度:IP地址长度为4B
#define ARP_REQUEST		0x0001							//操作:ARP请求为1
#define ARP_REPLY		0x0002							//操作:ARP应答为2
#define ARP_THA			{0,0,0,0,0,0}					//目的MAC地址:ARP请求中该字段没有意义,设为0;ARP响应中为接收方的MAC地址
#define ARP_PAD			{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
#define SPECIAL			0x70707070						//定义获得自己MAC地址的特殊源IP,112.112.112.112
#define BUFFERSIZE		24								//缓冲区足够大的话,守候线程可以更加从容干自己喜欢干的事儿!20061027

#define ETH_HRD_DEFAULT	{BROADMAC, {0,0,0,0,0,0}, htons(EH_TYPE)}
#define ARP_HRD_DEFAULT	{htons(ARP_HRD), htons(ARP_PRO), ARP_HLN, ARP_PLN, htons(ARP_REQUEST), {0,0,0,0,0,0}, 0, ARP_THA, 0, ARP_PAD}

typedef unsigned char uchar;
typedef unsigned short usint;
typedef unsigned long ulint;

//string seleDevName = "";
uchar* g_chLocalMac = (uchar *)malloc(sizeof(uchar) * 6);	//存放本地MAC地址
BOOL g_bThreadWaitingStop = 1;
int g_gotMac = 0;

struct ethernet_head
{
	uchar dest_mac[6];									//目标主机MAC地址
	uchar source_mac[6];								//源端MAC地址
	usint eh_type;										//以太网类型
};

struct arp_head
{
	usint hardware_type;								//硬件类型:以太网接口类型为1
	usint protocol_type;								//协议类型:IP协议类型为0X0800
	uchar add_len;										//硬件地址长度:MAC地址长度为6B
	uchar pro_len;										//协议地址长度:IP地址长度为4B
	usint option;										//操作:ARP请求为1,ARP应答为2

	uchar sour_addr[6];									//源MAC地址:发送方的MAC地址
	ulint sour_ip;										//源IP地址:发送方的IP地址
	uchar dest_addr[6];									//目的MAC地址:ARP请求中该字段没有意义;ARP响应中为接收方的MAC地址
	ulint dest_ip;										//目的IP地址:ARP请求中为请求解析的IP地址;ARP响应中为接收方的IP地址
	uchar padding[18];
};

struct arp_packet										//最终arp包结构
{
	ethernet_head eth;									//以太网头部
	arp_head arp;										//arp数据包头部
};

struct SQueryParam
{
	CWnd *pWnd;
	HTREEITEM hItem;
	pcap_if_t* pDvc;
};

int countCh(char* chIn){								//计算字符数组长度
	int i = 0;
	while (chIn[i++] != 0);
	return i;
}

#define IPTOSBUFFERS 12
char* ipTostr(ulint ulIP)
{								// 将一个无符号长整型的机器IP地址转换为字符串类型的用户友好IP格式
	static char output[IPTOSBUFFERS][3 * 4 + 3 + 1];
	static short which;									//定义两个静态数组,可容纳最多12组IP类地址,最大程度防止指针越界!
	uchar* chIP;
	chIP = (uchar*)&ulIP;								//取ulIP的地址,并强制转化为无符号字符型指针
	which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1); 
	sprintf(output[which], "%d.%d.%d.%d", chIP[0], chIP[1], chIP[2], chIP[3]); 
	return output[which];
}

char* macTostr(uchar* chMAC)
{							//将MAC地址的数组变为带“-”的大写的字符可读形式
	uchar* uMac = new uchar[18];
	for(int i=0; i < 17; i++){
		if ((i+1) % 3){
			if (!(i % 3)){
				if ((chMAC[i/3] >> 4) < 0x0A){
					uMac[i] = (chMAC[i/3] >> 4) + 48;
				}
				else{
					uMac[i] = (chMAC[i/3] >> 4) + 55;
				}
				if ((chMAC[i/3] & 0x0F) < 0x0A){
					uMac[i+1] = (chMAC[i/3] & 0x0F) + 48;
				}
				else{
					uMac[i+1] = (chMAC[i/3] & 0x0F) + 55;
				}
			}
		}
		else{
			uMac[i] = '-';
		}
	}
	uMac[17] = '\0';
	return (char*)uMac;
}

char* trimSpace(char* in){								//去掉字符串中多余的空格,对长串连续出现的空格只保留一个空格,以使显示美观
	int strLen = 0;
	while(in[strLen++] != '\0');
	char* chTemp = new char[strLen + 1];
	int i = 0;
	int j = 0;
	while(in[i] != '\0'){
		if(in[i] != ' '){
			chTemp[j++] = in[i++];
		}
		else{
			chTemp[j++] = in[i++];
			while(in[i] == ' ')i++;						//下一个是空格就一直朝前找下一个
		}
		/*chTemp[j++] = in[i++];						//简化不成功!!20061022
		if(in[i] == ' ' ){
			while(in[i] == ' ')i++;
		}*/
	}
	chTemp[j] = '\0';
	return chTemp;
}

/*处理数据包的回调函数示例								//太死板,不灵活,不利于多线程工作,不用!20061023
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data){
	struct tm *ltime; 
	char timestr[16]; 
	ltime = localtime(&header->ts.tv_sec);				// 转换时间戳为可以阅读的格式 
	strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); 
	printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len); 
}*/

//封装ARP请求包
uchar* enArpReqPack(uchar* source_mac, uchar* arp_sha, ulint chLocalIP, ulint arp_tpa, int PackSize)
{
	arp_packet arpPackStru = {ETH_HRD_DEFAULT,ARP_HRD_DEFAULT};
	//memset(eth_pa.dest_mac,'F',6);
	// = {'F','F','F','F','F','F'};
	uchar* arpStruToStr = (uchar *)malloc(sizeof(uchar) * PackSize);
	memset(arpStruToStr, 0, sizeof(arpStruToStr));
	memcpy(arpStruToStr,		&arpPackStru.eth.dest_mac,		6);
	memcpy(arpStruToStr + 6,	source_mac,						6);//new
	memcpy(arpStruToStr + 12,	&arpPackStru.eth.eh_type,		2);
	memcpy(arpStruToStr + 14,	&arpPackStru.arp.hardware_type,	2);
	memcpy(arpStruToStr + 16,	&arpPackStru.arp.protocol_type,	2);
	memcpy(arpStruToStr + 18,	&arpPackStru.arp.add_len,		1);
	memcpy(arpStruToStr + 19,	&arpPackStru.arp.pro_len,		1);
	memcpy(arpStruToStr + 20,	&arpPackStru.arp.option,		2);
	memcpy(arpStruToStr + 22,	arp_sha,						6);//new
	memcpy(arpStruToStr + 28,	&chLocalIP,						4);//new
	memcpy(arpStruToStr + 32,	&arpPackStru.arp.dest_addr,		6);
	memcpy(arpStruToStr + 38,	&arp_tpa,						4);//new
	return arpStruToStr;
}

//获得自己的MAC
uchar* getSelfMac(char* pDvcName, ulint chLocalIP)
{
	//int i = 0;//调试时统计需要经过多少次才能获得回包,以设置合理的sleep值
	//string j = "";
	pcap_t* pAdaptHandle;//打开网卡适配器时用
	char errbuf[PCAP_ERRBUF_SIZE + 1]; 
	if((pAdaptHandle = pcap_open_live(pDvcName, 60, 1, 100, errbuf)) == NULL){
		//arp包最大长度是60,节省内存资源,不设为65536!并且设为混杂模式以检查发往往000000的包20061012
		MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "Note", MB_OK);
		return NULL;
	}
	struct pcap_pkthdr *header;
	const u_char *pkt_data;
	int res;
	usint arp_op;
	uchar* arp_sha = (uchar *)malloc(sizeof(uchar) * 6);
	ulint arp_spa = 0;
	ulint arp_tpa = 0;
	uchar source_mac[6] = {0,0,0,0,0,0};
	uchar* arp_packet_for_self;
	arp_packet_for_self = enArpReqPack(source_mac, source_mac, SPECIAL, chLocalIP, 60);
	while(!g_gotMac){
		//i++;
		pcap_sendpacket(pAdaptHandle, arp_packet_for_self, 60);
		Sleep(10);//睡一会,给系统喘息的机会:)
		res = pcap_next_ex(pAdaptHandle, &header, &pkt_data);
		if(res == 0)continue;
		memcpy(&arp_op, pkt_data + 20, 2);
		memcpy(arp_sha, pkt_data + 22, 6);
		memcpy(&arp_spa, pkt_data + 28, 4);	
		memcpy(&arp_tpa, pkt_data + 38, 4);	
		if(arp_op == htons(ARP_REPLY) && arp_spa == chLocalIP && arp_tpa == SPECIAL){
			//发现当IP地址冲突时会有意想不到的问题,特在此加强限制条件20061024
			//j = char(i+48);
			//MessageBox(NULL, j.c_str(), "Note", MB_OK);
			g_gotMac = 1;
			free(arp_packet_for_self);
			pcap_close(pAdaptHandle);
			return arp_sha;
		}
		Sleep(100);//若不成功再等100ms再发,让网卡歇歇:) 20061025
	}
	free(arp_packet_for_self);
	pcap_close(pAdaptHandle);
	return arp_sha;
}

//发送ARP请求
#define ID_INDICATOR_INFO               59143
void sendArpReq(pcap_if_t* pDvc,uchar* g_chLocalMac)
{
	pcap_addr_t* pAdr = 0;
	DWORD dwLocalIP = 0;//存放本地ip地址
	ulint arp_tpa = 0;
	ulint snd_tpa = 0;
	ulint nlNetMask = 0;
	int netsize = 0;
	const char* pDvcName = pDvc->name;
	pcap_t* pAdaptHandle;//打开网卡适配器时用
	char errbuf[PCAP_ERRBUF_SIZE + 1];
	pAdaptHandle = pcap_open_live(pDvc->name, 60, 0, 100, errbuf);
	if(NULL==pAdaptHandle){
		//arp包最大长度是60,节省内存资源,不设为65536!并且设为混杂模式以检查发往往000000的包20061021
		MessageBox(NULL, "无法打开适配器,可能与之不兼容!", "Send", MB_OK);
		return;
	}
	uchar* arp_packet_for_req;
	arp_packet_for_req = enArpReqPack(g_chLocalMac, g_chLocalMac, dwLocalIP, dwLocalIP, 60);	//构造包,并将只更改倒数第二个形参,在字符串里对之进行局部更改!效率高得多,不要重复申请STRUCT,会浪费大量内存空间20061024
	for (pAdr = pDvc->addresses; pAdr; pAdr = pAdr->next){
		if (g_bThreadWaitingStop) break;
		dwLocalIP = ((struct sockaddr_in *)pAdr->addr)->sin_addr.s_addr;
		if (0==dwLocalIP) continue;//可能网卡没有接网线
		nlNetMask = ((struct sockaddr_in *)(pAdr->netmask))->sin_addr.S_un.S_addr;	//得到子网掩码
		netsize = ~ntohl(nlNetMask);
		arp_tpa = ntohl(dwLocalIP & nlNetMask);										//获得的IP地址是网络序的,必须转为主机序

		memcpy(arp_packet_for_req + 28, &dwLocalIP, 4);								//将字串中源IP设为本次得到的本地IP
		for (int i=0; i < netsize; i++){
			if (g_bThreadWaitingStop) break;
			arp_tpa++;																//第一个循环对于初始化的x.x.x.0的地址不用发,是子网号20061027
			snd_tpa=htonl(arp_tpa);
			if (snd_tpa==dwLocalIP)continue;//不对自己发ARP请求包,也会产生地址冲突?原因何在?
			
			CString strInfo;
			strInfo.Format("查找%s",ipTostr(snd_tpa));
			AfxGetApp()->m_pMainWnd->PostMessage(UM_SET_STATUSBAR_TEXT,ID_INDICATOR_INFO,LONG(new CString(strInfo)));
			
			memcpy(arp_packet_for_req + 38, &snd_tpa, 4);//目的IP在子网范围内按序增长	
			pcap_sendpacket(pAdaptHandle, arp_packet_for_req, 60);
			Sleep(15);
		}
	}
	free(arp_packet_for_req);

	AfxGetApp()->m_pMainWnd->PostMessage(UM_SET_STATUSBAR_TEXT,ID_INDICATOR_INFO,LONG(new CString("查找完毕")));
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -