linux局域网arp,通过发送arp请求检测局域网内是否有机器处于混杂模式(有linux源代码)...

目的:

今天饱受局域网内的arp欺骗困挠,所以复习了一下相关的arp方面的知识。mark一下。

功能:

检测局域网内的某台机器是否处于混杂模式状态。

原理:

构造一个arp请求数据帧发送给带检测的机器。通过是收到arp响应判断带检测的机器是否处于混杂模式。首先构造出下面的数据帧。

ARP分组:

目的以太网地址 00 00 00 00 00 00(说明1)

发送方以太网地址 00 11 22 33 44 55(说明2)

高层协议类型 08 00(IP)

硬件类型 00 01(以太网)

硬件地址长度 06(以太网地址长度)

IP地址长度 04

发送方的IP地址 本机IP地址

目标的IP地址 被检测主机的IP地址

ARP操作码 00 01(ARP请求01、ARP应答02)

以太网帧:

协议类型 08 06(ARP)

发送方的硬件地址 本机以太网卡地址

目标硬件地址 FF FF FF FF FF FE

说明1:这时ARP要查询的以太网地址,全部填0或者1都可以。

说明2:用自己的以太网地址代替。

复制过来,省得打字太麻烦,最关键的一句话就是这里了:目标硬件地址 FF FF FF FF FF FE。这个地址是个特殊的mac地址叫做为广播地址。他有这样的特点,不管在windows或者linux环境下,当网卡处于混杂模式的情况下,网卡的硬件过滤器不会过滤该分组,当然是废话了,混杂模式的网卡才不管你这个地址是什么了,他什么都不过滤,但是如果是普通模式的情况下,硬件过滤器会丢弃该数据帧。那么我们就不会收到arp响应了。接着假如带检测的机器网卡在混杂模式下,该数据帧就会进行下一步处理,也就是通过软件过滤器了。目前的软件过滤器实现一般只判断这个mac地址的第一个字节是不是FF,如果是FF,软件过滤器就把这个数据帧当作是广播处理,就是不过滤的意思了,这样就会交给内核正常的处理流程了,这样的话处于混杂模式的机器就会发送一个arp相应给我们了,那就ok了。反之如果不是FF,软件过滤器就会丢弃掉这个数据帧,这就是为什么我们要把这个目标硬件地址设置成FF FF FF FF FF FE的原因了。

代码:

[code]

#include #include #include

#include #include #include #include #include #include

//arp frame header (14 bytes)

struct frame_hdr {

unsigned char dst_mac[6];

unsigned char src_mac[6];

unsigned short frm_type;

};

//arp frame header+body (14+8+20 bytes)

struct frame_ether {

struct frame_hdr fh;

struct arphdr ah;

unsigned char src_mac[6];

unsigned char src_ip[4];

unsigned char dst_mac[6];

unsigned char dst_ip[4];

};

int main(int argc, char **argv) {

int sockfd;

struct sockaddr_ll peer_addr;

//创建AF_PACKET类型socket

sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));

if(sockfd == -1)perror("socket()");

//初始化struct sockaddr_ll 类型的socket地址结构

memset(&peer_addr, 0, sizeof(peer_addr));

peer_addr.sll_family = AF_PACKET;

struct ifreq req;

strcpy(req.ifr_name, "eth0");

if(ioctl(sockfd, SIOCGIFINDEX, &req) != 0)perror("ioctl()");

peer_addr.sll_ifindex = req.ifr_ifindex;

peer_addr.sll_protocol = htons(ETH_P_ARP);

//发送arp请求到要检测的机器ip

unsigned char bad_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}; //伪广播地址,混杂模式下,软件过滤层不会过滤该数据帧。就是说会有arp相应了

unsigned char my_ip[4] = {192, 168, 1, 99};  //本机的ip地址

unsigned char my_mac[6] = {0x00, 0x0c, 0x29, 0x5e, 0x01, 0xff}; //本机的mac地址

unsigned char dst_ip[4] = {192, 168, 1, 102}; //要检测是否处于混杂模式的机器ip

unsigned char dst_mac[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

//build arp frame

struct frame_ether frame;

memcpy(frame.fh.dst_mac, bad_mac, 6);

memcpy(frame.fh.src_mac, my_mac, 6);

frame.fh.frm_type = htons(ETH_P_ARP);

frame.ah.ar_hrd = htons(ARPHRD_ETHER);

frame.ah.ar_pro = htons(ETH_P_IP);

frame.ah.ar_hln = 6;

frame.ah.ar_pln = 4;

frame.ah.ar_op = htons(ARPOP_REQUEST);

memcpy(frame.src_mac, my_mac, 6);

memcpy(frame.src_ip, my_ip, 4);

memcpy(frame.dst_mac, dst_mac, 6);

memcpy(frame.dst_ip, dst_ip, 4);

int nbytes = sendto(sockfd, &frame, sizeof(frame), 0, (struct sockaddr*)&peer_addr, sizeof(peer_addr));

printf("nbytes = %d\n", nbytes);

return 0;

}

[/code]

说明:

linux的2.6内核。

直接gcc编译。

然后执行。

同时打开一个窗口用tcpdump arp 观察是否收到了arp响应。

最后:

that's all!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值