欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

npcap收数据包,libnet发数据包

程序员文章站 2022-07-10 14:34:51
...

 

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

#ifdef _MSC_VER
/*
 * we do not want the warnings about the old deprecated and unsecure CRT functions
 * since these examples can be compiled under *nix as well
 */
#define _CRT_SECURE_NO_WARNINGS
#endif

//#include <stdio.h>
//#include <stdlib.h>
#include <string>
#include <pcap.h>
#include <libnet.h>
#include <QDebug>
#include "protocal/EAPMD5/EAPMD5.h"
#include "protocal/EAPTLS/EAPTLS.h"
#include "common/utils.h"
using namespace std;

#define AUTHWAY_EAPMD5 0
#define AUTHWAY_EAPTLS 1

#define STATUS_DISCONNECTION 0
#define STATUS_CONNECTION    1

#define MAC_ADDRESS_LEN 6


class SendAndRecv
{
public:
	SendAndRecv(string nic);
	~SendAndRecv();
	int proccess();
	int connect(string nic, uint8_t authWay, string username, string passward);
	int disconnect();

private:
	int init();
	int destroy();
	int initNpcap();
	int initLibnet();
	int destroyNpcap();
	int destroyLibnet();
	bool LoadNpcapDlls();
	int setFilter(char* str);
	//int sendData(char* data, int dataLen);
	//char* recvData();


	int getMAC();
	int analysisPackage(const u_char* pkt_data);
	int analysisMD5(const u_char* pkt_data);
	int analysisTLS(const u_char* pkt_data);
	int sendStart();
	int sendResIdentity(const u_char* pkt_data);
	int sendResMD5(const u_char* pkt_data);
	int sendResNAK(const u_char* pkt_data);
	int sendLogoff();
	int EAPstructToPtr(EAP* eap, uint8_t* payload);

	int analysisTLSResquest(const u_char* pkt_data);
	int processEAPTLS(const u_char* pkt_data);

	pcap_if_t* alldevs;
	pcap_if_t* d;
	pcap_if_t * m_d;
	pcap_t * m_adhandle;
	string m_strNic;
	string m_strMAC;
	uint8_t* m_mac;
	string m_nicName;
	u_int m_netmask;

	libnet_t* l;
	string m_username;
	string m_passward;
	UINT8 m_iAuthWay;
	UINT8 m_iConnectionStatus;
	EAPTLS* eaptls;

};






#include "SendAndRecv.h"
#include <tchar.h>

SendAndRecv::SendAndRecv(string nic)
{
	qDebug("init SendAndRecv");
	m_strNic = nic;	
	m_iAuthWay = AUTHWAY_EAPMD5;//md5
	m_iConnectionStatus = STATUS_DISCONNECTION;

	qDebug("m_strNic:");
	qDebug((char*)m_strNic.c_str());
	m_mac = NULL;
	m_mac = Utils::getMAC((char*)m_strNic.c_str(), m_nicName, m_netmask);
	qDebug("m_mac:");
	char buf[50] = { 0 };
	sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n", m_mac[0], m_mac[1], m_mac[2], m_mac[3], m_mac[4], m_mac[5]);
	qDebug(buf);

	init();
	eaptls = new EAPTLS();
	if (NULL == eaptls)
	{
		return;
	}

	qDebug("init SendAndRecv over");
}
SendAndRecv::~SendAndRecv()
{
	destroy();

	if (NULL != m_mac)
	{
		delete[]m_mac;
		m_mac = NULL;
	}
}

int SendAndRecv::init()
{
	initNpcap();
	initLibnet();
	
	return 0;
}

int SendAndRecv::destroy()
{
	destroyNpcap();
	destroyLibnet();

	return 0;
}

int SendAndRecv::initNpcap()
{
	qDebug("init Npcap\n");
	int inum;
	int i = 0;
	//pcap_t* adhandle;
	char errbuf[PCAP_ERRBUF_SIZE];

	/* Load Npcap and its functions. */
	qDebug("1");
	if (!LoadNpcapDlls())
	{
		fprintf(stderr, "Couldn't load Npcap\n");
		qDebug("Couldn't load Npcap\n");
		exit(1);
	}

	/* Retrieve the device list on the local machine */
	qDebug("2");
	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
	{
		fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
		qDebug("Error in pcap_findalldevs: %s\n");
		exit(1);
	}

	qDebug("3");
	string nic = "Network adapter '" + m_strNic + "' on local host";
	for (d = alldevs; d; d = d->next)
	{
		qDebug(d->description);
		if (0 == strcmp(d->description, nic.c_str()))
		{
			qDebug("find");
			break;
		}		
	}
	char* name = d->name + 8;
	/* Open the device */
	qDebug("4");
	if (d == NULL)
	{
		qDebug("d is null");
		exit(1);
	}
	
	qDebug("begin to pcap_open\n");
	if (m_nicName.size() == 0)
	{
		qDebug("m_nicName is null\n");
		exit(1);
	}
	qDebug("m_nicName:");
	qDebug(m_nicName.c_str());
	qDebug("2");
	if ((m_adhandle = pcap_open(m_nicName.c_str(),			// name of the device
		65536,			// portion of the packet to capture
					  // 65536 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)
	{
		fprintf(stderr, "\nUnable to open the adapter. %s is not supported by Npcap\n", d->name);
		qDebug("Unable to open the adapter.\n");

		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}

	//printf("\nlistening on %s...\n", d->description);

	/* At this point, we don't need any more the device list. Free it */
	//pcap_freealldevs(alldevs);

	qDebug("3");
	setFilter("ether proto 0x888e");

	return 0;
}
int SendAndRecv::setFilter(char* str)
{
	qDebug("setFilter");
	if (NULL == str)
	{
		return -1;
	}

	u_int netmask;
	qDebug("1");
	netmask = m_netmask;
	//if (d->addresses != NULL)
	//{
	//	/* Retrieve the mask of the first address of the interface */
	//	//netmask = ((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
	//	netmask = m_netmask;
	//}
	//else
	//{
	//	/* If the interface is without an address we suppose to be in a C class network */
	//	netmask = 0xffffff;
	//}

	//compile the filter
	struct bpf_program fcode;
	qDebug("2");
	if (pcap_compile(m_adhandle, &fcode, str, 1, netmask) < 0)
	{
		fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
		qDebug("Unable to compile the packet filter.\n");
		/* Free the device list */
		return -1;
	}

	//set the filter
	qDebug("3");
	if (pcap_setfilter(m_adhandle, &fcode) < 0)
	{
		fprintf(stderr, "\nError setting the filter.\n");
		qDebug("Error setting the filter.\n");
		/* Free the device list */
		return -1;
	}

	return 0;
}

int SendAndRecv::disconnect()
{
	/* Retrieve the packets */
	struct pcap_pkthdr* header;
	const u_char* pkt_data;
	int res = 0;
	bool bLogoff = false;
	while ((res = pcap_next_ex(m_adhandle, &header, &pkt_data)) >= 0)
	{
		if (!bLogoff)
		{
			int ret = sendLogoff();
			bLogoff = true;
			if (-1 == ret)
			{
				return -1;
			}
		}

		if (res == 0)			
			continue;/* Timeout elapsed */

		res = analysisPackage(pkt_data);
		if (res != 0)
		{
			break;
		}
	}

	if (STATUS_DISCONNECTION == m_iConnectionStatus)
	{
		return 0;
	}
	else
	{
		return -1;
	}
}

int SendAndRecv::connect(string nic, uint8_t authWay, string username, string passward)
{
	qDebug("SendAndRecv::connect()");
	m_strNic = nic;
	m_username = username;
	m_passward = passward;
	m_iAuthWay = authWay;

	if (authWay == AUTHWAY_EAPTLS)
	{
		m_username = "TestClient";
	}

	qDebug("m_username:");
	qDebug(m_username.c_str());
	qDebug("m_passward:");
	qDebug(m_passward.c_str());

	/* Retrieve the packets */
	struct pcap_pkthdr* header;
	const u_char* pkt_data;
	int res = 0;
	bool bStart = false;
	while ((res = pcap_next_ex(m_adhandle, &header, &pkt_data)) >= 0)
	{
		if (!bStart)
		{
			int ret = sendStart();
			bStart = true;
			if (-1 == ret)
			{
				return -1;
			}
			qDebug("send start success");
		}

		if (res == 0)			
			continue;/* Timeout elapsed */

		res = analysisPackage(pkt_data);
		if (1 == res)
		{
			break;
		}
		else if(-1 == res)
		{
			//sendLogoff();
			continue;
		}
		else
		{
			continue;
		}
	}

	if (STATUS_CONNECTION == m_iConnectionStatus)
	{
		return 0;
	}
	else
	{
		return -1;
	}
}

bool SendAndRecv::LoadNpcapDlls()
{
	_TCHAR npcap_dir[512];
	UINT len;
	len = GetSystemDirectory((LPWSTR)npcap_dir, 480);
	if (!len) {
		fprintf(stderr, "Error in GetSystemDirectory: %x", GetLastError());
		return FALSE;
	}
	_tcscat_s(npcap_dir, 512, _T("\\Npcap"));
	if (SetDllDirectory((LPWSTR)npcap_dir) == 0) {
		fprintf(stderr, "Error in SetDllDirectory: %x", GetLastError());
		return FALSE;
	}
	return TRUE;
}

int SendAndRecv::initLibnet()
{
	qDebug("init libnet\n");
	char errbuf[LIBNET_ERRBUF_SIZE];
	l = libnet_init(
		LIBNET_LINK,                            /* injection type */
		/*(d->name + 8)*/(m_nicName.c_str() + 8),                                   /* network interface */
		errbuf);                                /* errbuf */

	if (l == NULL)
	{
		qDebug("init libnet failed");
		return -1;
	}
	
	return 0;
}
int SendAndRecv::destroyNpcap()
{
	pcap_freealldevs(alldevs);
	return 0;
}

int SendAndRecv::destroyLibnet()
{
	if (l != NULL)
	{
		libnet_destroy(l);
		l = NULL;
	}
	
	return 0;
}

int SendAndRecv::proccess()
{
	//if (STATUS_DISCONNECTION == m_iConnectionStatus)
	//{
	//	connect();
	//}
	//else
	//{
	//	disconnect();
	//}

	return 0;
}

int SendAndRecv::sendStart()
{
	libnet_ptag_t t;
	uint8_t payload[2] = { 0x00 };
	t = libnet_build_802_1x(1, EAPOL_START, 0, payload, 1, l, 0);
	if (t == -1)
	{
		return -1;
	}

	uint8_t src_mac[7] = { 0x88, 0x51, 0xfb, 0x5b, 0x4a, 0x8f };
	uint8_t dst_mac[7] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
	t = libnet_build_ethernet(dst_mac, m_mac, 0x888e, NULL, 0, l, 0);
	if (t == -1)
	{
		return -1;
	}
	int packet_size = libnet_write(l);
	libnet_clear_packet(l);
	if (packet_size <= 0)
	{
		return -1;
	}

	return 0;
}

int SendAndRecv::analysisPackage(const u_char* pkt_data)
{
	if (NULL == pkt_data)
	{
		return -1;
	}

	uint8_t local_mac[7] = { 0x88, 0x51, 0xfb, 0x5b, 0x4a, 0x8f };
	uint8_t dst_mac[7] = { 0 };
	memcpy(dst_mac, pkt_data, 6);
	if(0 != strcmp((const char*)dst_mac, (const char*)m_mac))
	{
		return 0;
	}
	
	AUTH8021X* auth = (AUTH8021X*)(pkt_data + ETHERNET_HEADER_LEN);
	if (EAP_PACKET != auth->type)
	{
		return -1;
	}

	int ret = 0;
	if (AUTHWAY_EAPMD5 == m_iAuthWay)
	{
		ret = analysisMD5(pkt_data);
	}
	else
	{
		ret = analysisTLS(pkt_data);
	}

	return ret;
}

int SendAndRecv::analysisMD5(const u_char* pkt_data)
{
	if (NULL == pkt_data)
	{
		return -1;
	}

	EAP* eap = (EAP*)(pkt_data + ETHERNET_HEADER_LEN + sizeof(AUTH8021X));
	int ret = 0;
	if ((EAP_CODE_REQUEST == eap->code) && (EAP_TYPE_IDETITY == eap->type))
	{
		ret = sendResIdentity(pkt_data);
	}
	else if ((EAP_CODE_REQUEST == eap->code) && (EAP_TYPE_MD5_CHALLENGE == eap->type))
	{
		ret = sendResMD5(pkt_data);
	}
	else if (EAP_CODE_REQUEST == eap->code)
	{
		if ((EAP_TYPE_TLS == eap->type) || (EAP_TYPE_TTLS == eap->type) || (EAP_TYPE_PEAP == eap->type))
		{
			ret = sendResNAK(pkt_data);
		}
		else
		{
		}
	}
	else if (EAP_CODE_SUCCESS == eap->code)
	{
		if (STATUS_DISCONNECTION == m_iConnectionStatus)
		{
			m_iConnectionStatus = STATUS_CONNECTION;
		}
		return 1;
	}
	else if (EAP_CODE_FAILURE == eap->code)
	{
		if (STATUS_CONNECTION == m_iConnectionStatus)
		{
			m_iConnectionStatus = STATUS_DISCONNECTION;
		}
		return 1;
	}
	else
	{
		;
	}

	if (-1 == ret)
	{
		return -1;
	}

	return 0;
}

int SendAndRecv::EAPstructToPtr(EAP* eap, uint8_t* payload)
{
	if ((NULL == eap) || (NULL == payload))
	{
		return -1;
	}

	*payload = eap->code;
	payload++;

	*payload = eap->id;
	payload++;

	*(uint16_t*)payload = eap->len;
	payload += 2;

	*payload = eap->type;
	payload++;

	return 0;
}

int SendAndRecv::sendResIdentity(const u_char* pkt_data)
{
	qDebug("sendResIdentity begin");
	if (NULL == pkt_data)
	{
		return -1;
	}

	EAP* eap = (EAP*)(pkt_data + ETHERNET_HEADER_LEN + sizeof(AUTH8021X));

	uint16_t len = ntohs(eap->len);
	uint16_t eaplen = len;
	len += m_username.size();
	uint8_t* payload = new uint8_t[len+1];
	if (NULL == payload)
	{
		return -1;
	}
	memset(payload, '\0', len + 1);
	eap->code = EAP_CODE_RESPONSE;
	eap->len = htons(len);
	if (0 != EAPstructToPtr(eap, payload))
	{
		return -1;
	}
	memcpy(payload + eaplen, m_username.c_str(), m_username.size());

	libnet_ptag_t t;
	t = libnet_build_802_1x(1, EAP_PACKET, len, payload, len, l, 0);
	if (t == -1)
	{
		return -1;
	}

	uint8_t src_mac[7] = { 0x88, 0x51, 0xfb, 0x5b, 0x4a, 0x8f };
	uint8_t dst_mac[7] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
	t = libnet_build_ethernet(dst_mac, m_mac, 0x888e, NULL, 0, l, 0);
	if (t == -1)
	{
		return -1;
	}
	int packet_size = libnet_write(l);
	libnet_clear_packet(l);
	if (packet_size <= 0)
	{
		return -1;
	}

	delete []payload;
	payload = NULL;

	qDebug("sendResIdentity end");
	return 0;
}

int SendAndRecv::sendResMD5(const u_char* pkt_data)
{
	qDebug("sendResMD5 begin");
	if (NULL == pkt_data)
	{
		return -1;
	}

	EAP* eap = (EAP*)(pkt_data + ETHERNET_HEADER_LEN + sizeof(AUTH8021X));

	uint16_t len = ntohs(eap->len);
	uint16_t eaplen = len;
	len += m_username.size();
	uint8_t* payload = new uint8_t[len + 1];
	if (NULL == payload)
	{
		return -1;
	}
	memset(payload, 0, len + 1);
	eap->code = EAP_CODE_RESPONSE;
	eap->len = htons(len);
	if (0 != EAPstructToPtr(eap, payload))
	{
		return -1;
	}
	u_char* data = (u_char*)(pkt_data + ETHERNET_HEADER_LEN + AUTH8021X_HEADER_LEN + EAP_HEADER_LEN);
	uint8_t md5ValSize = *data;
	 
	memcpy(payload + EAP_HEADER_LEN, &md5ValSize, 1);

	u_char challenge[CHALLENGE_LEN + 1] = { 0 };
	memcpy(challenge, data + 1, CHALLENGE_LEN);
	MD5Encrypt(eap->id, m_passward, challenge, md5ValSize);
	memcpy(payload + EAP_HEADER_LEN + 1, challenge, md5ValSize);
	memcpy(payload + EAP_HEADER_LEN + 1 + md5ValSize, m_username.c_str(), m_username.size());
	
	
	libnet_ptag_t t;
	t = libnet_build_802_1x(1, EAP_PACKET, len, payload, len, l, 0);
	if (t == -1)
	{
		return -1;
	}

	uint8_t src_mac[7] = { 0x88, 0x51, 0xfb, 0x5b, 0x4a, 0x8f };
	uint8_t dst_mac[7] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
	t = libnet_build_ethernet(dst_mac, m_mac, 0x888e, NULL, 0, l, 0);
	if (t == -1)
	{
		return -1;
	}
	int packet_size = libnet_write(l);
	libnet_clear_packet(l);
	if (packet_size <= 0)
	{
		return -1;
	}

	delete[]payload;
	payload = NULL;

	qDebug("sendResMD5 end");
	return 0;
}

int SendAndRecv::sendResNAK(const u_char* pkt_data)
{
	qDebug("sendResNAK begin");
	if (NULL == pkt_data)
	{
		return -1;
	}

	EAP* eap = (EAP*)(pkt_data + ETHERNET_HEADER_LEN + sizeof(AUTH8021X));

	//uint16_t len = ntohs(eap->len);
	//uint16_t eaplen = len;
	uint8_t* payload = new uint8_t[EAP_HEADER_LEN + 1];
	if (NULL == payload)
	{
		return -1;
	}
	memset(payload, 0, EAP_HEADER_LEN + 1);
	eap->code = EAP_CODE_RESPONSE;
	eap->type = EAP_TYPE_NAK;
	eap->len = htons(EAP_HEADER_LEN + 1);
	if (0 != EAPstructToPtr(eap, payload))
	{
		return -1;
	}

	if (AUTHWAY_EAPMD5 == m_iAuthWay)
	{
		uint8_t data = EAP_TYPE_MD5_CHALLENGE;
		memcpy(payload + EAP_HEADER_LEN, &data, 1);
	}
	else
	{
		uint8_t data = EAP_TYPE_TLS;
		memcpy(payload + EAP_HEADER_LEN, &data, 1);
	}

	libnet_ptag_t t;
	t = libnet_build_802_1x(1, EAP_PACKET, EAP_HEADER_LEN + 1, payload, EAP_HEADER_LEN + 1, l, 0);
	if (t == -1)
	{
		return -1;
	}

	uint8_t src_mac[7] = { 0x88, 0x51, 0xfb, 0x5b, 0x4a, 0x8f };
	uint8_t dst_mac[7] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
	t = libnet_build_ethernet(dst_mac, m_mac, 0x888e, NULL, 0, l, 0);
	if (t == -1)
	{
		return -1;
	}
	int packet_size = libnet_write(l);
	libnet_clear_packet(l);
	if (packet_size <= 0)
	{
		return -1;
	}


	delete[]payload;
	payload = NULL;

	qDebug("sendResNAK end");
	return 0;
}

int SendAndRecv::sendLogoff()
{
	qDebug("sendLogoff begin");

	libnet_ptag_t t;
	uint8_t payload[2] = { 0x00 };
	t = libnet_build_802_1x(1, EAPOL_LOGOFF, 0, NULL, 0, l, 0);
	if (t == -1)
	{
		return -1;
	}

	uint8_t src_mac[7] = { 0x88, 0x51, 0xfb, 0x5b, 0x4a, 0x8f };
	uint8_t dst_mac[7] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
	t = libnet_build_ethernet(dst_mac, m_mac, 0x888e, NULL, 0, l, 0);
	if (t == -1)
	{
		return -1;
	}
	int packet_size = libnet_write(l);
	libnet_clear_packet(l);
	if (packet_size <= 0)
	{
		return -1;
	}
	qDebug("sendLogoff end");

	return 0;
}

int SendAndRecv::analysisTLS(const u_char* pkt_data)
{
	if (NULL == pkt_data)
	{
		return -1;
	}

	EAP* eap = (EAP*)(pkt_data + ETHERNET_HEADER_LEN + sizeof(AUTH8021X));
	int ret = 0;
	switch (eap->code)
	{
	case EAP_CODE_REQUEST:
		ret = analysisTLSResquest(pkt_data);
		break;
	case EAP_CODE_SUCCESS:
		if (STATUS_DISCONNECTION == m_iConnectionStatus)
		{
			m_iConnectionStatus = STATUS_CONNECTION;
		}
		ret = 1;
		break;
	case EAP_CODE_FAILURE:
		if (STATUS_CONNECTION == m_iConnectionStatus)
		{
			m_iConnectionStatus = STATUS_DISCONNECTION;
		}
		ret = 1;
		break;
	default:
		break;
	}

	return ret;
}

int SendAndRecv::analysisTLSResquest(const u_char* pkt_data)
{
	if (NULL == pkt_data)
	{
		return -1;
	}

	EAP* eap = (EAP*)(pkt_data + ETHERNET_HEADER_LEN + sizeof(AUTH8021X));
	int ret = 0;

	switch (eap->type)
	{
	case EAP_TYPE_IDETITY:
		ret = sendResIdentity(pkt_data);
		break;
	case EAP_TYPE_TLS:
		ret = processEAPTLS(pkt_data);
		break;
	default:
		if ((EAP_TYPE_MD5_CHALLENGE == eap->type) || (EAP_TYPE_TTLS == eap->type) || (EAP_TYPE_PEAP == eap->type))
		{
			ret = sendResNAK(pkt_data);
		}
		break;
	}
	return ret;
}

int SendAndRecv::processEAPTLS(const u_char* pkt_data)
{
	if (NULL == pkt_data)
	{
		return -1;
	}

	int len = 0;
	unsigned char* DataBuff = eaptls->process(pkt_data, len);
	if (NULL == DataBuff)
	{
		return 1;
	}

	qDebug("sendTLS begin");

	libnet_ptag_t t;
	uint8_t payload[2] = { 0x00 };
	t = libnet_build_802_1x(1, EAP_PACKET, len, DataBuff, len, l, 0);
	if (t == -1)
	{
		return -1;
	}

	uint8_t dst_mac[7] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
	t = libnet_build_ethernet(dst_mac, m_mac, 0x888e, NULL, 0, l, 0);
	if (t == -1)
	{
		return -1;
	}
	int packet_size = libnet_write(l);
	libnet_clear_packet(l);
	if (packet_size <= 0)
	{
		return -1;
	}
	qDebug("sendTLS end");
	return 0;
}

 

相关标签: 协议