一、功能
网存活主机扫描
二、执行结果
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);
}
}