본문 바로가기
  • AI (Artificial Intelligence)
Security/Monitoring

[jpcap] JPCAP을 이용한 패킷스니핑

by 로샤스 2014. 12. 4.

통신 Application을 개발하다보면 패킷덤프를 해야 할 경우가 생긴다. 

이럴 경우 자주 사용하는 프로그램이 wireshark(http://www.wireshark.org/)이다. 

그러나 아이러니하게도 wireshark이 워낙 많은 기능을 제공하다보니 우리가 원하는 기능을 따로 덤프할 경우 불편할 때도 생긴다.

이럴 경우, 원하는 네트웍 패킷만 덤프하기 위해서 따로 프로그램을 만드는 경우가 종종 있다.


대부분의 패킷덤프 프로그램은 PCAP 라이브러리를 사용한다. PCAP은 윈도우용도 존재한다.

Java에서 PCAP을 사용하려면 JPcap을 설치해야 한다.


(WinPcap 설치):http://www.winpcap.org/install/default.htm

(JPcap 설치)    http://netresearch.ics.uci.edu/kfujii/Jpcap/doc/download.html


다음은 자바와 winpcap을 이용한 패킷 덤프 예제를 약간 수정 변경한 것이다.


 

/* Program: Console TCP/IP packet sniffer, using jpcap
* Author: Plaguez
* Date: 02.01.2008
* 
* 수정자: 박성완
* 내용  : hex 출력
*/

import java.net.*;
import java.io.*;
import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.NetworkInterface;
import jpcap.NetworkInterfaceAddress;
import jpcap.packet.*;
    
public class Main 
{
        
    JpcapCaptor captor;
    NetworkInterface[] list;
    String str,info;
    int x, nChoice;
    
    int nCountPacket = 0;
            
    public static void main(String args[]) {
        new Main();
    }

    public Main() 
    {
    
        list = JpcapCaptor.getDeviceList();
        System.out.println("Available interfaces: ");
            
        for(x=0; x<list.length; x++) {
            System.out.println(x+" -> "+list[x].description);  
        }
        
        System.out.println("-------------------------\n");
        nChoice = Integer.parseInt(getInput("Choose interface (0,1..): "));
        System.out.println("Listening on interface -> "+list[nChoice].description);
        System.out.println("-------------------------\n");
          
        /*Setup device listener */
        try {
            captor=JpcapCaptor.openDevice(list[nChoice], 65535, false, 20);
             /* listen for TCP/IP only */
            captor.setFilter("ip and tcp", true);
        } catch(IOException ioe) { ioe.printStackTrace(); }
          
          
        /* start listening for packets */
        while (true) { 
            Packet    info = captor.getPacket();
            
            if(info != null){
                String sData = getPacketText(info);
             System.out.print(sData);
            }
        }
    }       
        
    /* get user input */
    public static String getInput(String q) 
    {
        String input = "";
        System.out.print(q);
        BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in));
        try {
            input = bufferedreader.readLine();
        } catch(IOException ioexception) { }
        
      return input;
    }
      
     
     /* return packet data in true text */
    String getPacketText(Packet pack)
    {   
     
        int i=0,j=0;
        
        // Data (Payload)만 출력
        byte[] bytes=new byte[pack.data.length];
        System.arraycopy(pack.data, 0, bytes, 0, pack.data.length);
        
        //--------------------------------------------------------------------
        // 캐스팅한번하면 Packet  클래스가 깨진다. 왜그런지는 모르겠다. --> 패키지특징내지 버그같음..
        //--------------------------------------------------------------------
        String sPackInfo = ""; 
        if( pack.data.length > 0){
            sPackInfo = "SRC:" +  ((IPPacket)pack).src_ip + "\r\n" + "DST:" +  ( (IPPacket)pack).dst_ip;
            sPackInfo += "\r\n" + ShowHex(bytes.length, bytes);
        }
        
        return sPackInfo;
    }
           
           
    // Hex 출력
    private String ShowHex(int nSize, byte[] pData)
    {
        final int DISPLAY_COUNT = 16;
        final int MAX_SIZE      = 1024 * 15; // 최대보여지는개수 
        
        String msg      = "";
        String sTmp     = "";
        String sTmp2    = "";
        String sLineNum = "";
     
        int nLineNum = 0;
         
        msg  = "0000:"; 
        
        if(nSize > MAX_SIZE) nSize = MAX_SIZE; 
                
        for(int i = 1; i < nSize + 1; i++){
            sTmp  = sTmp.format("%02X ", pData[ i - 1 ] );
            if(( pData[ i - 1] < 127) && ( pData[ i - 1] > 32)){
                sTmp2 += sTmp2.format("%c", pData[ i - 1 ] );
         
            } else {
                sTmp2 += ".";
            }
            
            if(i % DISPLAY_COUNT  == 0 && i != 1){
                msg += sTmp;
             
                msg += " ";
                msg += sTmp2;
             
                msg += "\r\n";
             
                sTmp2 = "";
                
                msg += sLineNum.format("%04X:", nLineNum += DISPLAY_COUNT); 
                
            } else if(i == nSize && i % DISPLAY_COUNT != 0 ){ 
                int nEmtSpace = DISPLAY_COUNT - (i % DISPLAY_COUNT);
                for(int j = 0; j < nEmtSpace; j++){
                 sTmp += "   "; 
                }
                msg += sTmp;
                msg += " ";
                msg += sTmp2;
                msg += "\r\n";

            } else { 
                msg += sTmp;
            } 
        }
     
        if ( nSize == 0 ) msg = "";
        return msg;
    }
    
 } 



*) Eclipse에서 JPCAP을 사용할 시 유의점.
JPCAP을 설치하면 c:\Windows\sun\java\lib\ext\ 폴더에 jpcap.jar 파일이 생성된다.
문제는 console에서 JPCAP을 사용하는 java 소스를 컴파일하면 문제없는 데, 이클립스에서 컴파일하려면 에러가 난다.
이유는 "윈도우 폴더의 보안"이 문제였다.

이럴 경우, 인터넷을 뒤져보면 여기저기에서 다음과 같은 해결방법을 알려주고 있다.

1. jpcap.jar를 eclipse의 lib 폴더에 복사
2. ecclipse의 build_path에서 add-jar로 jpcap.jar 추가



 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

출처 : http://blog.naver.com/adsloader/50140192464

(jpcap 자료 중 그나마 가장 쓸모있는 자료인듯)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

댓글