pcap4j编写内网扫描器

一、功能

       网存活主机扫描

二、执行结果

        2.1和nmap执行结果对比

eclipse 内扫描执行结果:

使用nmap扫描执行结果:

三、实现原理

       参考nmap

不同网段:nmap在扫描主机时先arp包解析到网关mac地址,然后发了ping包,icmp timestamp包,http ack包,和https syn包四种探测包。

同一网段:则只发送了arp包,解析到地址的ip则判定主机存活。

四、实现过程

选用开源框架pcap4j,地址是 https://github.com/kaitoy/pcap4j

我的项目地址:https://github.com/hcye/pcap4j_scanner

实现过程分为网段分析、构造数据包、发送数据包、接收并分析数据包、显示结果

4.1 网段分析

     Pcap4JTools类,通过掩码获得扫描网络地址段,判断目标网段是否和自己主机为一个网段。

package com.hcye.myScanner;
import org.pcap4j.core.PcapAddress;
import org.pcap4j.core.PcapNetworkInterface;
public class Pcap4JTools {
   private  int start;
   private  int end;
   private  String iphead;
   private  String mask;
   private String startIp;
   
public int getStart() {
    return start;
}

public int getEnd() {
    return end;
}

public String getIphead() {
    return iphead;
}

public String getMask() {
    return mask;
}

public String getStartIp() {
    return startIp;
}

   public Pcap4JTools(String dstip) {
    // TODO Auto-generated constructor stub
       int end1=0;
       String[] dstips;
       String mask1="";
       String ipheadString;
       int start1;
       String startIp;
       if (dstip.contains("/")) {
           dstips = dstip.split("/");
           mask1 = dstips[1];
           startIp = dstips[0];
       } else {
           mask1 = "32";
           startIp = dstip;
       }
       try {
           Integer.parseInt(mask1);
       } catch (NumberFormatException e) {
           System.out.print("----");
           return;
       }
       String[] ips = startIp.split("\\.");
       if (ips.length != 4) {
           System.out.print("--1--");
           return;
       }
       ipheadString=ips[0]+"."+ips[1]+"."+ips[2]+".";
       start1=Integer.parseInt(ips[3]);
       if (mask1.equals("32") || Integer.parseInt(mask1) > 32 || Integer.parseInt(mask1) < 1) {
           end1 = Integer.parseInt(ips[3]);
       } else {
           end1 = (int) (Integer.parseInt(ips[3]) + Math.pow(2, (32 - Integer.parseInt(mask1))));
           if (end1 > 255) {
               end1 = 255;
           } else {
               /**
                *
                *     剔除广播地址
                *     Remove broadcast address
                * */
               end1 = end1 - 1;
           }
       }
       this.startIp=ipheadString+start1;
       this.end=end1;
       this.mask=mask1;
       this.start=start1;
       this.iphead=ipheadString;
}

 

public static String getIpByNif(PcapNetworkInterface nif) {

    for(PcapAddress ad:nif.getAddresses()) {
        if(ad.getAddress().getHostAddress().length()<=15) {
            return ad.getAddress().getHostAddress();
        }
    }
    return "";
}
public static String getMacByNif(PcapNetworkInterface nif) {
    return nif.getLinkLayerAddresses().get(0).toString();
    
}

public boolean isDifferentVlan(String dstIp,String gateway){
       String[] dstIps= dstIp.split("\\.");
       String[] gateways=gateway.split("\\.");
       String dstIpHead=dstIps[0]+dstIps[1]+dstIps[2];
       String gatewayHead=gateways[0]+gateways[1]+gateways[2];
       if(dstIpHead.equals(gatewayHead)){
           return true;
       }else {
           return false;
       }
   }
}

4.2 构造数据包

      使用接口PacketBuilder构造数据包

package com.hcye.myScanner;
import org.pcap4j.packet.Packet;
import java.net.UnknownHostException;

public interface PacketBuilder {
     Packet getPacket();
     Packet getWholePacket(String dstIp, String dstMac) throws UnknownHostException;
}

本项目涉及4种数据包类型故编写了4个实现类:BuildArpPacket,BuildIcmpPacket,BuildSynPacket,BuildTimeStampPacket,分别用于构造arp包、ping包、syn包、icmp timestamp包。

package com.hcye.myScanner;
import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.ArpHardwareType;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.MacAddress;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class BuildArpPacket implements PacketBuilder {
    private final String srcIpAddress;
    private final String srcMac;
    public BuildArpPacket(PcapNetworkInterface nif){
        this.srcIpAddress=Pcap4JTools.getIpByNif(nif);
        this.srcMac = Pcap4JTools.getMacByNif(nif);
    }
    @Override
    public Packet getPacket() {
        return null;
    }
    @Override
    public Packet getWholePacket(String dstIp, String dstMac) {
        ArpPacket.Builder arpBuilder = new ArpPacket.Builder();
        try {
            arpBuilder
                    .hardwareType(ArpHardwareType.ETHERNET)
                    .protocolType(EtherType.IPV4)
                    .hardwareAddrLength((byte) MacAddress.SIZE_IN_BYTES)
                    .protocolAddrLength((byte) ByteArrays.INET4_ADDRESS_SIZE_IN_BYTES)
                    .operation(ArpOperation.REQUEST)
                    .srcHardwareAddr(MacAddress.getByName(srcMac))
                    .srcProtocolAddr(InetAddress.getByName(srcIpAddress))
                    .dstHardwareAddr(MacAddress.ETHER_BROADCAST_ADDRESS)
                    .dstProtocolAddr(InetAddress.getByName(dstIp));
        } catch (UnknownHostException e) {
            throw new IllegalArgumentException(e);
        }

        EthernetPacket.Builder etherBuilder = new EthernetPacket.Builder();
        etherBuilder
                .dstAddr(MacAddress.ETHER_BROADCAST_ADDRESS)
                .srcAddr(MacAddress.getByName(srcMac))
                .type(EtherType.ARP)
                .payloadBuilder(arpBuilder)
                .paddingAtBuild(true);
        return   etherBuilder.build();
    }


}


-------------------------------------------------------------------------------------------------------------------------------------------------

package com.hcye.myScanner;
import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.ArpHardwareType;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.MacAddress;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class BuildArpPacket implements PacketBuilder {
    private final String srcIpAddress;
    private final String srcMac;
    public BuildArpPacket(PcapNetworkInterface nif){
        this.srcIpAddress=Pcap4JTools.getIpByNif(nif);
        this.srcMac = Pcap4JTools.getMacByNif(nif);
    }
    @Override
    public Packet getPacket() {
        return null;
    }
    @Override
    public Packet getWholePacket(String dstIp, String dstMac) {
        ArpPacket.Builder arpBuilder = new ArpPacket.Builder();
        try {
            arpBuilder
                    .hardwareType(ArpHardwareType.ETHERNET)
                    .protocolType(EtherType.IPV4)
                    .hardwareAddrLength((byte) MacAddress.SIZE_IN_BYTES)
                    .protocolAddrLength((byte) ByteArrays.INET4_ADDRESS_SIZE_IN_BYTES)
                    .operation(ArpOperation.REQUEST)
                    .srcHardwareAddr(MacAddress.getByName(srcMac))
                    .srcProtocolAddr(InetAddress.getByName(srcIpAddress))
                    .dstHardwareAddr(MacAddress.ETHER_BROADCAST_ADDRESS)
                    .dstProtocolAddr(InetAddress.getByName(dstIp));
        } catch (UnknownHostException e) {
            throw new IllegalArgumentException(e);
        }

        EthernetPacket.Builder etherBuilder = new EthernetPacket.Builder();
        etherBuilder
                .dstAddr(MacAddress.ETHER_BROADCAST_ADDRESS)
                .srcAddr(MacAddress.getByName(srcMac))
                .type(EtherType.ARP)
                .payloadBuilder(arpBuilder)
                .paddingAtBuild(true);
        return   etherBuilder.build();
    }


}


--------------------------------------------------------------------------------------------------------------------------------------------------------

package com.hcye.myScanner;

 

import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;

import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.packet.*;
import org.pcap4j.packet.TcpMaximumSegmentSizeOption.Builder;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.packet.namednumber.IpNumber;
import org.pcap4j.packet.namednumber.IpVersion;
import org.pcap4j.packet.namednumber.TcpPort;
import org.pcap4j.util.MacAddress;


public class BuildSynpacket implements PacketBuilder {
    private final TcpPort srcPort;
    private final TcpPort dstPort;
    private final int sequenceNumber;
    private final byte dataOffset;
    private final boolean syn;
    private final short window;
    private final short checksum;
    private final List<TcpPacket.TcpOption> options;
    private final TcpPacket packet;
    private final String srcMac;
    private final String srcIp;

    public BuildSynpacket( PcapNetworkInterface nif)  {
        this.srcIp = Pcap4JTools.getIpByNif(nif);
        this.srcMac = Pcap4JTools.getMacByNif(nif);
        this.srcPort = TcpPort.getInstance((short) ((short) 30000 + Math.random() * 20000));
        this.dstPort = TcpPort.getInstance((short) 443);
        this.sequenceNumber = (short) ((short) 20000 + Math.random() * 20000);
        this.dataOffset = 0;
        this.syn = true;
        this.window = (short) 1024;
        this.checksum = (short) ((short) 20000 + Math.random() * 10000);
        this.options = new ArrayList<TcpPacket.TcpOption>();
        options.add(new Builder().maxSegSize((short) 1460).correctLengthAtBuild(true).build());
        TcpPacket.Builder b = new TcpPacket.Builder();
        b.dstPort(dstPort)
                .srcPort(srcPort)
                .sequenceNumber(sequenceNumber)
                .dataOffset(dataOffset)
                .syn(syn)
                .window(window)
                .checksum(checksum)
                .options(options)
                .correctChecksumAtBuild(false)
                .correctLengthAtBuild(false)
                .paddingAtBuild(true);
        this.packet = b.build();
    }

    @Override
    public Packet getPacket() {
        return packet;
    }

    @Override
    public Packet getWholePacket(String dstIp, String dstMac) throws UnknownHostException {
        Inet4Address srcAddr = (Inet4Address) Inet4Address.getByName(srcIp);
        Inet4Address dstAddr = (Inet4Address) Inet4Address.getByName(dstIp);
        IpV4Packet.Builder IpV4b = new IpV4Packet.Builder();
        IpV4b.version(IpVersion.IPV4)
                .tos(IpV4Rfc1349Tos.newInstance((byte) 0))
                .identification((short) ((short) 20000 + Math.random() * 10000))
                .ttl((byte) 100)
                .protocol(IpNumber.TCP)
                .srcAddr(srcAddr)
                .dstAddr(dstAddr)
                .payloadBuilder(
                        packet
                                .getBuilder()
                                .correctChecksumAtBuild(true)
                                .correctLengthAtBuild(true)
                                .paddingAtBuild(true))
                .correctChecksumAtBuild(true)
                .correctLengthAtBuild(true)
                .paddingAtBuild(true);

        EthernetPacket.Builder eb = new EthernetPacket.Builder();
        eb.dstAddr(MacAddress.getByName(dstMac))
                .srcAddr(MacAddress.getByName(srcMac))
                .type(EtherType.IPV4)
                .payloadBuilder(IpV4b)
                .paddingAtBuild(true);
        eb.get(TcpPacket.Builder.class).dstAddr(dstAddr).srcAddr(srcAddr);
        return eb.build();
    }

}


-------------------------------------------------------------------------------------------------------------------------------------------------

package com.hcye.myScanner;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;

import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.packet.EthernetPacket;
import org.pcap4j.packet.IcmpV4CommonPacket.Builder;
import org.pcap4j.packet.IcmpV4TimestampPacket;
import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.IpV4Rfc1349Tos;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.SimpleBuilder;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.packet.namednumber.IcmpV4Code;
import org.pcap4j.packet.namednumber.IcmpV4Type;
import org.pcap4j.packet.namednumber.IpNumber;
import org.pcap4j.packet.namednumber.IpVersion;
import org.pcap4j.util.MacAddress;

public class BuildTimeStampPacket implements PacketBuilder {
    private final IcmpV4TimestampPacket packet;
    private final short identifier;
    private final short sequenceNumber;
    private final int originateTimestamp;
    private final int receiveTimestamp;
    private final int transmitTimestamp;
    private final String srcIp;
    private final String srcMac;
    public BuildTimeStampPacket(PcapNetworkInterface nif) {
        this.srcIp = Pcap4JTools.getIpByNif(nif);
        this.srcMac = Pcap4JTools.getMacByNif(nif);
        this.identifier = (short) ((short) Math.random()*10000+1000);
        this.sequenceNumber = (short) 0;
        this.originateTimestamp = 0;
        this.receiveTimestamp = 0;
        this.transmitTimestamp = 0;

        IcmpV4TimestampPacket.Builder b = new IcmpV4TimestampPacket.Builder();
        b.identifier(identifier)
                .sequenceNumber(sequenceNumber)
                .originateTimestamp(originateTimestamp)
                .receiveTimestamp(receiveTimestamp)
                .transmitTimestamp(transmitTimestamp);
        this.packet = b.build();
    }

    @Override
    public Packet getPacket() {
        return packet;
    }

    @Override
    public Packet getWholePacket(String dstIp, String dstMac) throws UnknownHostException {
        Builder icmpV4b = new Builder();
        icmpV4b
                .type(IcmpV4Type.TIMESTAMP)
                .code(IcmpV4Code.NO_CODE)
                .payloadBuilder(new SimpleBuilder(packet))
                .correctChecksumAtBuild(true);

        IpV4Packet.Builder ipv4b = new IpV4Packet.Builder();
        ipv4b
                .version(IpVersion.IPV4)
                .tos(IpV4Rfc1349Tos.newInstance((byte) 0))
                .identification((short) 100)
                .ttl((byte) 100)
                .protocol(IpNumber.ICMPV4)
                .srcAddr(
                        (Inet4Address)
                                InetAddress.getByName(srcIp))
                .dstAddr(
                        (Inet4Address)
                                InetAddress.getByName(dstIp))
                .payloadBuilder(icmpV4b)
                .correctChecksumAtBuild(true)
                .correctLengthAtBuild(true);

        EthernetPacket.Builder eb = new EthernetPacket.Builder();
        eb.dstAddr(MacAddress.getByName(dstMac))
                .srcAddr(MacAddress.getByName(srcMac))
                .type(EtherType.IPV4)
                .payloadBuilder(ipv4b)
                .paddingAtBuild(true);
        return eb.build();
    }
}


--------------------------------------------------------------------

4.3 发送数据包

SendPacket类

构造函数解析:PcapNetworkInterface nif,虚拟网络接口,String dstIp,目标ip 如果是单ip的话 192.168.100.1网段192.168.100.1/24   24是掩码,String gateway目标地址网段,ExecutorService pool 线程池,PacketBuilder builde数据包构造器

public SendPacket(PcapNetworkInterface nif,String dstIp,String gateway,ExecutorService pool,PacketBuilder builder) {
        this.nif=nif;
        this.dstIP=dstIp;
        this.pool=pool;
        this.gateway=gateway;
        this.builder=builder;
    }

---------------------------------------------------------------------------------------------------------------------------------

 

package com.hcye.myScanner;

import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;

import org.pcap4j.core.NotOpenException;
import org.pcap4j.core.PcapHandle;
import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.core.PcapNetworkInterface.PromiscuousMode;
import org.pcap4j.packet.Packet;

public class SendPacket {
    private final String dstIP;
    private final String gateway;
    private final PacketBuilder builder;
    private final PcapNetworkInterface nif;
    private final ExecutorService pool;
    public SendPacket(PcapNetworkInterface nif,String dstIp,String gateway,ExecutorService pool,PacketBuilder builder) {
        this.nif=nif;
        this.dstIP=dstIp;
        this.pool=pool;
        this.gateway=gateway;
        this.builder=builder;
    }
    public void send() throws PcapNativeException, UnknownHostException {   //发送函数
        String dstMac="";

       //通过虚接口获得数据包操作对象PcapHandle
        PcapHandle sendHandler=nif.openLive(65536, PromiscuousMode.PROMISCUOUS, 10);  

      //如果发送请求不是arp,则先使用arp包解析到网关mac地址
        if(!builder.getClass().getSimpleName().equals("BuildArpPacket"))
        {    SendArpRequest arp =new SendArpRequest();
            dstMac=arp.sendArp(gateway,nif);
        }
        Pcap4JTools tools=new Pcap4JTools(dstIP);
        int start = tools.getStart();
        int end = tools.getEnd();
        String iphead=tools.getIphead();

//执行使用线程池发送数据包
        for(int i=start;i<=end;i++) {
            task t=new task(builder, nif, iphead+i, dstMac, sendHandler);
            pool.execute(t);
        }
    }
    private class task implements Runnable {
        private final PcapNetworkInterface nif;
        private final PacketBuilder builder;
        private final String dstip;
        private final String dstMac;
        private PcapHandle sendHandle;

        public task(PacketBuilder builder, PcapNetworkInterface nif, String dstip, String dstMac, PcapHandle sendHandle) {
            this.nif = nif;
            this.builder = builder;
            this.dstip = dstip;
            this.dstMac = dstMac;
            this.sendHandle = sendHandle;
        }

        /**
         * When an object implementing interface <code>Runnable</code> is used
         * to create a thread, starting the thread causes the object's
         * <code>run</code> method to be called in that separately executing
         * thread.
         * <p>
         * The general contract of the method <code>run</code> is that it may
         * take any action whatsoever.
         *
         * @see Thread#run()
         */
        @Override
        public void run() {

            Packet packet;
            try {
                packet = builder.getWholePacket(dstip,dstMac);
                if (!sendHandle.isOpen()) {
                    sendHandle = nif.openLive(65536, PcapNetworkInterface.PromiscuousMode.PROMISCUOUS, 10);
                }
                /**
                 *
                 *     每个请求发送两次
                 *    Two per request
                 *
                 * */
                for(int i=0;i<2;i++) {
                     sendHandle.sendPacket(packet);
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (PcapNativeException e) {
                e.printStackTrace();
            } catch (NotOpenException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
    }
}

4.4 接收数据包

      MyPacketListener 类

package com.hcye.myScanner;

import org.pcap4j.core.*;
import org.pcap4j.core.PcapNetworkInterface.PromiscuousMode;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.IcmpV4EchoReplyPacket;
import org.pcap4j.packet.IcmpV4TimestampReplyPacket;
import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.TcpPacket;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.TcpPort;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class MyPacketListener {
    private int counter=0;
    public Set<String> lisener(String dstip, PcapNetworkInterface nif,List<PacketBuilder> builder) throws PcapNativeException{
        Pcap4JTools tools = new Pcap4JTools(dstip);
        String srcip = Pcap4JTools.getIpByNif(nif);
        Set<String> set = new HashSet<>();

//构造带缓存的包处理器,防止漏包
        PcapHandle.Builder handleBuilder =
                new PcapHandle.Builder(nif.getName())
                    .snaplen(65536)
                    .promiscuousMode(PromiscuousMode.PROMISCUOUS)
                    .timeoutMillis(10)
                    .bufferSize(1024*1024*10);
            PcapHandle sendHandler=handleBuilder.build();
      
        String ipHead =tools.getIphead();
        /*
         *     获得需要扫描的ip总数
         *
         * */
        int scanIpCount =( tools.getEnd() - tools.getStart())*builder.size();

      //构造个单线程充当计时器以控制扫描时间,超时则退出进程
        ExecutorService pool=Executors.newSingleThreadExecutor();
        timer t=new timer(scanIpCount);
        Future<Boolean> f=pool.submit(t);
        try {
            while(!f.isDone()) {    //future done以后结束while循环停止接收数据包
                Packet packet=sendHandler.getNextPacket();
                if(packet==null) {
                    continue;
                }
                for(PacketBuilder b:builder) {
                 if(b.getClass().getSimpleName().equals("BuildArpPacket")) {
                    if(packet.contains(ArpPacket.class)) {
                        ArpPacket arp=packet.get(ArpPacket.class);
                        if(arp.getHeader().getOperation()==ArpOperation.REPLY) {
                            /**
                             *     转换成arp包,过滤reply包
                             *  Convert to ipv4 packet to judge
                             *
                             * */
                              counter++;
                              for (int i = tools.getStart(); i <=  tools.getEnd(); i++) {
                                  if (arp.getHeader().getDstProtocolAddr().getHostAddress().equals(srcip) && arp.getHeader().getSrcProtocolAddr().getHostAddress().equals(ipHead + i))
                                      set.add(ipHead + i);
                              }
                        }
                    }
                    
                }else if (b.getClass().getSimpleName().equals("BuildIcmpPacket")) {
                    if(packet.contains(IcmpV4EchoReplyPacket.class)) {
                        IpV4Packet icmpreply=packet.get(IpV4Packet.class);
                        /**
                         *    转换成IPv4包进行判断
                         *    Convert to ipv4 packet to judge
                         * */
                         counter++;
                         for (int i =tools.getStart(); i <= tools.getEnd(); i++) {
                             if (icmpreply.getHeader().getSrcAddr().getHostAddress().equals(ipHead + i) && icmpreply.getHeader().getDstAddr().getHostAddress().equals(srcip)) {
                                 set.add(ipHead + i);
                             }
                    }
                    }
                    
                }else if(b.getClass().getSimpleName().equals("BuildSynpacket")) {
                    if(packet.contains(TcpPacket.class)) {
                        TcpPacket tcp=packet.get(TcpPacket.class);
                        if(tcp.getHeader().getSrcPort()==TcpPort.HTTPS) {
                            /**
                             *     转换成tcp包进行判断,tcp包含端口信息
                             * Convert to tcp packet for judgment, tcp packet contain port information
                             *
                             * */
                             counter++;
                            IpV4Packet syn=packet.get(IpV4Packet.class);
                             for (int i =tools.getStart(); i <= tools.getEnd(); i++) {
                                    if (syn.getHeader().getSrcAddr().getHostAddress().equals(ipHead + i) && syn.getHeader().getDstAddr().getHostAddress().equals(srcip)) {
                                        set.add(ipHead + i);
                                    }
                        }
                        }
                        }
                }else if(b.getClass().getSimpleName().equals("BuildTimeStampPacket")) {
                    if(packet.contains(IcmpV4TimestampReplyPacket.class)) {
                        IpV4Packet timestamp=packet.get(IpV4Packet.class);
                        /**
                         *     转换成IPv4包进行判断
                         *     Convert to ipv4 packet to judge
                         *
                         * */
                         counter++;
                         for (int i =tools.getStart(); i <= tools.getEnd(); i++) {
                                if (timestamp.getHeader().getSrcAddr().getHostAddress().equals(ipHead + i) && timestamp.getHeader().getDstAddr().getHostAddress().equals(srcip)) {
                                    set.add(ipHead + i);
                                }
                    }
                    
                }
                
                }
                }
                if(counter>=scanIpCount) {
                    sendHandler.close();
                    break;
                }
            }
        } catch (NotOpenException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        pool.shutdownNow();
        sendHandler.close();
        return set;
    }
    private class timer implements Callable<Boolean>{
        private final int ipCount;
        public timer(int ipcount) {
            this.ipCount=ipcount;
        }
        @Override
        public Boolean call()  {
            // TODO Auto-generated method stub
            int i=0;
            while(i<ipCount) {
                try {
                    /**
                     *     计时器进程以20毫秒为单位,可调整
                     *    Timer process is adjustable
                     *
                     * */
                    Thread.sleep(20);
                    i++;
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    return false;
                }
            
            }
            return true;
        }
        
    }
}

4.5 封装的统一执行函数

package com.hcye.myScanner;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import org.pcap4j.core.PcapNativeException;
import org.pcap4j.core.PcapNetworkInterface;
import org.pcap4j.core.Pcaps;

public class ScanLiveIp {
    /*
     * String dstIp="10.75.70.1/24"; //目标网段 String gateway="10.75.60.1"; //网关 String
     * myInterIp="10.75.60.155";//我的网卡地址
     */    
    public void scan(String dstIp,String gateway,String myInterIp) throws UnknownHostException, PcapNativeException {
        long i=System.currentTimeMillis();
        PcapNetworkInterface nif=Pcaps.getDevByAddress(InetAddress.getByName(myInterIp));
        Pcap4JTools tools=new Pcap4JTools(dstIp);
        Future<Set<String>> f=null;
        ExecutorService soonPool=Executors.newCachedThreadPool();
        ExecutorService fatherPool=Executors.newCachedThreadPool();
        List<PacketBuilder> builders=new ArrayList<PacketBuilder>();
        /**
         * 判断是否是同一个网段
         * 此处默认按照 24位掩码判断,对于自身广播域掩码小于24位时会出现部分地址扫描不到的情况,可以对 所有目标地址广播arp请求,如果返回则认定同一网段。
         * 没有arp reply 地址的默认为不同网段发送 icmp syn timestamp 请求。
         *
         * */
        if(tools.isDifferentVlan(dstIp, gateway)) {
            PacketBuilder arpBuilder = new BuildArpPacket(nif);
            builders.add(arpBuilder);
        }else {
            PacketBuilder icmpBuilder=new BuildIcmpPacket(nif);
            PacketBuilder timstamp=new BuildTimeStampPacket(nif);
            PacketBuilder synPacket=new BuildSynpacket(nif);
            builders.add(icmpBuilder);
            builders.add(timstamp);
            builders.add(synPacket);
        }
//        PcapNetworkInterface nif,String dstIp,String gateway,ExecutorService pool,PacketBuilder builder
        
        for(PacketBuilder b:builders) {
            task t=new task(dstIp,nif,builders);
            f=fatherPool.submit(t);
            task1 t1=new task1(nif,dstIp,gateway,soonPool,b);
            fatherPool.execute(t1);
        }
        
        
        try {
            Set<String> s=f.get();
            if(tools.isDifferentVlan(dstIp, gateway)) {
                s.add(myInterIp);
                s.add(gateway);
            }
            for(String str:s) {
                System.out.println(str);
            }
            System.out.println(s.size()+" hosts up");
        } catch (InterruptedException | ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            soonPool.shutdownNow();
            fatherPool.shutdownNow();
            System.out.print("scanned in "+((System.currentTimeMillis()-i)/1000.00)+" seconds");
        }
    }
    
    

    
private class task implements Callable<Set<String>>{
    private final String dstip;
    private final PcapNetworkInterface nif;
    private final List<PacketBuilder> builder;
    public task(String dstip,PcapNetworkInterface nif,List<PacketBuilder> builder) {
        this.dstip=dstip;
        this.nif=nif;
        this.builder=builder;
    }
    @Override
    public Set call() throws Exception {
        // TODO Auto-generated method stub
        MyPacketListener listener=new MyPacketListener();
        Set<String> set=listener.lisener(dstip, nif, builder);
        return set;
    }
    
}
private class task1 implements Runnable{
//    nif, dstIp,gateway, pool,icmpBuilder
    private final PcapNetworkInterface nif;
    private final String dstIp;
    private final String gateway;
    private final ExecutorService pool;
    private final PacketBuilder builder;
    public task1(PcapNetworkInterface nif,String dstIp,String gateway,ExecutorService pool,PacketBuilder builder) {
        this.nif=nif;
        this.dstIp=dstIp;
        this.pool=pool;
        this.gateway=gateway;
        this.builder=builder;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        SendPacket sendPacket=new SendPacket(nif, dstIp,gateway, pool,builder);
        try {
            sendPacket.send();
        } catch (UnknownHostException | PcapNativeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
}

}

-------------------------------------------------------------------------------------------------------------------------------------

4.6 测试方法

package com.hcye.myScanner;
import java.net.UnknownHostException;
import org.pcap4j.core.PcapNativeException;
public class MyTest1 {
    public static void main(String[] args) throws UnknownHostException, PcapNativeException {
        String dstIp="10.75.60.1/24"; //目标网段   Target segment,可以跨网段扫描
        String gateway="10.75.60.1";  //网关 gateway
        String myInterIp="10.75.60.155";//我的网卡地址 My network card address
        ScanLiveIp scan=new ScanLiveIp();
        scan.scan(dstIp, gateway, myInterIp);
    }
}

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值