프로그래밍/jpcap programming
JPCAP 패킷 캡쳐
dp.
2011. 6. 2. 10:37
작성자 : 유창훈
안녕하세요 이번엔, 패킷을 캡쳐하는 방법을 설명하도록 하겠습니다.
안녕하세요 이번엔, 패킷을 캡쳐하는 방법을 설명하도록 하겠습니다.
지난 번에 말씀드렸던 jpcap에서는 몇가지 유용한 패키지를 제공해주고 있습니다.
저번시간에 JpcapCaptor.getDeviceList() 라는 메소드를 통해서 디바이스 드라이버 정보를 얻어오는 방법을 알아보았습니다.
이번 시간에는 패킷을 캡쳐해주는 메소드에 대해서 알아보도록 하겠습니다.
- public static JpcapCaptor openDevice(NetworkInterface intrface,
int snaplen, boolean promisc, int to_ms)
이 메소들를 통해서 패킷을 받아오게 되는데요. 다음의 메소드도 같이 보세요.
- public int loopPacket(int count,PacketReceiver handler)
openDevice 메소드를 통해 패킷 캡쳐를 활성화 시키고, loopPackt으로 패킷이 캡쳐되었을때 어떠한 행동을 할지 지정이 가능합니다
- openDevice(인터페이스번호, 한번에 캡쳐가능한byte, true면 promisc모드, processPacket()의 Timeout)
- loopPacket(캡쳐할 패킷수[-1이면 무제한], 패킷이 캡쳐되었을때 실행할 메소드)
일단 소스를 보면서 얘기하도록 하겠습니다.
일단 패킷캡쳐하는 부분만 따로 테스트를 해보느라, 저번에 소스와 통합과 GUI프로그래밍은 패킷 보내기 까지 완성된후 하도록 하겠습니다.
여기서 dump클래스는 패킷이 캡쳐되었을때, 수행되는 클래스입니다. dump에서 결과적으로 eceivePacket()메소드가 실행되는 구조입니다.
=========dump.java===========
import jpcap.*;
import jpcap.packet.Packet;
class dump implements PacketReceiver {
public void receivePacket(Packet p) {
/*Jpcap에서 패킷을 받아오는 형식은 byte형 으로 어떤 패킷구조 형식을 띄기 쉬운 형태로 유저에게 던져주게 됩니다. Jpcap에서 사용자 편하게 하려고 여러 메소드들을 많이 만들어놔서 구현이 편하게 하였는데요. 개인적으로 제가 하고자하는 것은 프래임에서 앞에 동화를 위한 dst_mac addr부터 시작되는 모든 부분을 가공이 되지 않은 형태로 받아와서 , 우리가 원하는 형태로 조작하는 것이기 때문에, 최대한 어떠한 틀이 잡혀있지 않은상태로 , 단순히 배열에 쭉~ 담겨져있는 상태로 패킷을 받고자 하였습니다.
*/
byte[] bytes = new byte[p.header.length + p.data.length];
//Jpcap이라는 놈이 패킷을 잡았을때, 어떠한 패킷이든 Packet이라는 틀에 넣어두면서 //header과 data부분으로 구분지어 놓는 형태입니다.
System.arraycopy(p.header, 0, bytes, 0, p.header.length);
System.arraycopy(p.data, 0, bytes, p.header.length, p.data.length);
//이렇게 하면 우리가 선언한 bytes 라는 byte형 배열에 캡쳐된 패킷이 쭉 담기게 됩니다.
if(bytes[6]==(byte)0x00 &&
bytes[7]==(byte)0x0d &&
//byte형 배열이라 byte형태로 값을 비교합니다. 매줄마다 형변환하는게 귀찮아서
//한번에 어떻게 처리해놓고하는방법이 없을까 했는데, 잘 안되네요. . 자바 고수님들 ~~help//
bytes[8]==(byte)0x60 &&
bytes[9]==(byte)0xb7 &&
bytes[10]==(byte)0x40 &&
bytes[11]==(byte)0xf7 )
//저희 강의실 선생님 컴퓨터 맥주소가 00-0d-60-b6-40-f7입니다.
//이더넷프래임에서 6,7,8,9,10,11번째 바이트가 출발지 mac주소입니다.
{
System.out.println("From teacher");
}
/*StringBuffer buf = new StringBuffer();
for (int i = 0, j; i < bytes.length;) {
for (j = 0; j < 8 && i < bytes.length; j++, i++) {
String d = Integer.toHexString((int) (bytes[i] & 0xff));
buf.append((d.length() == 1 ? "0" + d : d) + " ");
if (bytes[i] < 32 || bytes[i] > 126)
bytes[i] = 46;
}
buf.append("[" + new String(bytes, i - j, j) + "]\n");
}
System.out.println(buf.toString());
*/
}
public static void main(String[] args) throws Exception {
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
if (args.length < 1) {
System.out.println("usage: java Tcpdump <select a number from the following>");
for (int i = 0; i < devices.length; i++) {
System.out.println(i + " :" + devices[i].name + "("
+ devices[i].description + ")");
System.out.println(" data link:" + devices[i].datalink_name
+ "(" + devices[i].datalink_description + ")");
System.out.print(" MAC address:");
for (byte b : devices[i].mac_address)
System.out.print(Integer.toHexString(b & 0xff) + ":");
System.out.println();
for (NetworkInterfaceAddress a : devices[i].addresses)
System.out.println(" address:" + a.address + " "
+ a.subnet + " " + a.broadcast);
}
} else {
JpcapCaptor jpcap = JpcapCaptor.openDevice(devices[Integer.parseInt(args[0])], 2000, true, 1);
//j실행을위한 arg값을 인자로 받아실행, 최대 2000byte까지캡쳐, promics모드작동
jpcap.loopPacket(-1, new dump());
///패킷이 캡쳐되면 dump()를 실행하여라
}
}
}
=======================
실행한상태에서 다른커맨드창 띄워서 ping 을 하면 필터링된 맥주소가 출발지인 패킷만 화면에 보여주게 됩니다.
이제 우리가 원하는 디바이스에 접근하여 원하는 모드로 원하는 양만큼 패킷을 캡쳐할 수 있고, 무엇보다도 원하는 형태의 패킷을 캡쳐할 수 있습니다.
오늘은 여기까지 하도록 하겠습니다.
다음시간은 패킷 보내는걸 알아보도록 하겠습니다.
* 참고로 녹색으로 주석 되어있는부분은 출력형식을 좀 조절하여 표현한것입니다. 간단하게 패킷 캡쳐 프로그램을 구현해 보았습니다.