用Java实现ARP的收发

Tags: , ,

Jpcap的安装

  • 下载并安装Java Runtime.
  • 下载并安装Winpcap.
  • 下载并安装Jpcap.注意生成的jpcap.jar和jpcap.dll的文件路径。

在Eclipse中配置Jpcap

  • 创建Java Project
  • 将jpcap.jar添加到classpath中。
  • 将jpcap.dll拷贝到eclipse.exe同一目录下。


获得网络接口列表

现在的笔记本都至少有两个以上的网络接口,Jpcap只能针对一个网络接口进行网络包的监听收发,所以第一步是要了解你有哪些网络接口。这是一段现成的代码。

// Obtain the list of network interfaces
NetworkInterface[] devices = JpcapCaptor.getDeviceList();

// for each network interface
for (int i = 0; i < devices.length; i++) { // print out its name and description System.out.println(i + ": " + devices[i].name + "(" + devices[i].description + ")"); // print out its datalink name and description System.out.println(" datalink: " + devices[i].datalink_name + "(" + devices[i].datalink_description + ")"); // print out its MAC address System.out.print(" MAC address:"); for (byte b : devices[i].mac_address) System.out.print(Integer.toHexString(b & 0xff) + ":"); System.out.println(); // print out its IP address, subnet mask and broadcast address for (NetworkInterfaceAddress a : devices[i].addresses) System.out.println(" address:" + a.address + " " + a.subnet + " " + a.broadcast);

访问ARP Table

Java没有办法直接访问Windows下的ARP Table,网上推荐的方法是调用Command Line和SNMP两种。我这里使用的是前者。

final String dosCommand = “arp -a “;
try {
final Process process = Runtime.getRuntime().exec(dosCommand);
BufferedReader br = new BufferedReader(new InputStreamReader(
process.getInputStream()));
String line = null;
/*
* example:192.168.124.255 ff-ff-ff-ff-ff-ff 静态
*/
while ((line = br.readLine()) != null) {
if (line.indexOf(” ” + ip.getHostName() + ” “) > -1) {
StringTokenizer st = new StringTokenizer(line);
st.nextToken();
// return the mac address according to the ip
return st.nextToken();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return null;

针对特定IP发起ARP Request

注意“captor.setFilter(“arp”, true);”的作用是过滤除了ARP之外所有的网络包,用于之后的网络包监听。

int index = Integer.parseInt(args[0]);
InetAddress targetIP = InetAddress.getByName(args[1]);
NetworkInterface device = getDevice(index);
JpcapCaptor captor = JpcapCaptor.openDevice(device, 65535, false,
20);
captor.setFilter(“arp”, true);
JpcapSender sender = captor.getJpcapSenderInstance();
// 进行广播数据报的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 = device.addresses[0].address.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

Jpacap处理网络包的形式有好几种,具体可以参考官网的Tutorial.我这里使用的getPacket使用的blocking模式,所以不会同步处理包监听。
这段代码最后会判断返回的mac是否是本地缓存的,如果不是则可以认为是ARP欺骗。

while (true) {
ARPPacket packet = (ARPPacket) captor.getPacket();
if (packet != null && packet.operation == ARPPacket.ARP_REPLY) {
Inet4Address ip = (Inet4Address) packet
.getSenderProtocolAddress();
if (ip.equals(targetIP)) {
String localMac = ARP.getMacByIP(ip);
if (localMac != null ){
localMac = localMac.replaceAll(“-”, “:”);
}
if (localMac.equals(packet.getSenderHardwareAddress())) {
//Cheat
System.exit(1);
}
}
}
}

问题总结

Can’t load IA 32-bit .dll on a AMD 64-bit platform
Jpcap目前不支持64位,如果你Eclipse运行的vm是64位的,就会报这个错,下载一个32位的JRE或者JDK就可以了。


java.lang.UnsatisfiedLinkError: no jpcap in java.library.path
这是classpath中找不到DLL文件,解决的办法很多。我的做法是把jpcap.dll拷贝到eclipse.exe的文件夹下。

参考链接

WinPcap
Jpcap Download
Jpcap How to install
Jpcap 在myeclipse下的安装
JPCAP——Java中的数据链路层控制(libpcap)

 

无觅相关文章插件,快速提升流量