IP-Pakete erzeugen mit hping

Dieser Text befindet sich in der neusten Version auf http://www.eggdrop.ch/texts/hping/.

Warnung

Das versenden von fehlerhaften Paketen kann zu Netzwerkstörungen oder Abstürzen von Computersystemen führen. Ich übernehme keine Verantwortung für Schäden, die durch die Benutzung von hping entstanden sind. Die folgenden Beispiele dürfen nur zu Test- und Lernzwecken im eigenen Netzwerk auf eigene Verantwortung durchgeführt werden.

Inhalt

1 Einleitung
1.1 Was ist hping?
1.2 Voraussetzungen
2 Benutzen von hping
2.1 ICMP oder TCP Ping
2.2 Weitere Optionen
2.3 IP-Pakete in eine bestehende Verbindung schicken

1. Einleitung

1.1 Was ist hping?

hping (http://www.hping.org/) ist ein Programm, mit welchem sich selber IP-Pakete erstellen lassen. In diesem Text werde ich eine kurze Beschreibung dieses Programms mit Beispielen aus der Praxis zeigen.

1.2 Voraussetzungen

Dieser Text setzt voraus, dass du ein UNIX-Betriebssystem installiert hast (z.B. Linux) mit folgenden wichtigen Netzwerk-Tools: telnet (standardmässig vorinstalliert), netcat (wird mit nc aufgerufen), tcpdump (http://www.tcpdump.org/) oder einen anderen Sniffer und natürlich hping (http://www.hping.org/). Du musst grundlegende UNIX-Befehle und Netzwerkgrundlagen kennen, also unter anderem wie der IP bzw. TCP-Header aussieht (Bücher und Texte darüber gibt es genug).

2. Benutzen von hping

2.1 ICMP oder TCP Ping

hping wird immer als root ausgeführt, weil normale Benutzer keine Rechte haben, um IP-Pakete zu erstellen. Das Programm sieht zunächst wie ping aus. Wir geben eine Adresse als Argumemnt an und hping liefert uns unter anderem die Zeit, die vergeht, bis das Paket wieder ankommt:

[root@server /root]# hping 192.168.0.2
HPING 192.168.0.2 (rl1 192.168.0.2): NO FLAGS are set, 40 headers + 0 data bytes
len=46 ip=192.168.0.2 flags=RA DF seq=0 ttl=64 id=0 win=0 rtt=0.8 ms
len=46 ip=192.168.0.2 flags=RA DF seq=1 ttl=64 id=0 win=0 rtt=0.4 ms
len=46 ip=192.168.0.2 flags=RA DF seq=2 ttl=64 id=0 win=0 rtt=0.4 ms
len=46 ip=192.168.0.2 flags=RA DF seq=3 ttl=64 id=0 win=0 rtt=0.4 ms
^C
--- 192.168.0.2 hping statistic ---
4 packets tramitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 0.4/0.5/0.8 ms
[root@server /root]# 

hping sendet dabei ein TCP/IP-Paket an 192.168.0.2 Port 0, worauf ein Rechner ohne Firewall mit einem RST-Paket reagiert, was man an der Ausgabe von hping sieht. len ist die länge des empfangenen Pakets in Bytes, ip ist klar, flags kann folgende Buchstaben haben:

DF bedeutet, dass das Don't fragment-Bit gesetzt ist und rtt zeigt die Zeit an, nach welcher das Paket zurückgekommen ist. Unter tcpdump sieht dieses Pingen folgendermassen aus:

192.168.0.1.1947 > 192.168.0.2.0: . win 512
192.168.0.2.0 > 192.168.0.1.1947: R 0:0(0) ack 970862968 win 0 (DF)

Wollen wir den Ping über ICMP senden, machen wir das mit der Option -1. Die Anzahl der Pings geben wir mit der Option -c ein:

[root@server /root]# hping -1 -c 2 192.168.0.2        
HPING 192.168.0.2 (rl1 192.168.0.2): icmp mode set, 28 headers + 0 data bytes
46 bytes from 192.168.0.2: icmp_seq=0 ttl=64 id=32251 rtt=0.8 ms
46 bytes from 192.168.0.2: icmp_seq=1 ttl=64 id=32252 rtt=0.4 ms

--- 192.168.0.2 hping statistic ---
2 packets tramitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.4/0.6/0.8 ms
[root@server /root]# 

2.2 Weitere Optionen

Zurück zum Senden von TCP Paketen. Um den Zielport anzugeben (Standard war ja 0), verwenden wir die Option -p. Ich möchte in diesem Beispiel SYN-Pakete zu einem HTTP-Server schicken. Deshalb verwende ich hier -p 80 und -S, um das SYN-Flag einzuschalten (andere Flags verwenden den selben Parameter wie in der Liste in Abschnitt 2.1, also z.B. -F für FIN).

[root@server /root]# hping 192.168.0.2 -p 80 -S
HPING 192.168.0.2 (rl1 192.168.0.2): S set, 40 headers + 0 data bytes
len=46 ip=192.168.0.2 flags=SA DF seq=0 ttl=64 id=0 win=5840 rtt=0.8 ms
len=46 ip=192.168.0.2 flags=SA DF seq=1 ttl=64 id=0 win=5840 rtt=0.5 ms
^C
--- 192.168.0.2 hping statistic ---
2 packets tramitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.5/0.6/0.8 ms
[root@server /root]# 

So weit gut, nun, wenn wir das Ganze unter tcpdump anschauen, ergibt sich folgendes Bild pro Ping:

192.168.0.1.1819 > 192.168.0.2.80: S 1059302232:1059302232(0) win 512
192.168.0.2.80 > 192.168.0.1.1819: S 3275439828:3275439828(0) ack 1059302233 win 5840 <mss 1460> (DF)
192.168.0.1.1819 > 192.168.0.2.80: R 1059302233:1059302233(0) win 0

Das liest sich wie folgt: 192.168.0.1 (der Computer der die Pings sendet) sendet ein Paket mit SYN-Flag gesetzt nach 192.168.0.2 (das Opfer). 192.168.0.2 antwortet mit SYN und ACK, aber 192.168.0.1 sendet ein RST zurück. Das ist deshalb, weil 192.168.0.1 nicht "weiss", dass hping versucht hat, eine Verbindung herzustellen und denkt, es seie ein fälschlich empfangenes Paket. Um das zu verhindern, müssen wir unsere Quelladresse verändern, was sich auch "spoofen" nennt (wir könnten auch dem Kernel bzw. einer direkt davor liegenden Firewall sagen, dass er/sie keine RST-Pakete schicken soll). Auch das beherrscht hping ohne Problem mit der Option -a:

[root@server /root]# hping 192.168.0.2 -p 80 -S -a 192.168.0.5
HPING 192.168.0.2 (rl1 192.168.0.2): S set, 40 headers + 0 data bytes
^C
--- 192.168.0.2 hping statistic ---
4 packets tramitted, 0 packets received, 100% packet loss
round-trip min/avg/max = 0.0/0.0/0.0 ms
[root@server /root]# 

192.168.0.5 ist hier eine nicht-existierende Adresse. tcpdump meint:

192.168.0.5.2835 > 192.168.0.2.80: S 434998816:434998816(0) win 512
arp who-has 192.168.0.5 tell 192.168.0.2

Weil der Rechner im LAN die Mac-Adresse zum Versenden der Nachricht braucht und die nicht hat, verwende ich einen existierenden Rechner 192.168.0.3, welcher aber alle Pakete verwirft:

192.168.0.3.2843 > 192.168.0.2.22: S 408201400:408201400(0) win 512
192.168.0.2.22 > 192.168.0.3.2843: S 118197321:118197321(0) ack 408201401 win 5840 <mss 1460> (DF)

Jetzt Antwortet der Host brav dem 192.168.0.3 mit SYN und ACK.

Das Senden der Pakete geht standardmässig im Sekundentakt. Mit der Option -i oder mit --fast lassen sich andere Geschwindigkeiten festlegen:

2.3 IP-Pakete in eine bestehende Verbindung schicken

Nehmen wir mal an, wir haben eine Verbindung mit einem Host aufgebaut und wollen nun mit hping etwas hinein senden. Dazu lassen wir Netcat auf einem Port lauschen, hier 2000. Das geht mit einem folgenden Aufrüfe (je nach Netcat-Version):

nc -lp 2000
nc -l 2000

Du kannst natürlich auch ein eigenes Programm verwenden, welches auf einem Port lauscht. Bevor ich mich mit dem Host verbinde, starte ich noch im Hintergrund tcpdump, am Besten mit der Option -n, welche bewirkt, dass die Hostnamen und Portnamen nicht aufgelöst werden, weil sonst sieve statt 2000 steht. Zusätzlich verwende ich noch -S - was das bewirkt, werde ich dir später erklären. Nun kann ich mich mit dem PC verbinden:

[tom@ws tom]$ telnet 192.168.0.1 2000
Trying 192.168.0.1...
Connected to 192.168.0.1.
Escape character is '^]'.

Hier der ein bisschen verkürzte Output von tcpdump -n -S:

192.168.0.2.32988 > 192.168.0.1.2000: SWE 241717173:241717173(0) win 5840 (DF) [tos 0x10] 
192.168.0.1.2000 > 192.168.0.2.32988: S 1918513912:1918513912(0) ack 241717174 win 17376
192.168.0.2.32988 > 192.168.0.1.2000: . ack 1918513913 win 5840 (DF) [tos 0x10] 

Nun, wie schicken wir jetzt ein Paket mit hping an den Zielhost? Zuerst müssen wir den Quellport angeben, welcher hier 32988 ist, was mit der Option -s geschieht. Um Daten mit hping zu verschicken, erstellen wir eine Datei mit dem Inhalt, z.B.:

echo hallo! > data

Damit wir diese Datei mit hping verwenden können, müssen wir die Grösse der Datei bestimmen, hier 7 (6 für hallo! und 1 für das Abschliessende \n). Bei grösseren Dateien können wir das auch mit ls -l datei ermitteln. Mit der Option -d geben wir die ermittelte Grösse an und mit -E den Dateinamen. Daraus ergäbe sich der folgende Aufruf:

hping -s 32988 -p 2000 -A -d 7 -E data -c 1 192.168.0.1

Wenn wir dieses Paket losschicken, bemerken wir, dass der Host zwar mit ACK antwortet, aber die Nachricht wird nicht bei 192.168.0.1 angezeigt. Warum? Ganz einfach: Weil die 32 Bit lange Sequence Nummer und Acknowledgement Nummer nicht mit der unseres Pakets übereinstimmt. Schauen wir uns nochmal oben die Ausgabe von tcpdump an. Hier sehen wir die Zahlen 241717173 bzw. 241717174 und 1918513912 bzw. 1918513913. Das sind die Sequenznummern und die Bestätigungsnummern (Acknowledgement). Die Option -S, die wir vorhin bei tcpdump verwendet haben bewirkt, dass die absoluten Nummern stehen und nicht die relativen, weil es hier in diesem Beispiel einfacher mit relativen Nummern ist. Natürlich könnten wir die Option auch weglassen. Die Sequenznummer wird jedes Mal, wenn wir etwas senden, um die Anzahl der gesendeten Bytes erhöht. Dasselbe geschieht mit der Bestätigungsnummer, wenn wir etwas empfangen. Wie müssen wir nun vorgehen? Mit -M setzen wir die Sequenznummer und mit -L die Bestätigungsnummer. Hier der ganze Vorgang mit dem 3-Weg-Handshake und dem zu sendenden und daraufhin empfangenen Paket:

     192.168.0.1                                                     192.168.0.2
        +---+                                                           +---+
  |  1. |   |  SYN        SEQ = 241717173                               |   |
  |     |   | <-------------------------------------------------------- |   |
  |     |   |                                                           |   |
  |  2. |   |  SYN, ACK   SEQ = 1918513912       ACK = 241717174 (+1)   |   |
  |     |   | --------------------------------------------------------> |   |
  |     |   |                                                           |   |
  |  3. |   |  ACK        SEQ = 241717174        ACK = 1918513913 (+1)  |   |
  |     |   | <-------------------------------------------------------- |   |
  |     |   |                                                           |   |
  |     |   | Senden von Daten (7 Bytes):                               |   |
  |  4. |   |  ACK        SEQ = 241717174        ACK = 1918513913       |   |
  |     |   | <-------------------------------------------------------- |   |
  |     |   |                                                           |   |
  |  5. |   |  ACK        SEQ = 1918513913       ACK = 241717181 (+7)   |   |
  |     |   | --------------------------------------------------------> |   |
 \|/    |   |                                                           |   |

Wir müssen dabei das 4. Paket erzeugen, was mit folgendem Aufruf erledigt wird:

hping -s 32988 -p 2000 -A -d 7 -E data -c 1 -M 241717174 -L 1918513913 192.168.0.1

tcpdump zeigt hier auch das Richtige an:

192.168.0.2.33109 > 192.168.0.1.2000: . 241717174:241717181(7) ack 1918513913 win 512
192.168.0.1.2000 > 192.168.0.2.33109: . ack 241717181 win 17376

Leider wird durch unseren Eingriff die originale Verbindung, die wir mit Telnet hergestellt haben, unbrauchbar, weil der Zielrechner die höhere Sequenznummer erwartet und telnet immer noch mit der alten sendet, weil telnet ja nicht wissen kann, dass hping etwas dazwischengesendet hat. Um überhaupt noch etwas mit der Telnet-Verbindung anfangen zu können, können wir ein Paket gleicher Länge an den Zielhost schicken, welches zwar verworfen wird, jedoch wird die Sequenznummer bei Telnet erhöht, sodass das nächste Paket wieder ankommen sollte.

Übrigens habe ich beim Testen herausgefunden, dass es bei älteren Versionen von hping einen Bug gibt, der es nicht erlaubt, Sequenznummern, die höher als 2147483647 sind, zu benutzen. Betroffen war bei mir die Version, die bei Debian Woody dabei ist. Abhilfe schuf das kompilieren der neusten Version von http://www.hping.org/.


Zurück zu www.eggdrop.ch
 
Letzte Änderung: 08.02.06
Copyright (C) 2003-2006 by Thomas "tom" S. <tom at eggdrop.ch>
Valid HTML 4.0!

Creative Commons License

Dieses Werk gehört zu http://www.eggdrop.ch/ und ist unter einer Creative Commons Lizenz lizensiert.