arp欺骗的简介我就不复述了,网上挺多解释的,其产生的主要原因就是never check.在这种情况下,什么乱七八糟够早的包都能发了。
其实有很多工具可以利用,比如,WinArpAttacker(可能会缺少一些dll文件,自己下载加进去,网上资源挺多的,我就不放链接了),不过,本机测验,WinArpAttacker断网效果不咋地啊,不过IP冲突还是不错。估计使用方式不正确(一定要在配置中选择你需要的网卡)。它的断网原理是同时欺骗网关和你攻击的主机。当然还有一种,比较简单但是效果也比较好的:ArpSpoof(额,资源自寻吧,不难),它就是伪造攻击IP持续给网关发包,然后,被攻击的IP就瞬断网了。。。(ps:同一网段)
IP中间人攻击,做得比较好的是EtterCap,不过,EtterCap在Linux下会比较好。Windows我用了Cain&Abel (更新的version,虽然我不会用,解压之后找不到)当然,如果想看原理,可以用WireShark抓包观察(注意设置过滤条件,不然,包太多了)
另外,工具能用,不过不要乱用,拿来学习学习是不错,比如开个虚拟机玩就好。
————————————————————————————————————————————————————————
工具介绍完了,如果,要自己编写,可以利用Winpcap编程(资源下载页面——Developer's Pack)实现,Winpcap是运行上面众多软件所需的算一个插件吧,它的exe资源页面——Installer for Windows。
下载之后,如何配置呢:
http://blog.sina.com.cn/s/blog_57432f380101qh3n.html
VS2013使用winpcap开发网络应用程序:
1.首先,从http://www.winpcap.org/下载winpcap.exe和Developer's Pack(资源在上面)。安装winpcap.exe,并将Developer's Pack进行解压。
2.配置VS2013。在VS2013中新建一个空工程(可以考虑win32空应用程序)。具体设置如下:
(1)项目 →属性→配置属性→点击C/C++目录,点击展开的目录General,在右侧的Additional Include Directories中添加Include目录(Include目录在WpdPack中)
(2)项目 →属性→配置属性→点击C/C++目录,在右边的Preprocessor Definition加上WPCAP,HAVE_REMOTE,WIN32;
(3)项目 →属性→配置属性→点击Linker目录,点击展开的目录General,在右边的Additional Library Directories中添加lib目录(Lib目录在WpdPack中)
(4)项目 →属性→配置属性→点击Linker目录下的Input,在右侧的Additional Dependencies中添加wpcap.lib和Packet.lib,ws2_32.lib。
如果你用的 inet_addr 函数,那么可能会碰到下面的问题:
http://jingyan.baidu.com/article/1709ad8097e5904634c4f03e.html?st=2&os=0&bd_page_type=1&net_type=1
还有问题可以看下这篇博文:
winpcap开发包使用中的问题总结
————————————————————————————————————————————————————————
最后就是编程问题,要进行arp欺骗编程,
First Step:得先得到网卡信息吧。。。
用winpcap所带的 pcap_findalldevs_ex 得到网卡列表。说实话,不好用啊,因为它的description属性太多简单,我电脑上出现了四五个Microsoft的描述,除此再无其他,这要我怎么选。。。虽然name属性可以区分它们,但是不够直观。
用GetAdaptersAddresses获取网卡信息,GetAdapterAddresses的介绍可以参看:http://blog.csdn.net/linuxtiger/article/details/7002896
这个函数的接口声明是这样的:
ULONG WINAPI GetAdaptersAddresses(
__in ULONGFamily,
__in ULONGFlags,
__in PVOIDReserved,
__inout PIP_ADAPTER_ADDRESSESAdapterAddresses,
__inout PULONG SizePointer
);
其中最主要的还是 __inout PIP_ADAPTER_ADDRESSES AdapterAddresses 大部分信息的储存都在这个结构里(ps:网卡是以链表的方式被存储)也就是,你想知道什么,就查看这个结构体所包含的东西就好。具体官方说明https://msdn.microsoft.com/en-us/library/windows/desktop/aa366058 如果想完全熟悉它,就不得不看了。
代码除了上面的链接,再给一个https://msdn.microsoft.com/en-us/library/windows/desktop/aa366058(其实都差不多)
下面这个我测试可用:
1 #include "stdafx.h" 2 3 4 #include <winsock2.h> 5 #include <iphlpapi.h> 6 #include <stdlib.h> 7 #pragma comment(lib, "IPHLPAPI.lib") 8 9 #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) 10 #define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) 11 /* Note: could also use malloc() and free() */ 12 13 int _tmain(int argc, TCHAR **argv) 14 { 15 16 /* Declare and initialize variables */ 17 18 DWORD dwSize = 0; 19 DWORD dwRetVal = 0; 20 21 int i = 0; 22 23 // Set the flags to pass to GetAdaptersAddresses 24 ULONG flags = GAA_FLAG_INCLUDE_PREFIX; 25 26 // default to unspecified address family (both) 27 ULONG family = AF_UNSPEC; 28 29 LPVOID lpMsgBuf = NULL; 30 31 PIP_ADAPTER_ADDRESSES pAddresses = NULL; 32 ULONG outBufLen = 0; 33 34 PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; 35 PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; 36 PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL; 37 PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL; 38 IP_ADAPTER_DNS_SERVER_ADDRESS *pDnServer = NULL; 39 IP_ADAPTER_PREFIX *pPrefix = NULL; 40 41 if (argc != 2) { 42 printf(" Usage: getadapteraddresses family "); 43 printf(" getadapteraddresses 4 (for IPv4) "); 44 printf(" getadapteraddresses 6 (for IPv6) "); 45 printf(" getadapteraddresses A (for both IPv4 and IPv6) "); 46 exit(1); 47 } 48 49 if (_ttoi(argv[1]) == 4) 50 family = AF_INET; 51 else if (_ttoi(argv[1]) == 6) 52 family = AF_INET6; 53 54 outBufLen = sizeof (IP_ADAPTER_ADDRESSES); 55 pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen); 56 57 // Make an initial call to GetAdaptersAddresses to get the 58 // size needed into the outBufLen variable 59 if (GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen) 60 == ERROR_BUFFER_OVERFLOW) { 61 FREE(pAddresses); 62 pAddresses = (IP_ADAPTER_ADDRESSES *) MALLOC(outBufLen); 63 } 64 65 if (pAddresses == NULL) { 66 printf("Memory allocation failed for IP_ADAPTER_ADDRESSES struct "); 67 exit(1); 68 } 69 // Make a second call to GetAdapters Addresses to get the 70 // actual data we want 71 printf("Memory allocated for GetAdapterAddresses = %d bytes ", outBufLen); 72 printf("Calling GetAdaptersAddresses function with family = "); 73 if (family == AF_INET) 74 printf("AF_INET "); 75 if (family == AF_INET6) 76 printf("AF_INET6 "); 77 if (family == AF_UNSPEC) 78 printf("AF_UNSPEC "); 79 80 dwRetVal = 81 GetAdaptersAddresses(family, flags, NULL, pAddresses, &outBufLen); 82 83 if (dwRetVal == NO_ERROR) { 84 // If successful, output some information from the data we received 85 pCurrAddresses = pAddresses; 86 while (pCurrAddresses) { 87 printf(" Length of the IP_ADAPTER_ADDRESS struct: %ld ", 88 pCurrAddresses->Length); 89 printf(" IfIndex (IPv4 interface): %u ", pCurrAddresses->IfIndex); 90 printf(" Adapter name: %s ", pCurrAddresses->AdapterName); 91 92 pUnicast = pCurrAddresses->FirstUnicastAddress; 93 if (pUnicast != NULL) { 94 for (i = 0; pUnicast != NULL; i++) 95 pUnicast = pUnicast->Next; 96 printf(" Number of Unicast Addresses: %d ", i); 97 } else 98 printf(" No Unicast Addresses "); 99 100 pAnycast = pCurrAddresses->FirstAnycastAddress; 101 if (pAnycast) { 102 for (i = 0; pUnicast != NULL; i++) 103 pAnycast = pAnycast->Next; 104 printf(" Number of Anycast Addresses: %d ", i); 105 } else 106 printf(" No Anycast Addresses "); 107 108 pMulticast = pCurrAddresses->FirstMulticastAddress; 109 if (pMulticast) { 110 for (i = 0; pMulticast != NULL; i++) 111 pMulticast = pMulticast->Next; 112 printf(" Number of Multicast Addresses: %d ", i); 113 } else 114 printf(" No Multicast Addresses "); 115 116 pDnServer = pCurrAddresses->FirstDnsServerAddress; 117 if (pDnServer) { 118 for (i = 0; pDnServer != NULL; i++) 119 pDnServer = pDnServer->Next; 120 printf(" Number of DNS Server Addresses: %d ", i); 121 } else 122 printf(" No DNS Server Addresses "); 123 124 printf(" DNS Suffix: %wS ", pCurrAddresses->DnsSuffix); 125 printf(" Description: %wS ", pCurrAddresses->Description); 126 printf(" Friendly name: %wS ", pCurrAddresses->FriendlyName); 127 128 if (pCurrAddresses->PhysicalAddressLength != 0) { 129 printf(" Physical address: "); 130 for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; 131 i++) { 132 if (i == (pCurrAddresses->PhysicalAddressLength - 1)) 133 printf("%.2X ", 134 (int) pCurrAddresses->PhysicalAddress[i]); 135 else 136 printf("%.2X-", 137 (int) pCurrAddresses->PhysicalAddress[i]); 138 } 139 } 140 printf(" Flags: %ld ", pCurrAddresses->Flags); 141 printf(" Mtu: %lu ", pCurrAddresses->Mtu); 142 printf(" IfType: %ld ", pCurrAddresses->IfType); 143 printf(" OperStatus: %ld ", pCurrAddresses->OperStatus); 144 printf(" Ipv6IfIndex (IPv6 interface): %u ", 145 pCurrAddresses->Ipv6IfIndex); 146 printf(" ZoneIndices (hex): "); 147 for (i = 0; i < 16; i++) 148 printf("%lx ", pCurrAddresses->ZoneIndices[i]); 149 printf(" "); 150 151 pPrefix = pCurrAddresses->FirstPrefix; 152 if (pPrefix) { 153 for (i = 0; pPrefix != NULL; i++) 154 pPrefix = pPrefix->Next; 155 printf(" Number of IP Adapter Prefix entries: %d ", i); 156 } else 157 printf(" No IP Adapter Prefix entries "); 158 159 printf(" "); 160 161 pCurrAddresses = pCurrAddresses->Next; 162 } 163 } else { 164 printf("Call to GetAdaptersAddresses failed with error: %d ", 165 dwRetVal); 166 if (dwRetVal == ERROR_NO_DATA) 167 printf(" No addresses were found for the requested parameters "); 168 else { 169 170 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dwRetVal, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 171 (LPTSTR) & lpMsgBuf, 0, NULL)) { 172 printf(" Error: %s", lpMsgBuf); 173 LocalFree(lpMsgBuf); 174 FREE(pAddresses); 175 exit(1); 176 } 177 } 178 } 179 FREE(pAddresses); 180 return 0; 181 }
虽然GetAdaptersAddresses比较新,而且看到有那么多信息属性,不过好像在网关和子网掩码的获取上,可能没有GetAdapterInfo顺手。我查了一些它的API,不过也出现了下列问题:http://bbs.csdn.net/topics/390036236,没办法,只好用GetAdapterInfo了。
http://www.cnblogs.com/L-hq815/archive/2012/08/04/2622829.html(基本可以直接跑,它对数据结构解释的代码可别往程序里放)
我对它的代码做一个粘贴吧:
1 #include <WinSock2.h> 2 #include <Iphlpapi.h> 3 #include <iostream> 4 using namespace std; 5 #pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库 6 7 int main(int argc, char* argv[]) 8 { 9 //PIP_ADAPTER_INFO结构体指针存储本机网卡信息 10 PIP_ADAPTER_INFO pIpAdapterInfo = new IP_ADAPTER_INFO(); 11 //得到结构体大小,用于GetAdaptersInfo参数 12 unsigned long stSize = sizeof(IP_ADAPTER_INFO); 13 //调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量 14 int nRel = GetAdaptersInfo(pIpAdapterInfo,&stSize); 15 //记录网卡数量 16 int netCardNum = 0; 17 //记录每张网卡上的IP地址数量 18 int IPnumPerNetCard = 0; 19 if (ERROR_BUFFER_OVERFLOW == nRel) 20 { 21 //如果函数返回的是ERROR_BUFFER_OVERFLOW 22 //则说明GetAdaptersInfo参数传递的内存空间不够,同时其传出stSize,表示需要的空间大小 23 //这也是说明为什么stSize既是一个输入量也是一个输出量 24 //释放原来的内存空间 25 delete pIpAdapterInfo; 26 //重新申请内存空间用来存储所有网卡信息 27 pIpAdapterInfo = (PIP_ADAPTER_INFO)new BYTE[stSize]; 28 //再次调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量 29 nRel=GetAdaptersInfo(pIpAdapterInfo,&stSize); 30 } 31 if (ERROR_SUCCESS == nRel) 32 { 33 //输出网卡信息 34 //可能有多网卡,因此通过循环去判断 35 while (pIpAdapterInfo) 36 { 37 cout<<"网卡数量:"<<++netCardNum<<endl; 38 cout<<"网卡名称:"<<pIpAdapterInfo->AdapterName<<endl; 39 cout<<"网卡描述:"<<pIpAdapterInfo->Description<<endl; 40 switch(pIpAdapterInfo->Type) 41 { 42 case MIB_IF_TYPE_OTHER: 43 cout<<"网卡类型:"<<"OTHER"<<endl; 44 break; 45 case MIB_IF_TYPE_ETHERNET: 46 cout<<"网卡类型:"<<"ETHERNET"<<endl; 47 break; 48 case MIB_IF_TYPE_TOKENRING: 49 cout<<"网卡类型:"<<"TOKENRING"<<endl; 50 break; 51 case MIB_IF_TYPE_FDDI: 52 cout<<"网卡类型:"<<"FDDI"<<endl; 53 break; 54 case MIB_IF_TYPE_PPP: 55 printf("PP "); 56 cout<<"网卡类型:"<<"PPP"<<endl; 57 break; 58 case MIB_IF_TYPE_LOOPBACK: 59 cout<<"网卡类型:"<<"LOOPBACK"<<endl; 60 break; 61 case MIB_IF_TYPE_SLIP: 62 cout<<"网卡类型:"<<"SLIP"<<endl; 63 break; 64 default: 65 66 break; 67 } 68 cout<<"网卡MAC地址:"; 69 for (DWORD i = 0; i < pIpAdapterInfo->AddressLength; i++) 70 if (i < pIpAdapterInfo->AddressLength-1) 71 { 72 printf("%02X-", pIpAdapterInfo->Address[i]); 73 } 74 else 75 { 76 printf("%02X ", pIpAdapterInfo->Address[i]); 77 } 78 cout<<"网卡IP地址如下:"<<endl; 79 //可能网卡有多IP,因此通过循环去判断 80 IP_ADDR_STRING *pIpAddrString =&(pIpAdapterInfo->IpAddressList); 81 do 82 { 83 cout<<"该网卡上的IP数量:"<<++IPnumPerNetCard<<endl; 84 cout<<"IP 地址:"<<pIpAddrString->IpAddress.String<<endl; 85 cout<<"子网地址:"<<pIpAddrString->IpMask.String<<endl; 86 cout<<"网关地址:"<<pIpAdapterInfo->GatewayList.IpAddress.String<<endl; 87 pIpAddrString=pIpAddrString->Next; 88 } while (pIpAddrString); 89 pIpAdapterInfo = pIpAdapterInfo->Next; 90 cout<<"--------------------------------------------------------------------"<<endl; 91 } 92 93 } 94 //释放内存空间 95 if (pIpAdapterInfo) 96 { 97 delete pIpAdapterInfo; 98 } 99 100 return 0; 101 }
同样的,多放一个链接:http://blog.csdn.net/zjg555543/article/details/7547309 (真的,都差不多)
add: http://blog.csdn.net/lyd_253261362/article/details/36004167
SECOND STEP:选择网卡完了总要构造包吧
用Winpcap的函数,所以看一下Winpcap主要数据结构及函数 或者 Winpcap编程常用函数和数据结构总结 这篇博文。
Second Step:扫描网段活动主机,选择攻击对象
本来呢,我觉得我发包之后,然后收到了应答包,arp表里就该有它的记录,我只要在程序里用 system命令将 arp -a 的结果输出到文件夹然后再读出就可以了。
但是,在我的系统上,即使收到了包,因为我和这些主机没有真正通信过,arp表根本不理好嘛。。。
所以,我就借用网上某段代码,他用了线程来做这个事情,一边发包,一边收包,我们认为,收到包=主机在活动中
不过pcap中收包有两个函数:一个是回调方式,一个是非回掉方式,我的代码用了后者
Third Step:选择攻击方式,构造包,开始攻击
这个,用pcap的sendpacket和receivepacket就好。主要注意填充的时候啊,那个ip的字节顺序(hton、 ntoh)
为什么后面讲得这么少,因为代码里都有,也附带说明了http://download.csdn.net/detail/u014576894/9207567
学习愉快