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;
}