Promiscuous Mode Detector

Transcrição

Promiscuous Mode Detector
Praktische Diplomarbeit 2004 — Sna04/2
Promiscuous Mode Detector
H ALM R EUSSER
[email protected]
IT01
R ANKO V ESELINOVI Ć
[email protected]
IT01
25. Oktober 2004
Betreut durch Prof. Dr. A NDREAS S TEFFEN
Zusammenfassung
Im Zeitalter der kontinuierlichen Vernetzung und permanenter Erreichbarkeit der Rechner wird
die Sicherheit der Netze immer wichtiger. Es vergeht kein Monat, in dem man nicht von Datendiebstahl bei Firmen liest. Sensible Daten werden unverschlüsselt über das lokale Netz geschickt. Diese grobe Fahrlässigkeit gewisser Administratoren erleichtert den Datendieben das
Leben.
Mit einer L INUX-LiveCD und einem normalen Arbeitsplatzrechner ist man schon genügend
ausgestattet, um sensible Daten zu erhaschen. Die dazu notwendige Software ist ein NetworkAnalyser oder Sniffer. Beides sind passive Elemente, welche man theoretisch von aussen nicht
detektieren kann. Da es aber keine fehlerfreie Software gibt, ist es möglich, Fehler der Implementierung auszunutzen und die unerwünschten Zuhörer zu detektieren.
Bis jetzt existierte kein O PEN S OURCE Tool, welches in der Lage war, Sniffer aus der Ferne zu
detektieren. Um dieses Manko zu beseitigen, wurde im Rahmen dieser Diplomarbeit ein solches
Tool entwickelt. Es wurden vorhandene Methoden zusammengetragen, analysiert und bewertet.
Die erfolgversprechendsten wurden dann in Form von Plugins in die Software eingebunden.
Mit der vorliegenden Arbeit, halten Sie nun ein Tool zum Detektieren von Sniffern im Netzwerk
in den Händen. Bei neun von zehn Betriebssystemen waren alle implementierten Methoden erfolgreich. Einzig S UN OS 5.7 war in der Lage drei von vier Testmethoden zu trotzen.
In der Testphase mussten wir feststellen, dass viele embedded Systeme, wie es z.B. Netzwerkdrucker, Druckerserver und ADSL-Router sind, schlecht implementierte Networkstacks besitzen. Dies kann unter Umständen zu falschen Verdächtigungen führen. Im Netzwerk sollte dies
jedoch kein Problem darstellen, da diese Geräte von vornherein bekannt sein sollten.
Die Arbeit konnten wir erfolgreich abschliessen. Damit steht den Administratoren ein hilfreiches
und mächtiges Werkzeug zur Verfügung, welches den Script-Kiddies das Leben schwer machen
wird.
Winterthur, 23. Oktober 2004
H ALM R EUSSER
R ANKO V ESELINOVI Ć
I
Abstract
In an era of continuous networking and permanent accessibility of computers, network security
has become a serious issue. News about data theft in companies has become a common headline. Sensitive data is sent unencrypted over the wire. This culpable negligence of certain network
administrators makes the life for data thieves easier.
All you need is a L INUX-LiveCD and a common PC to start snooping around for sensitive data.
The Software need is a network analyser or sniffer. Both of them are passive elements and theoretically not detectable from outside. As a matter of fact, accurate software does not exist. This
makes it possible to exploit weakness of implementation and detect the unwanted listener.
Up until now there was no open source tool that was able to detect a sniffer. Within the scope of
our diploma thesis, existing methods should be collected, analysed and evaluated. Furthermore
a tool had to be developed, which implements the auspicious methods and closes the gap.
The document you’re holding in your hands provides you with a tool which is able to detect
sniffers from outside. The testing of nine out of ten operating systems with all implemented methods was successful. S UN OS 5.7 though was able to defy three of four methods.
During testing we discovered that some embedded systems, e.g. network printers, print servers
and ADSL routers have a really bad network stack. Using such stacks can lead to false suspicion.
However, administrators in a corporate network should have all the necessary information about
such devices so they should not pose a challenge anymore.
We successfully finished our diploma thesis. Network administrators are provided with a useful
and powerful tool which will make the life for script-kiddies hard.
III
Erklärung betreffend das selbständige Verfassen einer
Projekt- oder Diplomarbeit im Dept. T
Mit der Abgabe dieser Projekt-/VDP-/SDP-Arbeit versichert der/die Studierende, dass er/sie die Arbeit
selbständig und ohne fremde Hilfe verfasst hat. (Bei Gruppenarbeiten gelten die Leistungen der
übrigen Gruppenmitglieder nicht als fremde Hilfe.)
Der/die unterzeichnende Studierende erklärt, dass alle zitierten Quellen (auch Internetseiten) im Text
oder Anhang korrekt nachgewiesen sind, d.h. dass die Projekt-/VDP-/SDP-Arbeit keine Plagiate
enthält, also keine Teile, die teilweise oder vollständig aus einem fremden Text oder einer fremden
Arbeit unter Vorgabe der eigenen Urheberschaft bzw. ohne Quellenangabe übernommen worden
sind.
Bei Verfehlungen aller Art werden die Paragraphen 35 und 36 (Unredlichkeit und Verfahren bei
Unredlichkeit) des Reglements für Prüfungen am TWI sowie die Bestimmungen des
Disziplinarverfahrens der Hochschulordnung (Paragraph 38) angewendet.
Ort, Datum:
........................................................
Unterschriften:
.........................................................
.........................................................
.........................................................
Dieses Formular ist bei allen abgegebenen Projekt- und Diplomarbeiten nach der Aufgabenstellung
mit Original-Unterschrift und –Datum (keine Kopie) einzufügen.
Inhaltsverzeichnis
Vorbemerkungen
I.
XVII
Einleitung
1
1. Aufgabenstellung
3
2. Pflichtenheft
2.1. Ziele . . . . . . . . . . . . . . . . . . . . .
2.2. Anforderungen an das zu entwickelnde Tool
2.3. Projektplan . . . . . . . . . . . . . . . . .
2.4. Dokumentation . . . . . . . . . . . . . . .
.
.
.
.
5
5
5
6
6
3. Was sind Sniffer?
3.1. Einsatz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
7
4. Wie funktioniert ein Sniffer?
4.1. shared und microsegmentiertes LAN . . . . . . . . . . . . . . . . . . . . . . .
4.2. promiscuous mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3. Implementation in L INUX? . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
8
8
9
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
II. Theorie: Sniffer Erkennung
11
5. Networkstack Tests
5.1. Grundlagen . . . . . . . . . . . . . . . .
5.1.1. Hardware-Filter . . . . . . . . . .
5.1.2. Software-Filter . . . . . . . . . .
5.1.3. Reaktionen . . . . . . . . . . . .
5.2. ARP-Test . . . . . . . . . . . . . . . . .
5.2.1. Das Address Resolution Protocol
5.2.2. Methode . . . . . . . . . . . . .
5.2.3. Erweiterungen . . . . . . . . . .
5.2.4. Voraussetzungen . . . . . . . . .
5.2.5. Evaluation . . . . . . . . . . . .
5.3. ICMP-Test . . . . . . . . . . . . . . . . .
VII
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
14
14
14
15
16
18
18
21
21
22
22
22
Inhaltsverzeichnis
5.3.1. Internet Control Message Protocol Echo-Request & Echo-Reply
5.3.2. Methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.3. Voraussetzungen . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.4. Evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4. Source Route . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4.1. Source Routing . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4.2. Methode . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6. DNS Test
6.1. Das Domain Name System
6.2. Methode . . . . . . . . . .
6.3. Erweiterungen . . . . . . .
6.4. Voraussetzungen . . . . .
6.5. Evaluation . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
22
24
24
25
25
25
26
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
28
28
30
31
31
31
7. LATENCY-Tests
7.1. ICMP-Time-Delta- & Ping-Drop-Test . . . . .
7.1.1. Methode . . . . . . . . . . . . . . . .
7.1.2. Erweiterungen . . . . . . . . . . . . .
7.1.3. Voraussetzungen . . . . . . . . . . . .
7.1.4. Evaluation . . . . . . . . . . . . . . .
7.2. Timestamp-Request . . . . . . . . . . . . . . .
7.2.1. ICMP-Timestamp-Request und -Reply
7.2.2. Methode . . . . . . . . . . . . . . . .
7.2.3. Erweiterungen . . . . . . . . . . . . .
7.2.4. Voraussetzungen . . . . . . . . . . . .
7.2.5. Evaluation . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
32
32
32
33
33
33
34
34
35
35
35
35
8. Weitere Methoden
8.1. Host . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2. Decoy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.3. SNMP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
36
37
37
III.
38
SAD
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
— Sniff And Die
9. Design
9.1. UML-Diagramm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
39
40
10. Das Framework
10.1. Der Option-Manager . . . .
10.2. Der Configfile-Parser . . . .
10.3. Der Kommandozeilen-Parser
10.4. Threads . . . . . . . . . . .
10.4.1. InjectionThread . . .
41
41
42
44
45
45
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
VIII
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Inhaltsverzeichnis
10.4.2. CaptureThread . .
10.5. Die Scan-Strategy . . . . .
10.5.1. Vorlage für Plugins
10.5.2. Thread Handling .
10.6. Exceptions . . . . . . . . .
10.6.1. SadEx . . . . . . .
10.6.2. Anwendung . . . .
10.7. SAD . . . . . . . . . . . .
10.7.1. Rating . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11. Plugin-HowTo
11.1. Das L INUX-Plugin-Interface . . . . . . . . . . . .
11.2. Probleme mit C++ . . . . . . . . . . . . . . . . .
11.3. Die Umsetzung bei SAD . . . . . . . . . . . . . .
11.4. Schreiben eines eigenen Plugins . . . . . . . . . .
11.4.1. Bekanntgabe der Optionen . . . . . . . . .
11.4.2. Implementieren der setLocalVal() Methode
11.4.3. Implementation der scan() Methode . . . .
12. SAD-Plugins
12.1. ARP . . . . . . . .
12.2. ICMP . . . . . . .
12.3. DNS . . . . . . . .
12.4. LATENCY . . . .
12.4.1. LatencyCT
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
45
46
46
47
48
48
48
50
51
.
.
.
.
.
.
.
52
52
52
53
54
54
54
55
.
.
.
.
.
57
57
57
58
59
59
IV. Auswertung
61
13. Vorhandene Tools
63
14. SAD
14.1. LATENCY-Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.1.1. Messungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.1.2. Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
64
64
67
15. Ausnahmen
15.1. Phänomen Surecom Router . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15.2. false positives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
68
68
69
16. Ausblick
16.1. Anti-SAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16.2. Zukunft von SAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
71
71
71
IX
Inhaltsverzeichnis
Schlusswort
73
V.
74
Anhang
A. Projektplan
75
B. Ein einfacher L INUX-Sniffer
77
C. L INUX Networkstack-Walkthrough
C.1. Ethernet Card and Lower-Kernel Reception — Layer 1
C.2. Network Core Processing — Layer 2 . . . . . . . . . .
C.2.1. NAPI . . . . . . . . . . . . . . . . . . . . . .
C.2.2. netif_rx() und netif_rx_schedule() . . . . . . .
C.2.3. NET_RX softirq net_rx_action() . . . . . . . .
C.3. Ausgewählte Passagen aus den Kernelsourcen . . . . .
80
80
81
81
82
83
83
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
D. Glossar
86
Literaturverzeichnis
87
E. The GNU General Public License
89
F. Code
F.1. Makefile . . . . . . . . .
F.2. Framework . . . . . . .
F.2.1. optionMgr.hpp .
F.2.2. optionMgr.cpp .
F.2.3. Option . . . . .
F.2.4. cfgParser.hpp . .
F.2.5. cfgParser.cpp . .
F.2.6. console.hpp . . .
F.2.7. console.cpp . . .
F.2.8. sadThread.hpp .
F.2.9. captureT.hpp . .
F.2.10. captureT.cpp . .
F.2.11. injectionT.hpp .
F.2.12. injectionT.cpp . .
F.2.13. latencyCT.hpp .
F.2.14. latencyCT.cpp .
F.2.15. ScanStrategy.hpp
F.2.16. ScanStrategy.cpp
F.2.17. sadEx.hpp . . . .
F.2.18. sad.cpp . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
X
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
97
98
100
100
100
101
102
102
105
105
108
108
109
111
111
113
113
115
116
120
121
Inhaltsverzeichnis
F.3. Plugins . . . . . .
F.3.1. arp.hpp . .
F.3.2. arp.cpp . .
F.3.3. icmp.hpp .
F.3.4. icmp.cpp .
F.3.5. dns.hpp . .
F.3.6. dns.cpp . .
F.3.7. latency.hpp
F.3.8. latency.cpp
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
XI
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
125
125
125
129
129
133
133
137
137
Abbildungsverzeichnis
4.1. Ethernet-Frames in einem shared LAN . . . . . . . . . . . . . . . . . . . . . .
4.2. promiscuous mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.3. Paket-Prozess-Kette . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8
9
10
5.1.
5.2.
5.3.
5.4.
5.5.
5.6.
5.7.
5.8.
5.9.
.
.
.
.
.
.
.
.
.
15
19
20
21
23
24
25
26
27
6.1. Der DNS-Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
30
7.1. Time-Delta-Test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.2. ICMP Timestamp-Request/-Reply Nachricht . . . . . . . . . . . . . . . . . . .
33
34
9.1. UML-Diagramm von SAD . . . . . . . . . . . . . . . . . . . . . . . . . . . .
40
10.1. Flussdiagramm: SAD-Ablauf . . . . . . . . . . . . . . . . . . . . . . . . . . .
50
14.1.
14.2.
14.3.
14.4.
.
.
.
.
66
66
67
67
C.1. Old API: Kernel <2.4.19 . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
C.2. New API (NAPI): Kernel ≥ 2.4.19 . . . . . . . . . . . . . . . . . . . . . . . .
81
82
Der L INUX Software-Filter . . . . . . . . . .
Die Arbeitsweise von ARP . . . . . . . . . .
ARP-Paket . . . . . . . . . . . . . . . . . .
ARP-Detektion . . . . . . . . . . . . . . . .
Aufbau eines ICMP Request/Reply Paketes .
ICMP-Test . . . . . . . . . . . . . . . . . . .
Format der source route Option im IP-Header
Ablauf source routing . . . . . . . . . . . . .
source routing Methode . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Durchschnittliche Antwortzeit im unbelasteten Netzwerk
Durchschnittliche Antwortzeit im belasteten Netzwerk .
Durchschnittliche Drops im belasteten Netzwerk . . . .
Erzeugte Netzlast . . . . . . . . . . . . . . . . . . . . .
XII
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tabellenverzeichnis
5.1. Reaktionen auf ARP-Scans . . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
14.1. Analysierte Betriebssysteme . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.2. Angaben zur Messreihe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14.3. Durschnittswerte der 10 Tests . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
65
65
XIII
Listings
5.1. ARP Request . . . . . . . . . . . . . . . . . . . . . . . .
5.2. ARP Reply . . . . . . . . . . . . . . . . . . . . . . . . .
5.3. Echo Request . . . . . . . . . . . . . . . . . . . . . . . .
5.4. Echo Reply . . . . . . . . . . . . . . . . . . . . . . . . .
5.5. source routing . . . . . . . . . . . . . . . . . . . . . . . .
6.1. DNS-Query . . . . . . . . . . . . . . . . . . . . . . . . .
6.2. DNS-Response . . . . . . . . . . . . . . . . . . . . . . .
6.3. Reverse-DNS-Query . . . . . . . . . . . . . . . . . . . .
6.4. Reverse-DNS-Response . . . . . . . . . . . . . . . . . . .
7.1. ICMP Timestamp-Request . . . . . . . . . . . . . . . . .
7.2. ICMP Timestamp-Reply . . . . . . . . . . . . . . . . . . .
8.1. O PEN BSD: ifconfig -a . . . . . . . . . . . . . . . . . . .
8.2. L INUX: dmesg | grep -i promiscuous . . . . . . . . . . . .
10.1. Die Klasse OptionMgr . . . . . . . . . . . . . . . . . . .
10.2. Der Option-Struct . . . . . . . . . . . . . . . . . . . . . .
10.3. Aufbau einer Option . . . . . . . . . . . . . . . . . . . .
10.4. Aufbau von sad.conf . . . . . . . . . . . . . . . . . . . .
10.5. Die Klasse cfgParser . . . . . . . . . . . . . . . . . . . .
10.6. Die Klasse console . . . . . . . . . . . . . . . . . . . . .
10.7. CaptureT: nonblocking . . . . . . . . . . . . . . . . . . .
10.8. CaptureT: Konstruktor . . . . . . . . . . . . . . . . . . .
10.9. ScanStrategy::addThread() . . . . . . . . . . . . . . . . .
10.10.ScanStrategy::startThreads() . . . . . . . . . . . . . . . .
10.11.SadEx . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10.12.Ableitung von SadEx . . . . . . . . . . . . . . . . . . . .
10.13.Eine Exception werfen . . . . . . . . . . . . . . . . . . .
10.14.Eine Exception abfangen . . . . . . . . . . . . . . . . . .
10.15.S AD Verwaltungs-Konstrukte . . . . . . . . . . . . . . . .
10.16.Optionen von SAD . . . . . . . . . . . . . . . . . . . . .
10.17.Ausgabe von SAD . . . . . . . . . . . . . . . . . . . . . .
11.1. Das L INUX-Plugin-Interface . . . . . . . . . . . . . . . .
11.2. Definition der class factory functions im ScanStrategy.hpp
11.3. class factory functions am Beispiel vom ARP-Plugin . . .
11.4. Bekanntgabe der Optionen . . . . . . . . . . . . . . . . .
11.5. Setzen der lokalen Variablen . . . . . . . . . . . . . . . .
XIV
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
20
20
23
23
26
28
28
29
29
34
35
36
36
41
41
42
43
43
44
45
45
47
47
48
48
48
49
50
51
51
52
53
53
54
54
Listings
11.6. Eintrag in sad.conf . . . . . .
12.1. Optionen des Plugins ARP . .
12.2. Optionen des Plugins ICMP .
12.3. DNS-Test: Bau der IP-Adresse
12.4. Dynamischer Bau des Filters .
12.5. Optionen des Plugins DNS . .
12.6. Optionen des Plugins Latency
12.7. Latency CaptureThread . . . .
15.1. fake ICMP Request . . . . . .
15.2. Erwartete Antwort . . . . . .
15.3. Multicast korrigiertes Paket . .
15.4. Zweite Antwort . . . . . . . .
B.1. Minisniffer . . . . . . . . . .
B.2. Ausgabe . . . . . . . . . . . .
C.1. net/core/dev.c . . . . . . . . .
C.2. net/ethernet/eth.c . . . . . . .
C.3. net/ipv4/arp.c . . . . . . . . .
C.4. net/ipv4/ip_input.c . . . . . .
Makefile . . . . . . . . . . . . . . .
OptionMgr.hpp . . . . . . . . . . .
OptionMgr.cpp . . . . . . . . . . .
Option.hpp . . . . . . . . . . . . .
cfgParser.hpp . . . . . . . . . . . .
cfgParser.cpp . . . . . . . . . . . .
console.hpp . . . . . . . . . . . . .
console.cpp . . . . . . . . . . . . .
sadThread.hpp . . . . . . . . . . . .
captureT.hpp . . . . . . . . . . . . .
captureT.cpp . . . . . . . . . . . . .
injectionT.hpp . . . . . . . . . . . .
injectionT.cpp . . . . . . . . . . . .
latencyCT.hpp . . . . . . . . . . . .
latencyCT.cpp . . . . . . . . . . . .
ScanStrategy.hpp . . . . . . . . . .
ScanStrategy.cpp . . . . . . . . . .
sadEx.hpp . . . . . . . . . . . . . .
sad.cpp . . . . . . . . . . . . . . .
arp.hpp . . . . . . . . . . . . . . .
arp.cpp . . . . . . . . . . . . . . . .
icmp.hpp . . . . . . . . . . . . . .
icmp.cpp . . . . . . . . . . . . . . .
dns.hpp . . . . . . . . . . . . . . .
dns.cpp . . . . . . . . . . . . . . .
latency.hpp . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
XV
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
56
57
57
58
58
58
59
60
68
68
68
69
77
79
83
84
84
85
98
100
100
101
102
102
105
105
108
108
109
111
111
113
113
115
116
120
121
125
125
129
129
133
133
137
Listings
latency.cpp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
XVI
Vorbemerkungen
Dieses Dokument wurde in LATEX 2ε geschrieben. Dabei haben wir uns an folgende Konventionen gehalten:
Namen von Personen, Firmen und Produkten werden mit K APITÄLCHEN dargestellt.
Schlüsselworte werden kursiv dargestellt.
Verweise auf Literatur zum jeweiligen Thema, werden nur beim ersten Auftauchen des Begriffes gemacht (z.B. LATEX 2ε [1]).
Code-Schnipsel werden in Schreibmaschinenschrift dargestellt.
Listings werden in der Listing-Umgebung dargestellt.
# i n c l u d e < s t d i o . h>
i n t main ( v o i d )
{
/ ∗ H e l l o World ∗ /
p r i n t f ( " H e l l o World \ n " ) ;
return 0;
}
# zeigt, dass es sich um eine Root-Shell handelt.
$ zeigt, dass es sich um eine User-Shell handelt.
Wenn im Dokument von uns die Rede ist, bezieht sich das immer auf die Autoren dieses Dokumentes, d.h. auf die Herren H ALM R EUSSER & R ANKO V ESELINOVI Ć.
XVII
Teil I.
Einleitung
Zusammenfassung
In diesem Kapitel wird kurz erklärt, was einen Sniffer ausmacht und wozu er eingesetzt wird.
Es wird auch erklärt, was der Unterschied zwischen einem shared und einem microsegmentierten LAN ist. Des Weiteren werden der Begriff promiscuous mode eingeführt und eine kurze
Information zur Implementation eines Sniffers in L INUX vorgestellt.
1. Aufgabenstellung
3
4
2. Pflichtenheft
Angenehm sind die erledigten
Arbeiten.
(Marcus Tullius Cicero
(106-43))
2.1. Ziele
Ziel dieser Diplomarbeit ist das Schreiben eines Promiscuous Mode Detectors. Des Weiteren
sollen die vorhandenen Methoden analysiert und bewertet werden. Dies beinhaltet eine Untersuchung der Schwächen von Ethernet- und TCP/IP-Implementierungen und wie diese für unsere
Ziele ausgenutzt werden können. Ausgiebige Tests an den Betriebssystemen
• L INUX 2.2, 2.4 und 2.6
• O PEN BSD
• F REE BSD
• M AC OSX
• S UN OS 5.7
• W INDOWS 2000/XP
sollen die ganze Arbeit abrunden. An dieser Stelle sei nochmals darauf hingewiesen, dass nur
Software-Sniffer auf IP-Basis erkannt werden sollen. Dies bedeutet implizit, dass HardwareNetwork-Analyser nicht erkannt werden können.
2.2. Anforderungen an das zu entwickelnde Tool
Primär soll das Tool, welches wir liebevoll S NIFF A ND D IE genannt haben, unter L INUX laufen.
Jedoch soll die Portabilität mit anderen U NIX-Derivaten nicht absichtlich, durch Einsatz von
L INUX-Spezialitäten, verletzt werden.
Features
• Gegebenes Framework
• Erweiterbarkeit durch Plugins
• Multi-Threading
• Konfiguration mittels einer Konfigurationsdatei
5
2.3. Projektplan
2.3. Projektplan
Die Verteilung der Aufgaben und der genaue Ablauf der verrichteten Arbeiten, ist aus dem Projektplan im Anhang A ersichtlich.
2.4. Dokumentation
Die vorliegende Arbeit lässt sich in vier Bereiche aufteilen. Der erste Teil führt in das verwendete Vokabular ein. Begriffe im Zusammenhang mit Sniffern und Network-Analysern und deren
Funktionsweisen werden eingeführt.
Im zweiten Teil werden dem Leser dann die Schwächen der Ethernet- und TCP/IP-Implementierung gezeigt. Des Weiteren werden Methoden gezeigt, wie man den Lauscher dazu bringt,
sich zu verraten. Es wird erklärt, wie es dem Administrator damit möglich sein sollte, Sniffer zu
detektieren.
Der dritte Teil ist dem von uns entwickelten Tool SAD gewidmet. Der Leser lernt die Konzepte
hinter SAD und deren Umsetzung kennen. Des Weiteren erfährt er, wie man selber Erweiterungen, in Form von Plugins, schreiben kann.
Der vierte und letzte Teil fasst unsere Resultate zusammen. Es werden gängige Betriebssysteme
ausgewertet und an ihnen die Funktionsweise von SAD gezeigt.
6
3. Was sind Sniffer?
Microsoft isn’t evil, they just
make really crappy operating
systems.
(Linus Torvalds)
Die Sicherheit eines lokalen Netzwerkes verdient immer grössere Beachtung. Plain-Text Daten
wie zum Beispiel Passwörter oder private E-Mails, können abgehört werden. Ein solches Mithören nennt man auch sniffen (engl. “to sniff” für riechen, schnüffeln).
Es gibt einige, darunter auch freie Software, die den Datenverkehr eines Netzwerks empfangen
und darstellen können. Da der ganze Datenverkehr aus einem binär codierten Strom besteht,
sind Sniffer meistens mit einem Protokoll-Analyser ausgestattet, der die empfangenen Daten in
eine für Menschen lesbare Form darstellt.
3.1. Einsatz
• Diagnose von Netzwerkproblemen
• Eindringungsversuche entdecken
• Networktraffic-Analyse und Filterung nach verdächtigem Inhalt
• Datenspionage
7
4. Wie funktioniert ein Sniffer?
4.1. shared und microsegmentiertes LAN
Sniffer können in CSMA/CD und geswitchten Netzwerken arbeiten. In einem shared LAN hängen alle Geräte am gleichen Bus. Pakete, die an eine Maschine gesendet werden, können von
allen anderen Rechnern im gleichen Segment abgehört werden.
Abbildung 4.1.: Ethernet-Frames in einem shared LAN
In einem geswitchten Netzwerk sieht dies anders aus. Der Switch, ein intelligentes Netzwerkgerät, merkt sich die Zuordnung MAC-Adresse↔Port. So werden Pakete nur dem dafür zuständigen Host gesendet und nicht wie oben gebroadcastet.
Falls eine unbekannte MAC-Adresse auftritt, wird das Paket an alle Ports geflutet → shared
LAN Verhalten.
Eine andere Methode, um gezielt einen Host auszuschnüffeln, bietet das so genannte ARP poisoning.
4.2. promiscuous mode
Ein Sniffer kennt zwei verschiedene Modi:
• non-promiscuous mode: Es werden ankommende und abgehende Daten des eigenen Computers gesnifft.
8
4.3. Implementation in L INUX?
• promiscuous mode: Es wird der gesamte Datenverkehr gesammelt. Es werden also nicht
nur die an ihn adressierten Frames empfangen, sondern auch die nicht an ihn adressierten.
Im non-promiscuous mode werden folgende Frames nicht verworfen:
• Ziel-MAC-Adresse entspricht der Hardware-Adresse der Netzwerkkarte.
• Ziel-MAC-Adresse entspricht der Broadcast-Adresse
• Ziel-MAC-Adresse entspricht einer Multicast-Adresse
Im promiscuous mode werden keine Frames hardwaremässig verworfen.
Abbildung 4.2.: promiscuous mode
4.3. Implementation in L INUX?
Wie man einen einfachen Sniffer unter L INUX implementieren kann, wird im Anhang B erläutert.
Es gibt noch eine wichtige Eigenschaft, die es zu erklären lohnt. Falls auf dem Netzwerk sehr
viele Daten auftreten, kann es soweit kommen, dass der Kernel beginnt Pakete zu verwerfen, da
er nicht alle verarbeiten kann.
Die Lösung für dieses Problem ist, möglichst früh in der Paket-Prozess-Kette einen Filter einzubauen. Der L INUX Kernel erlaubt es einen Filter namens LPF direkt in die Protokoll-ProzessRoutinen einzubauen.
9
4.3. Implementation in L INUX?
Abbildung 4.3.: Paket-Prozess-Kette
10
Teil II.
Theorie: Sniffer Erkennung
Zusammenfassung
Nebst der Funktionsweise der einzelnen Methoden wird in diesem Teil die nötige Theorie für
das Verständnis von SAD vermittelt. Der Leser sollte danach in der Lage sein, die bei SAD angewandten Tricks zu verstehen.
Überblick
In der Theorie ist es unmöglich einen Sniffer zu detektieren, weil ein Sniffer ein rein “passives”
Gerät ist.
Dies ist aber so nicht ganz richtig. Natürlich gibt es Hardware-Protokoll-Analyser, die nur Daten
sammeln, oder man kann einfach die Tx-Leitungen durchschneiden!
Da die meisten Sniffer aber auf Rechnern laufen, die einen eigenen IP-Stack besitzen, gibt es ein
paar Ansätze, die dazu dienen, herauszufinden, ob sich eine solche Maschine im promiscuous
mode befindet.
Diese Möglichkeiten lassen sich in folgende Kategorien aufteilen:
Networkstack Es werden gezielt Schwächen des Networkstacks spezifischer Betriebssysteme
ausgenutzt.
Zur Auswertung sind vor allem Protokolle geeignet, die Antworten erzeugen, wie zum
Beispiel ARP oder ICMP.
DNS Reverse Lookups Um eine bessere Lesbarkeit der gesammelten Informationen zu erreichen, bieten viele Sniffer die Möglichkeit die IP-Adressen in Domainnamen umzusetzen. Um dies jedoch zu ermöglichen, muss der Sniffer agieren und DNS Namensauflösungen bewerkstelligen.
Latenzzeiten und Packetdropping Ein Sniffer ist gezwungen die gesammelten Daten zu
parsen und zu analysieren, was zwangsläufig Rechenleistung benötigt. Wenn ein Rechner
zu viel Zeit verbraucht mit Filtern, kann es auch sein, dass er anfängt, Pakete zu verwerfen.
Weitere Methoden Zum Schluss gibt es noch weitere Ansätze, wie z.B. das Aufspüren lokaler Sniffer.
13
5. Networkstack Tests
Kluge Leute lernen auch von
ihren Feinden.
(Aristoteles)
Sniffer arbeiten so, dass sie alle Pakete, die über das Netzwerk transferiert werden, mithören
können. Um dies zu erreichen, muss die Netzwerkkarte in den promiscuous mode geschaltet
werden.
Somit werden alle Pakete “blind” akzeptiert und zum Kernel weitergeleitet. Der Networkstack1
muss je nach Protokoll gewisse Funktionen erledigen, wie zum Beispiel auf einen ICMP Request
einen Reply senden. Der Kernel kann nun einige Fehler machen, indem er zum Beispiel auf
Anfragen antwortet, die nicht für ihn bestimmt sind.
5.1. Grundlagen
5.1.1. Hardware-Filter
Jede Ethernet Netzwerkkarte wird durch eine so genannte, sechs Byte lange, MAC-Adresse
repräsentiert. Jede Netzwerkkarte besitzt ein Satz von Filtern, die es benutzt um verschieden
Arten von Paketen zu bearbeiten:
Unicast Alle Pakete, welche als Ziel-Adresse die MAC der Karte eingetragen haben.
Broadcast Alle Pakete, welche als Ziel-Adresse FF:FF:FF:FF:FF:FF haben.
Multicast Alle Pakete, welche an eine speziell konfigurierte Multicast-Adresse gesendet werden. Diese Adressen müssen in der Multicast Liste der Netzwerkkarte registriert werden.
Beispiele:
01:00:5E:00:00:00 Multicast-Adresse 0 Weder benutzt noch registriert auf der Netzwerkkarte.
01:00:5E:00:00:01 Multicast-Adresse 1 Adresse, mit der jeder Host in einem LAN
adressiert werden kann. Falls die Netzwerkkarte Multicast unterstützt, sollte diese
Adresse in der Liste eingetragen sein.
All Multicast Alle Pakete, welche das group bit2 gesetzt haben. Beispiel: 01:00:00:00:00:00
Promiscuous Alle Pakete. Die Ziel-Adresse wird nicht überprüft.
1
2
siehe Anhang C
erstes Byte ungerade
14
5.1. Grundlagen
5.1.2. Software-Filter
Der Software-Filter ist abhängig vom Kernel des jeweiligen Betriebssystems. Die Hauptaufgabe
dieses Filters besteht darin herauszufinden, für wen das Paket bestimmt war und dieses für den
Kernel richtig Kennzuzeichnen.
So soll vermieden werden, dass auf gesniffte Pakete so reagiert wird, wie wenn es ein Paket für
den Host wäre.
L INUX
Um genaueres zu Erfahren kann im Anhang ?? nachgeschaut werden. Trotzdem einige Erläuterungen, wie der L INUX Software-Filter aufgebaut ist.
L INUX klassifiziert Pakete in folgende 4 Typen:
• TO_US Pakete: Ziel-Adresse ist unsere MAC-Adresse.
• BROADCAST Pakete: Ziel-Adresse = FF:FF:FF:FF:FF:FF.
• MULTICAST Pakete: Das group bit ist gesetzt.
• OTHERHOST Pakete: Alle Anderen.
Abbildung 5.1.: Der L INUX Software-Filter
Networkstack Routinen wie zum Beispiel arp_rcv() oder ip_rcv() prüfen nun einfach,
ob der Pakettyp OTHERHOST ist. Falls nein, wird bei Bedarf eine Antwort generiert.
Eine Frage, die sich stellt, lautet: Warum behandelt L INUX Adressen, bei denen das group bit
gesetzt ist automatisch als Multicast-Adresse?
Diese Behandlung ist kein Fehler, denn 01:00:5E:xx:xx:xx Adressen sind IP-Multicast-Adressen,
aber die MAC-Adresse wird auch von anderen Protokollen in höheren Layern benutzt.
15
5.1. Grundlagen
W INDOWS
Da der M$ W INDOWS Quellcode offiziell nicht zugänglich ist, ist es schwer, den Software-Filter
zu analysieren. Es bleibt nicht viel übrig als mit diversen Tests den Mechanismus zu erraten.
Siehe Abschnitt 5.1.3.
5.1.3. Reaktionen
Legende
— Abweisung des Pakets
→ Weiterleiten des Pakets
Antwort generieren
Nutzbare, falsche Antwort
16
gr.bit
our MAC
other MAC
Broadcast
(FF:FF:FF:FF:FF:FF)
Fake Broadcast
(FF:FF:FF:FF:FF:FE)
Fake 16 Broadcast
(FF:FF:00:00:00:00)
Fake 8 Broadcast
(FF:00:00:00:00:00)
MCast not in List
(01:00:5E:00:00:00)
MCast in List
(01:00:5E:00:00:01)
Group Bit set
(01:00:00:00:00:00)
off
W INDOWS XP
normal
promisc
hw sw res hw sw res
→ → → →
—
→ —
L INUX 2.6
normal
promisc
hw sw res hw sw res
→ → → →
—
→ —
O PEN BSD
normal
promisc
hw sw res hw sw res
→ → → →
—
→ —
→
→
→
→
→
—
→
→
—
→
→
—
→
—
→
→
→
—
→
→
—
→
→
—
—
→
→
—
—
→
→
→
—
on
on
→
—
→
→
—
→
→
→
→
—
→
→
—
→
→
→
—
→
→
→
→
—
→
→
→
→
→
→
→
→
→
—
→
→
Tabelle 5.1.: Reaktionen auf ARP-Scans
→
→
5.2. ARP-Test
5.2. ARP-Test
In diesem Abschnitt wird die Funktionsweise von ARP erklärt. Sollten Sie mit ARP vertraut
sein, können Sie getrost den Abschnitt 5.2.1 überspringen.
Danach wird kurz darauf eingegangen, um was es beim ARP-Test geht und welche Ansätze
existieren.
5.2.1. Das Address Resolution Protocol
Das Address Resolution Protocol wird für die dynamische3 Zuordnung zwischen einer 32-BitIP-Adresse und einer 48-Bit-MAC-Adresse verwendet. Die Arbeitsweise von ARP wird anhand
folgenden Beispiels gezeigt.
Jedes Mal, wenn ein Befehl der Form
$ f t p k e r m i t . zhwin . ch
eingegeben wird, werden die folgenden Schritte ausgeführt. Diese nummerierten Schritte sind
in Abbildung 5.2 dargestellt.
1. Die Anwendung (der FTP Client) verwendet die Funktion gethostbyname(3), um
den Hostnamen in eine 32-Bit-IP-Adresse umzuwandeln.
2. Der FTP Client fordert sein TCP auf, eine Verbindung zu dieser IP-Adresse aufzubauen.
3. TCP sendet einen Teil einer Verbindungsanfrage zum Remote-Host in der Form eines
IP-Datagramms zu dessen IP-Adresse.
4. Befindet sich der Ziel-Host in einem lokal angeschlossenen Netzwerk, kann das IP-Datagramm
direkt zu diesem Host gesendet werden. Sollte sich der Ziel-Host jedoch in einem entfernten Netzwerk befinden, ermittelt die IP-Routing-Funktion die Internetadresse eines im
lokalen Netzwerk angeschlossenen Routers und stellt diesem das IP-Datagramm zu. In
beiden Fällen wird also das IP-Datagramm zu einem Host oder Router im lokalen Netzwerk gesendet.
5. In einem Ethernet muss der sendende Host die 32-Bit-IP-Adresse in eine 48-Bit-EthernetAdresse umwandeln. Eine Übersetzung einer logischen Internet-Adresse in die entsprechende physikalische Hardware-Adresse ist also erforderlich. Dies ist die Funktion von
ARP.
6. ARP sendet ein bestimmtes Ethernet-Frame, genannt ARP Request, an alle Host im Netzwerk4 . In Abbildung 5.2 sind die Broadcasts durch gepunktete Linien dargestellt. Der
ARP Request beinhaltet die IP-Adresse des Ziel-Hosts sowie die Anforderung “Falls Sie
Besitzer dieser IP-Adresse sind, geben Sie mir bitte Ihre Hardware-Adresse zurück”.
3
Wir verwenden den Begriff dynamisch, da dieser Vorgang automatisch abläuft und normalerweise keine Aufgabe
für den Anwender oder Systemadministrator ist.
4
Dieses Prinzip wird Broadcasting genannt.
18
5.2. ARP-Test
7. Der ARP-Layer des Ziel-Hosts empfängt diesen Broadcast, erkennt, dass der Absender
nach der entsprechenden Hardware-Adresse fragt, und antwortet mit einem ARP Reply,
welcher die IP-Adresse und die entsprechende Hardware-Adresse des Ziel-Hosts beinhaltet.
8. Der ARP Reply wird empfangen und das IP-Datagramm, welches den ARP Request/Reply
ausgelöst hat, kann nun gesendet werden.
9. Das IP-Datagramm wird zum Ziel-Host gesendet.
Abbildung 5.2.: Die Arbeitsweise von ARP
19
5.2. ARP-Test
Format eines ARP-Pakets
Abbildung 5.3 zeigt das Format einer ARP Request/Reply-Nachricht im Zusammenspiel mit
Ethernet.
Abbildung 5.3.: ARP-Paket
Um die einzelnen Felder besser zu verstehen, schauen wir uns einen ARP Request/Reply an.
# a r p −d 1 6 0 . 8 5 . 1 6 3 . 7 4
$ ping 160.85.163.74
Mit arp -d 160.85.163.74 versichern wir uns, dass der ARP-Cache gelöscht ist.
Aus dem Ethernet-Frame ist ersichtlich, dass der ARP Request an die Broadcast-Adresse geschickt wird.
Im ARP-Paket trägt der Sender seine MAC- und IP-Adresse ein. Als Ziel-MAC trägt er lauter
Nullen ein, da diese noch nicht bekannt ist. Das Feld Opcode zeigt an, dass es ein Request ist.
E t h e r n e t II , Src : 0 0 : 0 6 : 1 b : ca : ea : 2 3 , Dst : f f : f f : f f : f f : f f : f f
Destination : ff : ff : ff : ff : ff : ff ( Broadcast )
Source : 0 0 : 0 6 : 1 b : ca : ea :23 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
Type : ARP ( 0 x0806 )
Address R e s o l u t i o n P r o t o c o l ( r e q u e s t )
Hardware t y p e : E t h e r n e t ( 0 x0001 )
P r o t o c o l t y p e : I P ( 0 x0800 )
Hardware s i z e : 6
Protocol size : 4
Opcode : r e q u e s t ( 0 x0001 )
S e n d e r MAC a d d r e s s : 0 0 : 0 6 : 1 b : c a : e a : 2 3 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
Sender IP a d d r e s s : 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
T a r g e t MAC a d d r e s s : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 : 0 0 ( 0 0 : 0 0 : 0 0 _00 : 0 0 : 0 0 )
T a r g e t IP a d d r e s s : 1 6 0 . 8 5 . 1 6 3 . 7 4 ( 1 6 0 . 8 5 . 1 6 3 . 7 4 )
Listing 5.1: ARP Request
Der ARP Reply geht nicht mehr als Broadcast auf die Leitung. Er ist direkt an den Absender
gerichtet. Es sind alle Felder des ARP-Pakets ausgefüllt. Man beachte, dass das Feld Opcode
nun auf Reply gesetzt ist.
E t h e r n e t I I , S r c : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5 , D s t : 0 0 : 0 6 : 1 b : c a : e a : 2 3
D e s t i n a t i o n : 0 0 : 0 6 : 1 b : ca : ea :23 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
20
5.2. ARP-Test
S o u r c e : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5 ( 1 6 0 . 8 5 . 1 6 3 . 7 4 )
Type : ARP ( 0 x0806 )
Address R e s o l u t i o n P r o t o c o l ( r e p l y )
Hardware t y p e : E t h e r n e t ( 0 x0001 )
P r o t o c o l t y p e : I P ( 0 x0800 )
Hardware s i z e : 6
Protocol size : 4
Opcode : r e p l y ( 0 x0002 )
S e n d e r MAC a d d r e s s : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5 ( 1 6 0 . 8 5 . 1 6 3 . 7 4 )
Sender IP a d d r e s s : 1 6 0 . 8 5 . 1 6 3 . 7 4 ( 1 6 0 . 8 5 . 1 6 3 . 7 4 )
T a r g e t MAC a d d r e s s : 0 0 : 0 6 : 1 b : c a : e a : 2 3 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
T a r g e t IP a d d r e s s : 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
Listing 5.2: ARP Reply
5.2.2. Methode
Die einfachste Variante der ARP-Detektion ist die, dass man einen ARP Request an eine fake
Broadcast-Adresse sendet. Wenn der Rechner mit dem ARP Reply antwortet, so befindet sich
dieser Rechner wahrscheinlich im promiscuous mode.
Abbildung 5.4.: ARP-Detektion
5.2.3. Erweiterungen
Eine Variation der klassischen ARP-Detektion macht sich den ARP-Cache zu nutzen. Ein
$ / u s r / s b i n / a r p −a
s t d m e i e r m i 1 2 . zhwin . ch ( 1 6 0 . 8 5 . 1 7 9 . 1 6 9 ) \
a u f 0 0 : A0 : C9 : B4 : 0 B : A5 [ e t h e r ] a u f e t h 0
21
5.3. ICMP-Test
s t d r e u s s h a l . zhwin . ch ( 1 6 0 . 8 5 . 1 6 3 . 7 4 ) \
a u f 0 0 : 0 2 : A5 : 9 9 : 4 2 : 0 5 [ e t h e r ] a u f e t h 0
edugw . zhwin . ch ( 1 6 0 . 8 5 . 1 6 0 . 1 ) \
a u f 0 0 : D0 : 0 3 : 2 2 : 7 C : 0A [ e t h e r ] a u f e t h 0
zeigt den lokalen ARP-Cache an. Jeder Eintrag beinhaltet alle nötigen Einträge, um ein Paket an
den Ziel-Host zu senden.
Nun kann man einen non-broadcast ARP Request senden. Danach macht man einen broadcast
Ping. Jeder der antwortet, ohne zuvor einen ARP Request an uns gestellt zu haben, muss die
MAC-Adresse aus einem gesnifften ARP Request haben.
5.2.4. Voraussetzungen
• Funktioniert im shared und switched LAN. Der Switch leitet unbekannte MAC-Adressen
an alle Ports weiter.
• Die zu testende Maschine muss einen IP-Stack mit Schwächen im Software-Filter besitzen.
5.2.5. Evaluation
Dieser Test bietet eine hohe Trefferquote und ist einfach zu implementieren.
5.3. ICMP-Test
In diesem Abschnitt werden kurz ICMP Requests besprochen. Der Ansatz besteht darin ICMP
Anfragen, mit einer falschen MAC-Adresse, an die richtige IP-Adresse zu senden.
5.3.1. Internet Control Message Protocol Echo-Request & Echo-Reply
ICMP-Nachrichten werden in der Regel entweder von der IP-Schicht oder einem Protokoll einer
höheren Schicht (TCP oder UDP) beachtet.
Das Prinzip eines ICMP Request’s & Reply’s ist, dass ein Host einem anderen Host eine Anfrage
schickt um zu antworten. Eine Anfrage wird meistens von einem Userprogramm namens PING
erstellt, die Antwort beim Ziel-Host wird in den meisten TCP/IP-Implementationen vom Kernel
gehandhabt.
22
5.3. ICMP-Test
Abbildung 5.5.: Aufbau eines ICMP Request/Reply Paketes
Die beiden Felder Typ und Code identifizieren das ICMP-Paket entweder als Request (8/0)
oder als Reply (0/0). Das Feld Kennung enthält eine eindeutige ID. Unter U NIX ist es die
Prozess-ID des aufrufenden Ping Programmes5 . Die Sequenznummer wird für jede einzelne
Anfrage inkrementiert. Zusammenhängende Request’s und Reply’s haben dieselbe Sequenznummer.
Um das Ganze besser zu verstehen, folgt ein Mitschnitt eines ICMP Request’s & Reply’s:
$ p i n g s t d v e s e l r a n . zwhin . ch
E t h e r n e t I I , S r c : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5 , D s t : 0 0 : 0 6 : 1 b : c a : e a : 2 3
I n t e r n e t P r o t o c o l , S r c Addr : s t d r e u s s h a l . zhwin . ch ( 1 6 0 . 8 5 . 1 6 3 . 7 4 ) ,
D s t Addr : s t d v e s e l r a n . zhwin . ch ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
I n t e r n e t C o n t r o l Message P r o t o c o l
Type : 8 ( Echo ( p i n g ) r e q u e s t )
Code : 0
Checksum : 0 xa8b3 ( c o r r e c t )
I d e n t i f i e r : 0 xa908
S e q u e n c e number : 0 x0001
Data (56 b y t e s )
Listing 5.3: Echo Request
E t h e r n e t I I , S r c : 0 0 : 0 6 : 1 b : c a : e a : 2 3 , D s t : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5
I n t e r n e t P r o t o c o l , S r c Addr : s t d v e s e l r a n . zhwin . ch ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ) ,
D s t Addr : s t d r e u s s h a l . zhwin . ch ( 1 6 0 . 8 5 . 1 6 3 . 7 4 )
I n t e r n e t C o n t r o l Message P r o t o c o l
Type : 0 ( Echo ( p i n g ) r e p l y )
Code : 0
Checksum : 0 xb0b3 ( c o r r e c t )
I d e n t i f i e r : 0 xa908
S e q u e n c e number : 0 x0001
Data (56 b y t e s )
Listing 5.4: Echo Reply
5
Man beachte die Networkorder
23
5.3. ICMP-Test
5.3.2. Methode
Das Prinzip ist sehr einfach: Es wird ein ICMP Request an den zu testenden Host gesendet. Man
verändert nun das Paket aber so, dass zwar die richtige Ziel-IP-Adresse aber eine fake Broadcast
als Ziel-MAC-Adresse übertragen wird.
Abbildung 5.6.: ICMP-Test
Falls nun ein ICMP Reply vom zu testenden Host zurückkommt, wurde der Hardware-Filter
nicht angewandt, das heisst, er muss seine Netzwerkkarte in den promiscuous mode geschaltet
haben.
Erweiterungen
Dieser Test kann mit einer Vielzahl von Nachrichten der ICMP-Reihe, die Antworten generieren,
realisiert werden.
Natürlich kann auch ein beliebiges anderes Protokoll verwendet werden, das Antworten erzeugt,
wie zum Beispiel der Echo- oder TCP-Dienste, falls zum Beispiel ICMP Request’s von einer
Firewall geblockt werden.
5.3.3. Voraussetzungen
• Funktioniert in shared und switched LAN. Der Switch leitet unbekannte MAC-Adressen
an alle Ports weiter.
• Die zu testende Maschine muss einen IP-Stack mit Schwächen im Software-Filter besitzen.
• Es darf kein Filter aktiviert sein, der überprüft, ob Ziel-MAC-Adresse und Ziel-IP-Adresse
ein gültiges Paar bilden.
24
5.4. Source Route
5.3.4. Evaluation
Dieser Test hat nicht eine ganz so hohe Trefferquote wie der ARP-Test, ist aber als Ergänzung
sehr gut geeignet, weshalb er auch implementiert wird.
5.4. Source Route
Dieser Abschnitt bietet einen Überblick über die IP-Option source routing. Der Ansatz ist in
etwa wie folgt gedacht: ICMP-Anfragen mit der loose source route Option ausstatten. So kann
man eine Umleitung über einen anderen Host im gleichen Segment erzwingen. Dieser Host muss
das Routing deaktiviert haben, falls nun doch eine ICMP-Antwort zurückkommt, befindet sich
der angefragte Host höchstwahrscheinlich im promiscuous mode.
5.4.1. Source Routing
Normal ist IP-Routing dynamisch, wobei jeder Router den nächsten Pfad selbst auswählt. Applikationen haben keinen Einfluss auf die Wegwahl.
Die Idee hinter source routing ist, dass der Sender die Route spezifizieren kann. Es werden
folgende zwei Varianten unterstützt:
• strict source souting: Der Sender spezifiziert den genauen Pfad, dem das IP-Datagramm
folgen muss.
• loose source routing: Der Sender spezifiziert einen Pfad, den das IP-Datagramm traversieren muss. Das Paket kann aber auch über beliebige Zwischenstationen gehen.
source routing ist eine Option des IP-Protokolls.
Abbildung 5.7.: Format der source route Option im IP-Header
Der Code ist 0x83 für loose source routing und 0x89 für strict source routing. Das Len Feld
enthält die Anzahl Bytes des source routing Optionsfeldes. Ptr bedeutet Pointer. Dies ist ein
Index, welcher auf die nächste IP-Adresse zeigt. In der Grafik 5.7 sieht man, welche Werte der
Pointer annehmen kann.
Die nächste Figur 5.8 zeigt, wie sich die Ziel-Adresse und das source routing Optionsfeld ändert.
# weist auf die aktuelle Zeigerposition hin.
25
5.4. Source Route
Abbildung 5.8.: Ablauf source routing
Um das Ganze besser zu verstehen, folgt ein Mitschnitt eines source routed ICMP Request’s:
$ . / s r c r o u t e _ p i n g edugw . zhwin . ch m a i l . zhwin . ch
E t h e r n e t I I , S r c : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5 , D s t : 0 0 : a0 : c5 : 4 e : 9 5 : c f
I n t e r n e t P r o t o c o l , S r c Addr : s t d r e u s s h a l . zhwin . ch ( 1 6 0 . 8 5 . 1 6 3 . 7 4 ) ,
D s t Addr : edugw . zhwin . ch ( 1 6 0 . 8 5 . 1 6 0 . 1 )
Version : 4
H e a d e r l e n g t h : 28 b y t e s
D i f f e r e n t i a t e d S e r v i c e s F i e l d : 0 x00 ( DSCP 0 x00 : D e f a u l t ; ECN : 0 x00 )
T o t a l L e n g t h : 36
I d e n t i f i c a t i o n : 0 x0042 ( 6 6 )
F l a g s : 0 x00
Fragment o f f s e t : 0
Time t o l i v e : 64
P r o t o c o l : ICMP ( 0 x01 )
H e a d e r checksum : 0 x 0 3 f 2 ( c o r r e c t )
S o u r c e : s t d r e u s s h a l . zhwin . ch ( 1 6 0 . 8 5 . 1 6 3 . 7 4 )
D e s t i n a t i o n : dove . zhwin . ch ( 1 6 0 . 8 5 . 1 9 6 . 1 5 )
Options : (12 bytes )
NOP
Loose s o u r c e r o u t e ( 1 1 b y t e s )
Pointer : 4
edugw . zhwin . ch ( 1 6 0 . 8 5 . 1 6 0 . 1 ) <− ( c u r r e n t )
dove . zhwin . ch ( 1 6 0 . 8 5 . 1 9 6 . 1 5 )
I n t e r n e t C o n t r o l Message P r o t o c o l
Listing 5.5: source routing
5.4.2. Methode
Der Trick bei dieser Methode ist, ein source routed Paket über einen Rechner im gleichen Segment zu versenden, der das Routing deaktiviert hat und somit das Paket verwirft.
26
5.4. Source Route
Abbildung 5.9.: source routing Methode
Falls nun der Sniffer das Paket liest, schickt er eine Antwort zurück.
Erweiterungen
Um ganz sicher zu gehen, dass der Rechner, über den geroutet werden soll das Paket auch
verworfen hat, kann man noch das TTL-Feld überprüfen. Falls das Paket mit einem um eins
oder mehr dekrementierten TTL-Feld zurückkommt, wurde es geroutet und wurde somit auf
“normale” Weise beantwortet. Ist das TTL-Feld allerdings unverändert, deutet dies darauf hin,
das sich das Ziel im promiscuous mode befindet.
Voraussetzungen
• Funktioniert nur im shared LAN.
• Es muss ein dritter Host vorhanden sein, der IP-Routing deaktiviert hat.
• Der zu untersuchende Host darf source routed Pakete nicht verwerfen.
Evaluation
Die meisten Rechner ignorieren source routed Pakete, deswegen ist die Chance bei dieser Methode positive Resultate zu erzielen sehr gering. Unter L INUX lässt sich leicht feststellen, ob
source routed Pakete akzeptiert werden:
# cat / proc / sys / net / ipv4 / conf / a l l / a c c e p t _ s o u r c e _ r o u t e
0
27
6. DNS Test
Manche Sniffer, lösen IP-Adressen in Domainnamen auf, um die gesammelten Daten besser
darzustellen. Um dies zu erledigen, muss der Sniffer selbst aktiv werden.
6.1. Das Domain Name System
Das Domain Name System ist eine verteilte Datenbank, die von TCP/IP-Applikationen benutzt
wird, um Hostnamen und IP-Adressen aufzulösen und Informationen für die Zustellung von EMails bereitzustellen.
Da auch eine kurze Einführung den Rahmen diese Arbeit sprengen würde, begrenzen wir uns
auf einzelne Pakete, welche für die Detektion von Sniffern nötig sind und erklären diese hier.
Wir wollen uns die Namensauflösung anhand folgenden Beispiels anschauen.
$ p i n g m u s t a n g . zhwin . ch
Zuerst wird eine Anfrage in folgender Form an den DNS-Server gesendet.
E t h e r n e t I I , S r c : 0 0 : 0 6 : 1 b : c a : e a : 2 3 , D s t : 0 0 : d0 : 0 3 : 2 2 : 7 c : 0 a
I n t e r n e t P r o t o c o l , S r c Addr : 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ) ,
D s t Addr : 1 6 0 . 8 5 . 1 9 5 . 1 9 5 ( 1 6 0 . 8 5 . 1 9 5 . 1 9 5 )
U s e r Datagram P r o t o c o l , S r c P o r t : 32770 ( 3 2 7 7 0 ) , D s t P o r t : domain ( 5 3 )
Domain Name System ( q u e r y )
T r a n s a c t i o n ID : 0 x e 4 c c
F l a g s : 0 x0100 ( S t a n d a r d q u e r y )
Questions : 1
Answer RRs : 0
A u t h o r i t y RRs : 0
A d d i t i o n a l RRs : 0
Queries
m u s t a n g . zhwin . ch : t y p e A, c l a s s i n e t
Listing 6.1: DNS-Query
Die Antwort des DNS-Servers sieht folgendermassen aus:
E t h e r n e t I I , S r c : 0 0 : 3 0 : 4 8 : 5 1 : 4 9 : bf , D s t : 0 0 : 0 6 : 1 b : c a : e a : 2 3
I n t e r n e t P r o t o c o l , S r c Addr : 1 6 0 . 8 5 . 1 9 5 . 1 9 5 ( 1 6 0 . 8 5 . 1 9 5 . 1 9 5 ) ,
D s t Addr : 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
U s e r Datagram P r o t o c o l , S r c P o r t : domain ( 5 3 ) , D s t P o r t : 32770 ( 3 2 7 7 0 )
Domain Name System ( r e s p o n s e )
28
6.1. Das Domain Name System
T r a n s a c t i o n ID : 0 xc55b
F l a g s : 0 x8580 ( S t a n d a r d q u e r y r e s p o n s e , No e r r o r )
Questions : 1
Answer RRs : 1
A u t h o r i t y RRs : 3
A d d i t i o n a l RRs : 5
Queries
m u s t a n g . zhwin . ch : t y p e A, c l a s s i n e t
Answers
m u s t a n g . zhwin . ch : t y p e A, c l a s s i n e t , a d d r 1 6 0 . 8 5 . 1 9 2 . 3 0
A u t h o r i t a t i v e nameservers
Additional records
Listing 6.2: DNS-Response
Das DNS wird auch für die Umsetzung von IP-Adressen zu Namen verwendet. Dies nennt man
Reverse-DNS-Lookup. Schauen wir uns nun folgendes Beispiel an:
$ host 160.85.192.30
Die Query an den DNS-Server hat folgende Form:
E t h e r n e t I I , S r c : 0 0 : 0 6 : 1 b : c a : e a : 2 3 , D s t : 0 0 : d0 : 0 3 : 2 2 : 7 c : 0 a
I n t e r n e t P r o t o c o l , S r c Addr : 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ) ,
D s t Addr : 1 6 0 . 8 5 . 1 9 5 . 1 9 5 ( 1 6 0 . 8 5 . 1 9 5 . 1 9 5 )
U s e r Datagram P r o t o c o l , S r c P o r t : 32770 ( 3 2 7 7 0 ) , D s t P o r t : domain ( 5 3 )
Domain Name System ( q u e r y )
T r a n s a c t i o n ID : 0 x c f 9 8
F l a g s : 0 x0100 ( S t a n d a r d q u e r y )
Questions : 1
Answer RRs : 0
A u t h o r i t y RRs : 0
A d d i t i o n a l RRs : 0
Queries
3 0 . 1 9 2 . 8 5 . 1 6 0 . i n −a d d r . a r p a : t y p e PTR , c l a s s i n e t
Listing 6.3: Reverse-DNS-Query
Der DNS-Server liefert uns den dazugehörigen Namen mustang.zhwin.ch.
E t h e r n e t I I , S r c : 0 0 : 3 0 : 4 8 : 5 1 : 4 9 : bf , D s t : 0 0 : 0 6 : 1 b : c a : e a : 2 3
I n t e r n e t P r o t o c o l , S r c Addr : 1 6 0 . 8 5 . 1 9 5 . 1 9 5 ( 1 6 0 . 8 5 . 1 9 5 . 1 9 5 ) ,
D s t Addr : 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
U s e r Datagram P r o t o c o l , S r c P o r t : domain ( 5 3 ) , D s t P o r t : 32770 ( 3 2 7 7 0 )
Domain Name System ( r e s p o n s e )
T r a n s a c t i o n ID : 0 x c f 9 8
F l a g s : 0 x8580 ( S t a n d a r d q u e r y r e s p o n s e , No e r r o r )
Questions : 1
Answer RRs : 1
A u t h o r i t y RRs : 2
A d d i t i o n a l RRs : 2
Queries
3 0 . 1 9 2 . 8 5 . 1 6 0 . i n −a d d r . a r p a : t y p e PTR , c l a s s i n e t
29
6.2. Methode
Answers
3 0 . 1 9 2 . 8 5 . 1 6 0 . i n −a d d r . a r p a : t y p e PTR , c l a s s i n e t ,
m u s t a n g . zhwin . ch
A u t h o r i t a t i v e nameservers
Additional records
Listing 6.4: Reverse-DNS-Response
6.2. Methode
Einige Sniffer bieten die Möglichkeit des automatischen Reverse-DNS-Lookups an. Dadurch generiert der Sniffer jedoch zusätzlichen DNS-Traffic.
Der Administrator kann diese Eigenschaft wie folgt ausnutzen. Zuerst pingt er eine IP-Adresse
an. Danach versetzt er sich selbst in den promiscuous mode und snifft nach DNS-Queries.
Abbildung 6.1.: Der DNS-Test
Da der Sniffer die Namensauflösung On-the-Fly macht, generiert er eine DNS-Query. Der Administrator braucht nur die gesnifften Pakete nach dem Eintrag
Queries
9 9 . 1 . 1 6 8 . 1 9 2 . i n −a d d r . a r p a : t y p e PTR , c l a s s i n e t
zu durchsuchen. Der Rechner, der diese Anfrage generiert hat, ist im promiscuous mode.
30
6.3. Erweiterungen
6.3. Erweiterungen
Da viele Sniffer sich bereits aufgelöste Adressen merken, kann man den Test beliebig oft wiederholen indem man zufällige IP-Adressen anpingt.
6.4. Voraussetzungen
• Nur im shared LAN möglich.
• Plattform- und Betriebssystem unabhängig.
• Sniffer muss On-the-Fly DNS-Lookups machen.
• Es besteht die Möglichkeit, mit einem einzigen Test, das ganze Subnet nach Sniffern abzusuchen.
6.5. Evaluation
Der DNS-Test ist ein sehr zuverlässiger Indikator für einen Sniffer.
Die Implementation ist zwar nicht ganz ohne, aber dieser Test wird realisiert.
31
7. LATENCY-Tests
Der Machine-Latency Test ist ein der mächtigsten Detektionsmethoden. Damit besteht das Potenzial, Rechner im promiscuous mode, unabhängig des installierten Betriebssystems, zu detektieren. Diese Unabhängigkeit erkauft man sich mit zeitweiliger überhöhter Netzlast und einer
Menge von Evaluationen der Erfahrungswerte. Trotzdem werden hier einige Ansätze vorgestellt.
Der Hardware-Filter vergleicht von jedem ankommenden Paket die MAC-Adresse mit der eigenen Adresse. Stimmen die Adressen nicht überein, so wird das Paket verworfen. Diese Filterung
ist eine “billige” Operation, weil das System nur wenig belastet wird. Der Kernel wird nur belastet, wenn die MAC-Adressen übereinstimmen oder wenn es sich um einen Broad- oder Multicast
handelt.
Versetzt man nun die Netzwerkkarte in den promiscuous mode, so wird die ganze HardwareFilterung umgangen und es wird softwaremässig gefiltert. Jedes ankommende Paket wird per
Interrupt Service Routine an den Kernel weiter geleitet. Des Weiteren kommt hinzu, dass viele
Sniffer im User-Space arbeiten. Das bedeutet, dass bei jedem ankommenden Paket, ein ContextSwitch vom Kernel- in den User-Space stattfindet. Dies ist eine “teure” Operation.
In der Abbildung 4.3 ist die Filterung von L INUX ersichtlich.
7.1. ICMP-Time-Delta- & Ping-Drop-Test
Beim Time-Delta-Test geht es darum, Antwortzeiten in einem Netzwerk zu messen. Das Netzwerk muss sich dafür einmal in einem belasteten und einmal in einem unbelasteten Zustand
befinden.
7.1.1. Methode
Als Erstes misst man, am Besten über mehrere Versuche, den durchschnittlichen Round-TripDelay. Im nächsten Schritt flooded man einen zweiten Rechner im Netz mit einer möglichst
grossen Anzahl von Datenpaketen.
Falls der Host im promiscuous mode ist, versucht er alle Datenpakete zu filtern, was Verzögerungen verursacht. Wenn wir nun während des floodens nochmals eine Reihe von Zeitmessungen
untersuchen, sollten wir erhebliche Unterschiede feststellen. Auch kann es sein, dass Antworten
ganz ausfallen → dropping.
Zu beachten ist, dass das belastete Netz nicht ungeachtet an uns vorbeigeht. Unsere Pakete treten
auch verzögert ins Netz, vor allem wenn wir die Rolle des Verkehrsgenerators übernehmen.
32
7.1. ICMP-Time-Delta- & Ping-Drop-Test
Abbildung 7.1.: Time-Delta-Test
7.1.2. Erweiterungen
Für diesen Test gibt es eine ganze Reihe von Erweiterungen. Um möglichst weit nach oben im
Networkstack zu kommen, ist es sinnvoll zum Beispiel einen TCP 3-Way Handshake auszuführen. Viele offene Session zu erzeugen, kann auch einen “positiven” Seiteneffekt haben.
Falls der zu untersuchende Rechner sogar offene well known Ports, auf die man Abfragen stellen
kann, aufweist, hat dies zur Folge, dass sehr viel im User-Space behandelt werden muss.
7.1.3. Voraussetzungen
• Nur im shared LAN möglich.
• Das Netz muss für eine gewisse Zeit überbeansprucht werden können.
• Sehr viele Erfahrungswerte müssen gesammelt werden.
7.1.4. Evaluation
Dieser Test wird ganz sicher implementiert, auch wenn vordergründig erstmals ein paar Erfahrungswerte gesammelt werden müssen.
33
7.2. Timestamp-Request
7.2. Timestamp-Request
ICMP Timestamp-Request gibt einem System die Möglichkeit, die Uhrzeit von einem anderen
System abzufragen. Der empfohlene Rückgabewert ist eine Anzahl von Millisekunden nach Mitternacht Universal Time Coordinated (UTC).
7.2.1. ICMP-Timestamp-Request und -Reply
Abbildung 7.2 zeigt den Header einer ICMP-Timestamp-Request/-Reply Nachricht.
Abbildung 7.2.: ICMP Timestamp-Request/-Reply Nachricht
Das abfragende System trägt die lokale Zeit, bevor das Paket über die Leitung geht, in das Feld
Timestamp auslösen ein. Das antwortende System trägt einen Wert für Timestamp empfangen
ein, sobald die Anforderung eintrifft, und einen Wert für Timestamp senden ein, wenn die
Antwort gesendet wird. In der Praxis setzen die meisten Implementierungen allerdings die beiden letzten Felder gleich. Ursprünglich waren die drei Felder dafür gedacht, dass der Absender
festhalten kann, wann er die Anforderung gesendet hat, und unabhängig davon die Dauer bis zur
Übertragung der Antwort ermitteln kann.
E t h e r n e t II , Src : 0 0 : 0 6 : 1 b : ca : ea : 2 3 , Dst : 0 0 : 3 0 : 4 f : 1 6 : 4 f : 1 e
I n t e r n e t P r o t o c o l , S r c Addr : 1 9 2 . 1 6 8 . 1 . 3 3 ( 1 9 2 . 1 6 8 . 1 . 3 3 ) ,
D s t Addr : 1 9 2 . 1 6 8 . 1 . 2 ( 1 9 2 . 1 6 8 . 1 . 2 )
I n t e r n e t C o n t r o l Message P r o t o c o l
Type : 13 ( Timestamp r e q u e s t )
Code : 0
Checksum : 0 x78ed ( c o r r e c t )
I d e n t i f i e r : 0 x00f2
S e q u e n c e number : 0 x01a8
O r i g i n a t e t i m e s t a m p : 33387899
Receive timestamp : 0
Transmit timestamp : 0
Listing 7.1: ICMP Timestamp-Request
34
7.2. Timestamp-Request
E t h e r n e t II , Src : 0 0 : 3 0 : 4 f : 1 6 : 4 f : 1 e , Dst : 0 0 : 0 6 : 1 b : ca : ea :23
I n t e r n e t P r o t o c o l , S r c Addr : 1 9 2 . 1 6 8 . 1 . 2 ( 1 9 2 . 1 6 8 . 1 . 2 ) ,
D s t Addr : 1 9 2 . 1 6 8 . 1 . 3 3 ( 1 9 2 . 1 6 8 . 1 . 3 3 )
I n t e r n e t C o n t r o l Message P r o t o c o l
Type : 14 ( Timestamp r e p l y )
Code : 0
Checksum : 0 x8904 ( c o r r e c t )
I d e n t i f i e r : 0 x00f2
S e q u e n c e number : 0 x01a8
O r i g i n a t e t i m e s t a m p : 33387899
R e c e i v e t i m e s t a m p : 33387895
T r a n s m i t t i m e s t a m p : 33387895
Listing 7.2: ICMP Timestamp-Reply
Hier sieht man schön, dass das abfragende System um vier Millisekunden dem abgefragten System voraus ist.
Es gibt ein Detail, welches es zu beachten gilt. Ein System, welches die Zeit nicht standardkonform zurückgeben kann, muss das MSB setzen.
7.2.2. Methode
Der Administrator sendet nun über einen längeren Zeitraum ICMP Requests und misst dabei den
Round-Trip-Delay. Danach wird das Netz für kurze Zeit mit gefälschten Paketen geflutet und die
Messung des RTD wiederholt. Da der abhörende Rechner die riesige Datenflut softwaremässig
filtern muss, erhöht sich seine Reaktionszeit beträchtlich.
7.2.3. Erweiterungen
Uns sind keine Erweiterungen bekannt.
7.2.4. Voraussetzungen
• Funktioniert nur im shared LAN.
7.2.5. Evaluation
Durch Tests haben wir festgestellt, dass die Felder Timestamp empfangen und Timestamp senden
von den Betriebssystemen immer auf die gleichen Werte initialisiert werden. Dadurch ist diese
Methode für uns nicht brauchbar.
35
8. Weitere Methoden
Dieses Kapitel ist der vollständigkeitshalber aufgeführt. Die hier vorgestellten Methoden sind
nicht Teil dieser Diplomarbeit.
8.1. Host
Der Administrator kann mittels ifconfig den Status der Netzwerkschnittstellen überprüfen.
Dies setzt jedoch voraus, dass der Rechner nicht gehackt wurde und die Systemprogramme nicht
ersetzt wurden. Des Weiteren muss sichergestellt sein, dass keine Kernel-Module installiert sind,
welche die System-Calls abfangen und die Ausgabe von ifconfig verfälschen.
# i f c o n f i g −a
l o 0 : f l a g s =8049 <UP , LOOPBACK, RUNNING, MULTICAST> mtu 33224
i n e t 1 2 7 . 0 . 0 . 1 netmask 0 xff000000
i n e t 6 : : 1 p r e f i x l e n 128
i n e t 6 f e 8 0 : : 1 % l o 0 p r e f i x l e n 64 s c o p e i d 0 x6
x l 0 : f l a g s =8943 <UP , BROADCAST, RUNNING, PROMISC , SIMPLEX , MULTICAST> \
mtu 1500
a d d r e s s : 0 0 : 0 4 : 7 5 : c1 : 1 a : 7 3
media : E t h e r n e t a u t o s e l e c t ( 1 0 0 baseTX )
status : active
i n e t 6 f e 8 0 : : 2 0 4 : 7 5 f f : f e c 1 : 1 a73%x l 0 p r e f i x l e n 64 s c o p e i d 0 x1
i n e t 1 6 0 . 8 5 . 1 7 0 . 1 3 1 netmask 0 x f f f f e 0 0 0 b r o a d c a s t 1 6 0 . 8 5 . 1 9 1 . 2 5 5
x l 1 : f l a g s =8802 <BROADCAST, SIMPLEX , MULTICAST> mtu 1500
a d d r e s s : 0 0 : 0 4 : 7 5 : c1 : 0 b : d7
media : E t h e r n e t a u t o s e l e c t ( none )
s t a t u s : no c a r r i e r
p f l o g 0 : f l a g s =0<> mtu 33224
p f s y n c 0 : f l a g s =0<> mtu 2020
e n c 0 : f l a g s =0<> mtu 1536
Listing 8.1: O PEN BSD: ifconfig -a
Aus diesem Beispiel ist ersichtlich, dass sich das Interface xl0 im promiscuous mode befindet.
Arbeitet man auf einem L INUX Rechner, so muss man Folgendes machen:
$ dmesg | g r e p − i p r o m i s c u o u s
d e v i c e e t h 0 e n t e r e d p r o m i s c u o u s mode
d e v i c e e t h 0 l e f t p r o m i s c u o u s mode
Listing 8.2: L INUX: dmesg | grep -i promiscuous
36
8.2. Decoy
8.2. Decoy
Das Verb to decoy stammt aus dem Englischen und bedeutet ködern. Der Administrator legt
einen Köder, in Form eines Testrechners, auf dem der Telnet-Login aktiviert ist, aus. Telnet
hat die unangenehme Eigenschaft, dass der Username und das Passwort im Klartext gesendet
werden. Auf dem Testrechner ist nur dieser Account zum Schein aktiviert. Er wird permanent
geloggt. Der potenzielle Hacker snifft nun die Username/Passwort-Kombination und versucht
sich auf dem Server einzuloggen. Et voilà.
8.3. SNMP
So genannte Smart-Hubs bieten die Möglichkeit via SNMP überwacht zu werden, an. Es werden
Optionen wie
• Logging der Verbindungen. D. h., es werden alle MAC-Adressen mit dem dazugehörigen
Port geloggt.
• Überwachung der Bandbreite.
• Statische Zuordnung der Anschlüsse. → Switch
angeboten. Die Möglichkeiten sind von Hersteller zu Hersteller verschieden.
37
Teil III.
SAD
— Sniff And Die
Zusammenfassung
Dieser Teil beschäftigt sich mit der Implementierung von SAD. Die Designentscheidungen und
das daraus folgende Framework werden dem Leser vorgestellt. Danach wird ihm gezeigt, wie er
SAD mit eigenen Plugins erweitern kann.
9. Design
Programmer: A device for
converting coffee into software
(unknown)
Das im Rahmen dieser Diplomarbeit entwickelte Tool trägt den Name SAD, welcher für S NIFF
A ND D IE steht. Der Name spielt auf eine düstere Zeit für Script-Kiddies an, denn von jetzt an
können Sie detektiert werden. Es soll keine Anspielung auf SED, welches ein stream editor ist,
sein1 .
Bei der Entwicklung wurde grosser Wert auf modularen Aufbau, Erweiterbarkeit und Plattformunabhängigkeit gelegt. Daraus ergaben sich die zwei Komponenten von SAD:
1. Das Framework
2. Die Plugins
Im Kapitel 10 wird auf die einzelnen Komponenten des Framework’s eingegangen. Kapitel 11
erklärt dem Leser das Schreiben von Plugins in C++ unter L INUX.
Getrieben durch den Gedanken der Plattformunabhängigkeit, versuchten wir möglichst Bibliotheken, welche erfolgreich auf den meisten Plattformen laufen, einzusetzen. Infolgedessen fiel
unsere Wahl auf folgende Bibliotheken:
C++-STL [14, 15] als Basis für alle Container.
B OOST [13] kam bei den Threads zum Einsatz.
libConfuse [21] wurde für das Parsen der Konfigurationsdatei benutzt.
libnet [16] wurde für das Bauen der Datenpakete verwendet.
libpcap [19] übernahm das Fangen der Datenpakete.
1
Wir hoffen jedoch, dass es für Administratoren genau so nützlich ist
39
9.1. UML-Diagramm
9.1. UML-Diagramm
Abbildung 9.1.: UML-Diagramm von SAD
40
10. Das Framework
The trouble with doing
something right the first time is
that nobody appreciates how
difficult it was.
(unknown)
Hier werden alle Klassen im Zusammenhang mit dem Framework beschrieben. Den Plugins ist
ein eigenes Kapitel (Nr. 11) gewidmet.
10.1. Der Option-Manager
Da jedes Plugin eigene Optionen zur Verfügung stellt, musste ein Weg gefunden werden, wie
diese gemanagt werden sollen. Für diesen Zweck wurde die Klasse OptionMgr, welche als
Singleton1 realisiert ist, geschaffen.
c l a s s OptionMgr
{
private :
OptionMgr ( ) ;
s t a t i c OptionMgr ∗ i n s t a n c e ;
multimap < s t r i n g , O p t i o n > o p t i o n s ;
...
public :
s t a t i c OptionMgr ∗ g e t I n s t a n c e ( v o i d ) ;
void addOption ( s t r i n g , Option ) ;
c o n s t multimap < s t r i n g , O p t i o n > ∗ c o n s t g e t O p t i o n s ( v o i d ) c o n s t ;
friend class console ;
...
};
Listing 10.1: Die Klasse OptionMgr
Dass es sich um einen Singleton handelt, sieht man am privaten Konstruktor und dem Zeiger auf
sich selbst. Alle Optionen von SAD und den Plugins, werden in der multimap verwaltet. Als
Schlüssel dient der Plugin-Name. Die Optionen haben folgende Form:
s t r u c t Option
{
1
Infos zu Design-Patterns findet man unter [9]
41
10.2. Der Configfile-Parser
string sopt ;
string lopt ;
arg has_arg ;
s t r i n g argument ;
string description ;
Option ( s t r i n g s , s t r i n g l , arg at , s t r i n g a , s t r i n g d )
: s o p t ( s ) , l o p t ( l ) , h a s _ a r g ( a t ) , a r g u m e n t ( a ) , d e s c r i p t i o n ( d ) {}
};
Listing 10.2: Der Option-Struct
Eine Option hat den von getopt_long()2 her bekannten Aufbau. Bei uns ist es jedoch möglich, als Kurzoption auch mehrere Zeichen zu benutzen.
Option example = {
"− f i p " ,
"−−f a k e −i p " ,
REQ_ARG,
" 1.1.1.1 " ,
" S p e c i f i e s t h e Fake I P "
};
Listing 10.3: Aufbau einer Option
void OptionMgr::addOption(String, Option)
Mit dieser Methode können die Plugins ihre Optionen dem Option-Manager beifügen. Ein Beispiel für die Anwendung ist im Abschnitt 10.7 gezeigt.
const multimap<string, Option>* const getOptions(void) const
Diese Methode liefert einen Zeiger auf das private Attribut options. Damit ist es, sowohl dem
Framework als auch den Plugins, möglich, auf die Optionen zu zugreifen.
friend class console
Der Kommandozeilen-Parser braucht Schreibzugriff auf den Option-Manager. Der Anwender
möchte ja die Default-Werte überschreiben können. Um unnötige getter und setter Methoden
zu schreiben, deklarierten wir die Klasse console als friend. Damit hat die Klasse console
vollen Zugriff auf alle Elemente des Option-Managers.
10.2. Der Configfile-Parser
LIB C ONFUSE
ist eine, unter der LGPL[3] stehende, Bibliothek zum Parsen von Konfigurationsdateien. Es werden im Wesentlichen Sections und List of Values unterstützt. Des Weiteren ist
2
man 3 getopt_long
42
10.2. Der Configfile-Parser
LIB C ONFUSE
in der Lage sowohl, C-, C++- als auch shellartige Kommentare zu handhaben.
Der Aufbau der Konfigurationsdatei von SAD ist wie folgt:
p l u g i n ARP
{
p a t h = / u s r / l o c a l / l i b / sad / l i b a r p . so . 0 # Path t o t h e P l u g i n
t r u s t = 0.8
/ / How much do I t r u s t t h i s P l u g i n ?
evaluation = " true "
/∗ Should I e v a l u a t e t h e r e s u l t s ∗/
}
Listing 10.4: Aufbau von sad.conf
Hier sind die möglichen Kommentare gut ersichtlich. Die Klasse cfgParser hat die Aufgabe,
diese Einträge zu parsen und zu verwalten.
class cfgParser
{
private :
cfgParser ( ) ;
static cfgParser ∗ instance ;
static string cfgfile_ ;
struct cfgval
{
s t r i n g path ;
float trust ;
cfg_bool_t evaluation ;
};
map< s t r i n g , c f g v a l > p l u g i n ;
...
public :
s t a t i c c f g P a r s e r ∗ g e t I n s t a n c e ( void ) ;
vector < s t r i n g > g e t P a t h ( void ) ;
vector < s t r i n g > getPlugInName ( void ) ;
float getTrust ( string );
bool g e t E v a l u a t i o n ( s t r i n g ) ;
...
};
Listing 10.5: Die Klasse cfgParser
Da wir nur einen Parser brauchen, ist diese Klasse ebenfalls als Singleton implementiert. Die
folgende Methoden werden von SAD benötigt und darum hier beschrieben.
vector<string>getPath(void)
43
10.3. Der Kommandozeilen-Parser
Diese Methode iteriert durch die map<string, cfgval> plugin durch und liefert alle
eingetragenen Pfade der zu ladenden Plugins. Diese werden von SAD für das Laden der Plugins
verwendet.
vector<string>getPlugInName(void)
Diese Methode extrahiert alle Plugin-Namen aus der map<string, cfgval> plugin.
Nötig sind diese Namen für die Verwaltung der geladenen Plugins.
float getTrust(string)
Hiermit wir ein Wert zwischen 0 und 1 zurückgegeben. Die genaue Verwendung wird im Abschnitt 10.7.1 erläutert.
bool getEvaluation(string)
Da im Konfigurationsfile eingestellt werden kann, ob man das Resultat eines Plugins in die Gesamtbewertung mit einbeziehen will, braucht man diese Methode, um den Wert auszulesen.
10.3. Der Kommandozeilen-Parser
Da getopt_long() Kurzoptionen mit nur einem Buchstaben unterstützt, wurde diese Klasse
geschrieben.
class console
{
private :
OptionMgr ∗ o p t s _ ;
...
public :
i n t c m d p a r s e ( i n t , char ∗ ∗ ) ; / / r e t u r n s 0 on s u c c e s s
...
};
Listing 10.6: Die Klasse console
int cmdparse(int, char **)
Diese Methode parst die Kommandozeile und unternimmt allfällige Änderungen am OptionManager. Ihr werden die Parameter argc und *argv[] übergeben.
Der Aufbau der Kommandozeile hat folgende Form:
# s a d [−PluginName ] [ P l u g I n O p t s i o n s ] [ s a d O p t i o n s ] T a r g e t −IP
44
10.4. Threads
10.4. Threads
Damit wir eine einheitliche Thread Schnittstelle haben, wurde die abstrakte Klasse SadThread
ins Leben gerufen. Sie schreibt vor, das der Aufrufoperator () überschrieben wird3 . Diese Methode kann man sich wie die run() Methode bei JAVA-Threads vorstellen.
10.4.1. InjectionThread
Die Hauptaufgabe dieser Klasse besteht darin, vom Plugin gebaute und via addPacket(libnet_t *)
hinzugefügte Pakete, ins Netz zu stellen. Dafür gibt es zwei Modi:
• Die kontinuierliche Variante, die ohne Unterbruch alle angeforderten Pakete sendet.
• Die unstetige Variante, welche nach jedem Paket eine vorgegebene Zeit wartet.
10.4.2. CaptureThread
Der CaptureThread ist einfach gesagt eine Wrapperklasse für LIBPCAP.
Nebst den Standardaufrufen für LIBPCAP müssen wir den Filter auf nonblocking setzen, weil
wir bei unseren Tests nicht sicher gehen können, überhaupt eine Antwort zu fangen.
i f ( p c a p _ s e t n o n b l o c k ( h a n d l e , C a p t u r e T : : NONBLOCK_TRUE, e r r b u f ) < 0 )
throw L i b p c a p E x ( e r r b u f ) ;
Listing 10.7: CaptureT: nonblocking
Mit Hilfe des Konstruktors können alle Eigenschaften dieses Threads gesetzt werden:
C a p t u r e T ( char ∗ , s t r i n g , i n t
/∗ Device :
∗ BPF F i l t e r S t r i n g :
∗ Z e i t i n ms :
∗
∗ Anzahl Versuche :
∗
∗ VorzeitigerAbbruch :
∗
∗
∗ Rueckgabewert :
∗/
, int , int , i n t &);
zB " e t h 0 "
man tcpdump
Z e i t , d i e nach e i n e m e r f o l g l o s e n p c a p _ n e x t
b i s zum n a e c h s t e n V e r s u c h g e w a r t e t w i r d .
Wird f o r t l a u f e n d d e k r e m e n t i e r t .
V e r s u c h e = 0 −−> Abbruch
Nachdem d i e s A n z a h l P a k e t e
g e f a n g e n wurde −−>
V o r z e i t i g e r Abbruch
Anzahl gefangener Pakete
Listing 10.8: CaptureT: Konstruktor
Der CaptureT fängt alle Pakete, die mit dem Filter übereinstimmen und inkrementiert jeweils
den Rückgabewert.
Falls (Zeit · AnzahlV ersuche) ms abgelaufen sind, ohne ein Paket zu fangen, beendet sich
der Thread.
3
Handhabung von B OOST::Thread
45
10.5. Die Scan-Strategy
10.5. Die Scan-Strategy
Die Klasse ScanStrategy ist das Kernstück der ganzen Plugin-Umgebung. Diese abstrakte
Klasse hat folgende zwei Hauptaufgaben:
10.5.1. Vorlage für Plugins
Die wichtigste Methode der ScanStrategy ist virtual void scan(void) = 0, welche alle Plugins implementieren müssen, und im eigentlichen Sinne die “main()” Funktion eines
Plugins darstellt.
Des Weiteren werden folgende, von allen Plugins gebrauchte, Member-Variablen zur Verfügung
gestellt:
• bool verbose
• int loop
Bestimmt, ob eine detaillierte Ausgabe erfolgen soll.
Anzahl Wiederholungen des Tests.
• char *device
Das Interface auf das LIBNET und LIPCAP zugreifen.
• u_int32_t ip_src
Die IP-Quell-Adresse
• u_int32_t ip_dst
Die IP-Ziel-Adresse
• libnet_t* context
• char errbuf[]
Ein LIBNET Kontext
Ein Errorstring für diverse LIBNET Funktionen
• stringstream filter
Dient als Hilfe, um einen Filter zu bauen4 .
Kommunikation mit dem Option-Manager
Folgende Methoden bewirken das Zusammenspiel mit dem OptionMgr:
void pushOpt(Option) Eine Hilfsmethode, die von den Plugins benutzt werden muss,
um ihre Optionen global beim OptionMgr bekannt zu machen.
void setGlobalVal(void) Setzt alle oben beschriebenen Variablen auf die von console
eingelesenen oder standard Werte.
setLocalVal(void) = 0 Ist eine rein abstrakte Methode, die von allen Plugins überschrieben werden muss und den Zweck hat, dass die Plugins ihre Werte auf die eingelesenen Werte setzen.
void usage(void) const
Das sich die Plugins nicht auch noch um die Ausgabe und Darstellung ihrer Optionen kümmern
müssen, stellt ScanStrategy diese Funktion zur Verfügung.
4
stringstreams sind viel flexibler als strings in der Handhabung mit unterschiedlichen Datentypen
46
10.5. Die Scan-Strategy
10.5.2. Thread Handling
Die Plugins müssen sich nicht um das Starten von Threads kümmern. Sie bekommen ein Interface zur Verfügung gestellt, welches ihnen einfaches Hinzufügen von beliebigen InjectionThreads und CaptureThreads ermöglicht.
Das Plugin kann dann zu einem gewünschten Zeitpunkt mit Hilfe der Methode startThreads()
alle hinzugefügten Threads starten.
v o i d S c a n S t r a t e g y : : a d d T h r e a d ( S a d T h r e a d &t )
{
i f ( dynamic_cast < C a p t u r e T ∗>(& t ) )
t h r e a d s . p u s h _ f r o n t (& t ) ;
e l s e i f ( dynamic_cast < I n j e c t i o n T ∗>(& t ) )
t h r e a d s . p u s h _ b a c k (& t ) ;
}
Listing 10.9: ScanStrategy::addThread()
CaptureThreads sollen vorne angefügt werden, sodass sie auch bestimmt vor den InjectionThreads gestartet werden. → Antworten werden sicher gefangen.
void S c a n S t r a t e g y : : s t a r t T h r e a d s ( )
{
try
{
boost : : thread_group threadg ;
deque < S a d T h r e a d ∗ > : : i t e r a t o r d i ;
f o r ( d i = t h r e a d s . b e g i n ( ) ; d i ! = t h r e a d s . end ( ) ; ++ d i )
{
i f ( C a p t u r e T ∗ c t = dynamic_cast < C a p t u r e T ∗>
( r e i n t e r p r e t _ c a s t < S a d T h r e a d ∗ >(∗ d i ) ) )
threadg . c r e a t e _ t h r e a d (∗ c t ) ;
e l s e i f ( I n j e c t i o n T ∗ i t = dynamic_cast < I n j e c t i o n T ∗>
( r e i n t e r p r e t _ c a s t < S a d T h r e a d ∗ >(∗ d i ) ) )
threadg . c r e a t e _ t h r e a d (∗ i t ) ;
}
threadg . join_all ( ) ;
threads . clear ( ) ;
}
c a t c h ( b o o s t : : t h r e a d _ r e s o u r c e _ e r r o r bex )
throw BoostEx ( " t h r e a d _ r e s o u r c e _ e r r o r " ) ;
}
Listing 10.10: ScanStrategy::startThreads()
Diese Methode startet alle Threads die vorhin hinzugefügt wurden, wartet anschliessend auf die
Beendigung aller und entfernt sie aus der Queue.
47
10.6. Exceptions
10.6. Exceptions
Exceptions bringen in einem objektorientierten Design erhebliche Vorteile:
• Exception-Handling ist im Programmcode eindeutig erkennbar.
• Regulärer Code wird durch Exception-Handling kaum belastet.
• Jede Exception muss behandelt werden, ansonsten findet ein Abbruch statt.
• durch Parametrisierung mit Typen und Objekten, fein dosierte Reaktion auf unterschiedliche Fehlerarten möglich.
• Einheitliches Sprachmittel führt zu portablen Lösungen.
10.6.1. SadEx
Wir haben eine Super-Klasse SadEx definiert, welche so aufgebaut ist:
c l a s s SadEx
{
protected :
s t r i n g errorMessage ;
public :
SadEx ( s t r i n g e ) : e r r o r M e s s a g e ( e ) {}
s t r i n g operator ( ) ( ) { return errorMessage ; }
};
Listing 10.11: SadEx
Es ist eine ganz einfache Klasse, die im Wesentlichen einen String enthält, der die Fehlermeldung speichern kann. Durch den Aufrufoperator () kann man diese Fehlermeldung wieder auslesen.
Nun kann man für jede Art von Fehlerklasse eine eigene Ableitung von SadEx definieren:
c l a s s L i b n e t E x : p u b l i c SadEx
{
public :
L i b n e t E x ( s t r i n g e ) : SadEx ( " L i b n e t : " + e ) {}
};
Listing 10.12: Ableitung von SadEx
10.6.2. Anwendung
In einem Plugin könnte ein Fehler auftreten:
i f ( ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_LINK , d e v i c e , e r r b u f ) ) == 0 )
throw L i b n e t E x ( e r r b u f ) ;
Listing 10.13: Eine Exception werfen
48
10.6. Exceptions
SAD
muss diese Exception abfangen und behandeln:
try
s c a n r e s u l t s [ ∗ i t e r ] = s s t r a t [ ∗ i t e r ]−> s c a n ( ) ;
c a t c h ( SadEx ex )
{
c e r r << ex ( ) << e n d l ;
e x i t ( EXIT_FAILURE ) ;
}
Listing 10.14: Eine Exception abfangen
49
10.7.
SAD
10.7. SAD
Hier treffen alle Klassen zusammen. Der Programmablauf ist folgender:
Abbildung 10.1.: Flussdiagramm: SAD-Ablauf
Für das ganze Management der Klasse sind folgende Konstrukte notwendig:
map< s t r i n g , S c a n S t r a t e g y ∗> s s t r a t ; / / P o i n t e r t o O b j e c t s
s t r u c t soManager
{
v e c t o r < v o i d ∗> p p t r ;
v e c t o r < c r e a t e S S _ t ∗> c f u n c ;
v e c t o r < d e s t r o y S S _ t ∗> d f u n c ;
} mgr ;
//
//
//
//
Pointer to PluginHandler
CreateFunction
DestroyFunction
libmanager
Listing 10.15: SAD Verwaltungs-Konstrukte
50
10.7.
SAD
Die STL-Map sstrat verwaltet die aus den Plugins kreierten Objekte. Der Schlüssel der Map
ist der Plugin-Name. Der Wert zum Schlüssel ist ein Zeiger auf eine ScanStrategy.
Die Struktur soManager beinhaltet einen Plugin-Handler und die Create- und Destroy-Funktionen.
Mehr zu den Create- und Destroy-Funktionen finden Sie im Kapitel 11.
SAD muss, wie jedes andere Plugin, seine globalen Optionen bekannt geben. Dem Administrator
stehen folgende Optionen zur Verfügung:
SAD O p t i o n s :
−i f
−− i n t e r f a c e
−t i p
−−t a r g e t −i p
−s i p
−−s o u r c e −i p
−v
−−v e r b o s e
<Scanning device >
< t a r g e t IP >
< s o u r c e IP >
verbose output
Listing 10.16: Optionen von SAD
10.7.1. Rating
Da es unter gewissen Umständen, welche durch das Netz gegeben sind, zu falschen Verdächtigungen5 kommen kann, mussten wir ein Rating einführen. Im Kapitel 10.2 ist der Aufbau eines
Eintrages der Konfigurationsdatei beschrieben. Das Feld trust ist ein Erfahrungswert, welcher
das Vertrauen in diese Methode widerspiegelt. Es kann ein Wert von 0. . .1 angegeben werden.
Der boolean evaluation gibt an, ob der Test in die Schlussbewertung mit aufgenommen
werden soll. Diese Option wurde eingeführt, da gewisse Sniffer einige Tests6 austricksen können. Dadurch hat der Administrator die Möglichkeit das Resultat des Tests anzuzeigen, jedoch
nicht zu berücksichtigen.
# . / sad 1 6 0 . 8 5 . 1 6 3 . 7 4
ScanResults :
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Method
Testresult %
Trust
Evaluation
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
ARP
100 %
0.8
1
DNS
100 %
1.0
0
ICMP
100 %
0.6
1
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
Sum :
70 %
Listing 10.17: Ausgabe von SAD
Das Schlussresultat ist der Mittelwert der zu evaluierenden Tests.
Sum :=
5
6
N
1 X
Evaluation · T rust · T estresult
N i=1
weitere Informationen dazu, finden sich im Kapitel 15
wie z.B. der DNS-Test. Mehr dazu im Kapitel 12.3
51
11. Plugin-HowTo
Plugins sind unter L INUX nichts anderes als dynamisch geladene Bibliotheken1 . Sie können zu
jedem beliebigen Zeitpunkt zum Programm dazugeladen werden.
11.1. Das L INUX-Plugin-Interface
Unter L INUX, besteht im Aufbau einer shared und einer dynamic loaded Library kein Unterschied. Einzig der Zeitpunkt des Ladens der Library variiert. L INUX stellt eine API zum öffnen,
durchsuchen, behandeln von Fehlern und schliessen des Plugins zur Verfügung. Die Schnittstellen sind in <dlfcn.h> definiert.
v o i d ∗ d l o p e n ( c o i n s t char ∗ f i l e n a m e , i n t f l a g ) ;
v o i d ∗ dlsym ( v o i d ∗ h a n d l e , c o n s t char ∗ symbol ) ;
char ∗ d l e r r o r ( v o i d ) ;
i n t d l c l o s e ( void ∗ handle ) ;
Listing 11.1: Das L INUX-Plugin-Interface
11.2. Probleme mit C++
Da das API in und für C geschrieben wurde, zieht das einige Probleme beim Laden von Klassen
mit sich.
Wie den meisten bekannt sein sollte, verfügt C++ über einen Mechanismus zum Überladen von
Funktionen2 und Methoden. Um diese Mehrdeutigkeit zu handhaben, hängt der Compiler zusätzliche Zeichen an das entsprechende Symbol in der Symboltabelle an.
Sei eine Funktion
void foo ( void ) ;
gegeben.
Der C-Compiler trägt in die Symboltabelle ein Symbol mit dem Namen
foo
1
2
auch shared objects genannt
verschiedene Funktionen mit demselben Namen, aber unterschiedlicher Anzahl von Argumenten
52
11.3. Die Umsetzung bei SAD
ein.
Der C++-Compiler jedoch, verunstaltet den Namen und fügt in die Symboltabelle Folgendes
ein:
foo@5%6^
Dies wäre an und für sich nicht schlimm, würden dies alle Compiler gleich machen. Das macht
es wiederum für den Programmierer unmöglich das gesuchte Symbol in einem Plugin zu finden.
Bei Klassen kommt noch ein Problem, neben der Verunstaltung der Namen in der Symboltabelle, auf uns zu. Da wir mit Instanzen von Klassen arbeiten und nicht mit Zeigern auf Funktionen
muss ein Weg geschaffen werden, um diese zu erstellen3 .
extern "C" und class factory functions sind die Schlüsselmechanismen für die Lösung dieses
Problems. Das C++ dlopen mini HOWTO[11] schreibt:
The solution is achieved through polymorphism. We define a base, interface class
with virtual members in the executable, and a derived, implementation class in the
module. Generally the interface class is abstract (a class is abstract if it has pure
virtual functions).
11.3. Die Umsetzung bei SAD
Das Framework stellt die abstrakte Klasse ScanStrategy zur Verfügung. Diese definiert die Methoden, welche von den Plugins zur Verfügung gestellt werden müssen.
Die Typen der class factory functions werden auch von der ScanStrategy vorgegeben.
t y p e d e f S c a n S t r a t e g y ∗ c r e a t e S S _ t ( c o n s t char ∗ , OptionMgr ∗ ) ;
typedef void d e s t r o y S S _ t ( S c a n S t r a t e g y ∗ ) ;
Listing 11.2: Definition der class factory functions im ScanStrategy.hpp
Die einzelnen Plugins implementieren nun die class factory functions wie folgt:
e x t e r n "C"
{
return
}
e x t e r n "C"
{
delete
}
S c a n S t r a t e g y ∗ c r e a t e ( char ∗n , OptionMgr ∗ o p t )
new a r p ( n , o p t ) ;
void d e s t r o y ( S c a n S t r a t e g y ∗p )
p;
Listing 11.3: class factory functions am Beispiel vom ARP-Plugin
3
Weitere Informationen können in [11] nachgelesen werden
53
11.4. Schreiben eines eigenen Plugins
11.4. Schreiben eines eigenen Plugins
Der Ablauf beim Schreiben eines Plugins besteht aus vier Schritten.
1. Bekanntgabe der Plugin-Optionen
2. Implementieren der setLocalVal() Methode.
3. Implementieren der scan() Methode.
4. Schreiben der class factory functions.
Der Punkt 4 wurde im Kapitel 11.3 abgehandelt und wird hier nicht weiter erläutert.
Jedes Plugin muss folgende Header-Files einbinden:
# include
# include
# include
# include
# include
< s a d / sadEx . hpp >
< s a d / S c a n S t r a t e g y . hpp >
< s a d / o p t i o n M g r . hpp >
< s a d / i n j e c t i o n T . hpp >
< s a d / c a p t u r e T . hpp >
11.4.1. Bekanntgabe der Optionen
Der erste Schritt besteht darin, die Fähigkeiten des Plugins dem Option-Manager von SAD mitzuteilen. Dies macht man am besten im Konstruktor des Plugins.
a r p : : a r p ( s t r i n g n , OptionMgr ∗ o p t ) : S c a n S t r a t e g y ( n , o p t )
{
/∗ Declare Options ∗/
p u s h O p t ( O p t i o n ( "−a " , "−−a r p " ,NO_ARG, " " , " A c t i v a t e ARP−T e s t " ) ) ;
p u s h O p t ( O p t i o n ( "−c " , "−−c o u n t " ,REQ_ARG, " 10 " , " Count t o r u n ARP−T e s t " ) ) ;
p u s h O p t ( O p t i o n ( "−fm " , "−−f a k e −mac " ,REQ_ARG, " FF : FF : 0 0 : 0 0 : 0 0 : 0 0 " ,
" Faked D e s t i n a t i o n MAC" ) ) ;
p u s h O p t ( O p t i o n ( "−sm " , "−−s o u r c e −mac " ,REQ_ARG, " " , " s o u r c e MAC" ) ) ;
}
Listing 11.4: Bekanntgabe der Optionen
11.4.2. Implementieren der setLocalVal() Methode
Bei Kreieren des Objekts, werden die Attribute dem Framework bekannt gemacht. Danach folgt
das Parsen der Kommandozeile. Der Parser liest die Argumente und setzt die entsprechenden
Werte der Option. Diese müssen nun dem Plugin bekannt gegeben werden. Dies geschieht durch
die Methode
void arp : : s e t L o c a l V a l ( void )
{
...
/ / Libnet I n i t for getting default addresses
54
11.4. Schreiben eines eigenen Plugins
i f ( ! ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_LINK , d e v i c e , e r r b u f ) ) )
throw L i b n e t E x ( e r r b u f ) ;
/ / S e t d e f a u l t MAC S o u r c e A d d r e s s
i f ( ! ( e t h _ s r c = ( u _ i n t 8 _ t ∗) libnet_get_hwaddr ( context ) ) )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
...
}
Listing 11.5: Setzen der lokalen Variablen
Das ganze Listing kann im Anhang F.3.2 angeschaut werden.
11.4.3. Implementation der scan() Methode
Nach dem Laden und Kreieren der Plugins wird die Methode scan() jedes Plugins aufgerufen.
Ihre Funktionsweise wird anhand einiger Codefragmente dargestellt.
double arp : : scan ( void )
{
/ / Set Global Values & D e f a u l t s
setGlobalVal ( ) ;
setLocalVal ( ) ;
/ / Libnet I n i t
i f ( ! ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_LINK , d e v i c e , e r r b u f ) ) )
throw L i b n e t E x ( e r r b u f ) ;
...
/ / Building the Packets
...
/ / B u i l d i n g I n j e c t i o n −T h r e a d
I n j e c t i o n T fakeArp ;
/ / A d d i n g l i b n e t −P a c k e t t o t h e T h r e a d
fakeArp . addPacket ( c o n t e x t ) ;
addThread ( fakeArp ) ;
/ / Building Filter
f i l t e r << " a r p [ 7 ] = = 0 x02 and " ;
f i l t e r << " s r c h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ d s t , LIBNET_DONT_RESOLVE ) << " and " ;
f i l t e r << " d s t h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ s r c , LIBNET_DONT_RESOLVE ) ;
/ / B u i l d i n g C a p t u r e−T h r e a d
CaptureT a rp ca p ( device , f i l t e r . s t r ( ) , 2 , 1000 , loop , examines ) ;
addThread ( arpcap ) ;
/ / S t a r t i n g Threads
startThreads ();
/ / C l e a n i n g up
libnet_destroy ( context );
/ / Returning the r e s u l t
return r e s u l t ;
}
Die Attribute context und filter sind im Interface ScanStrategy.hpp definiert.
Um das Plugin für SAD sichtbar zu machen, muss es nach /usr/local/lib/sad/ kopiert
und folgender Eintrag in /etc/sad/sad.conf gemacht werden:
55
11.4. Schreiben eines eigenen Plugins
p l u g i n ARP
{
p at h = / u s r / l o c a l / l i b / sad / l i b a r p . so
t r u s t = 0.8
evaluation = " true "
}
Listing 11.6: Eintrag in sad.conf
56
12.
SAD -Plugins
The essence of the creative act
is to see the familiar as strange.
(unknown)
In diesem Kapitel werden die Besonderheiten der implementierten Plugins beschrieben. Die
Theorie für das Verständnis ist im Teil II abgehandelt.
Der Ablauf innerhalb eines Plugins ist im Plugin-HowTo beschrieben. Darum wird an dieser
Stelle getrost darauf verzichtet.
12.1. ARP
Bei diesem Plugin haben wir die Option --fake-mac eingeführt um allfällige Verbesserungen, z.B. das Prüfen der ersten drei Words der Ethernet-Adresse, vorzubeugen. Diese Option
ermöglicht es uns, des Weiteren auf Multicast-Adressen zu testen.
Möchte der Administrator den unerwünschten Lauscher in flagranti erwischen, so sollte er ihn
unerkannt testen. Dies wird mit der Option --source-mac erreicht. Sie ist nicht mit einem
Standardwert gefüllt, deshalb wird im Normalfall die eigene MAC-Adresse für den Test genommen.
Das Plugin stellt folgende Optionen zur Verfügung.
ARP O p t i o n s :
−a
−−a r p
−c
−−c o u n t
−fm
−−f a k e −mac
−sm
−−s o u r c e −mac
A c t i v a t e ARP−T e s t
< Count t o r u n ARP−T e s t >
< Faked D e s t i n a t i o n MAC>
< s o u r c e MAC>
Listing 12.1: Optionen des Plugins ARP
12.2. ICMP
Der ICMP-Test unterscheidet sich vom ARP-Test nur dadurch, dass er anstelle eines ARP Requests einen ICMP Request absetzt. Er verfügt über folgende Optionen:
ICMP O p t i o n s :
−i
−−icmp
A c t i v a t e ICMP−T e s t
57
12.3. DNS
−c
−fm
−sm
−−c o u n t
−−f a k e −mac
−−s o u r c e −mac
< Count t o r u n ICMP−T e s t >
< Faked D e s t i n a t i o n MAC>
< s o u r c e MAC>
Listing 12.2: Optionen des Plugins ICMP
12.3. DNS
Das Besondere an unserer Implementierung ist, dass wir zufällig IP-Adressen pingen. Bei jedem
Durchgang wird diese wie folgt gebildet:
q u e r y i p << r a n d ( ) % 200 + 1 << " . " << r a n d ( ) % 255
<< " . " << r a n d ( ) % 255 << " . " << r a n d ( ) % 2 5 5 ;
Listing 12.3: DNS-Test: Bau der IP-Adresse
Dies hat zur Folge, dass der Filter dementsprechend auch dynamisch gebaut werden musste.
void dns : : b u i l d F i l t e r ( void )
{
unsigned i n t pos [ 4 ] , u o f f s e t = 21;
string s [4];
f o r ( i n t i = 3 ; i >= 0 ; −−i )
{
g e t l i n e ( queryip , s [ i ] , ’ . ’ ) ;
pos [ i ] = s [ i ] . s i z e ( ) ;
}
f i l t e r << " d s t p o r t 53 " << " and " << " s r c h o s t "
<< l i b n e t _ a d d r 2 n a m e 4 ( i p _ d s t , LIBNET_RESOLVE ) ;
f o r ( u n s i g n e d i n t i = 0 ; i < 4 ; ++ i )
{
f o r ( u n s i g n e d i n t j = 0 ; j < s [ i ] . s i z e ( ) ; ++ j )
{
f i l t e r << " and " << " udp [ " << u o f f s e t << " ]== "
<< s t a t i c _ c a s t < i n t > ( s [ i ] . a t ( j ) ) ;
u o f f s e t ++;
}
++ u o f f s e t ;
}
}
Listing 12.4: Dynamischer Bau des Filters
Das DNS-Plugin verfügt über folgende Optionen:
DNS O p t i o n s :
−d
−−d n s
A c t i v a t e DNS−T e s t
58
12.4. LATENCY
−c
−−c o u n t
< Count t o r u n DNS−T e s t >
Listing 12.5: Optionen des Plugins DNS
12.4. LATENCY
Der LATENCY-Test wurde im Kapitel 7 ausführlich beschrieben, hier folgt nur der Ablauf der
scan() Methode:
1. Baue eine Anzahl ICMP Request mit fortlaufenden Sequenznummern.
2. Erstelle ein Flood-Paket, zum Beispiel Telnet-Daten.
3. Starte alle ICMP Request und einen LatencyCaptureThread (siehe Abschnitt 12.4.1).
4. Berechne durschnittliche Antwortzeit.
5. Starte alle ICMP Request plus einen Flood-Thread.
6. Berechne durschnittliche Antwortzeit.
7. Vergleiche die berechneten Werte.
Folgende Optionen werden zur Verfügung gestellt:
LATENCY O p t i o n s :
−l
−−l a t e n c y
−c
−−c o u n t
−s p
−−s o u r c e −p o r t
−dp
−−d e s t i n a t i o n −p o r t
−p
−−p a y l o a d
−f i p
−−f a k e −i p
A c t i v a t e L a t e n c y −T e s t
< Count t o r u n L a t e n c y −T e s t >
<TCP−S o u r c e−P o r t o f t h e f l o o d i n g Thread >
<TCP−D e s t i o n a t i o n −P o r t o f t h e f l o o d i n g Thread >
< P a y l o a d you want t o s e n d ( i n " Double Quote " ) >
<Fake−IP >
Listing 12.6: Optionen des Plugins Latency
Um den Flood-Thread ein wenig den eigenen Bedürfnissen anzupassen, ist die Option --payload
frei einstellbar. Dadurch wird ermöglicht, eine eigen Datenmenge anzugeben oder interessante
Schlüsselwörter, wie zum Beispiel Password oder Login ins Netzwerk einzuschleusen.
Mit der Option --fake-ip kann das “Opfer” ausgewählt werden, welches geflutet wird. Dabei
ist zu beachten, dass diese IP-Adresse erreichbar ist, ansonsten unterbricht LIBNET das senden
von Paketen. Des Weiteren muss damit gerechnet werden, dass dieser Host erhebliche Schwierigkeiten bekommen kann, seine Arbeit fortzusetzen → DoS.
12.4.1. LatencyCT
Da der LATENCY-Test im Gegensatz zu den anderen Tests sehr zeitkritisch ist, mussten wir
einen neuen CaptureThread kreieren, welcher eine Ableitung namens LatencyCT ist. Dieser
Thread ist speziell auf den LATENCY-Test zugeschnitten.
Die Aufgabe bestand darin, von allen ICMP Requests die Sendezeiten und von allen ICMP
Replies die Empfangszeiten zu speichern.
59
12.4. LATENCY
v o i d LatencyCT : : o p e r a t o r ( ) ( )
{
struct pcap_pkthdr header ;
c o n s t u _ c h a r ∗p ;
unsigned short seq = 0 ;
u n s i g n e d char t y p e = 0 ;
w h i l e ( m a x _ a t t e m p t s && f i n i s h )
{
i f ( ( p = p c a p _ n e x t ( h a n d l e , &h e a d e r ) ) ! = NULL)
{
/ ∗ g e t s e q u e n c e number ∗ /
s e q = ∗ ( p + 4 0 ) ; s e q <<= 8 ; s e q | = ∗ ( p + 4 1 ) ;
/ ∗ g e t ICMP Echo t y p e ∗ /
type = ∗( p +34);
i f ( t y p e == 8 )
/∗ request ∗/
memcpy ( ( v o i d ∗)& s e n d [ s e q ] , ( v o i d ∗)& h e a d e r . t s , s i z e o f ( t i m e v a l ) ) ;
e l s e i f ( t y p e == 0 ) / ∗ r e p l y ∗ /
memcpy ( ( v o i d ∗)& a r r i v e [ s e q ] , ( v o i d ∗)& h e a d e r . t s , s i z e o f ( t i m e v a l ) ) ;
−−f i n i s h ;
(∗ examines )++;
}
else
{
−−m a x _ a t t e m p t s ;
}
}
}
Listing 12.7: Latency CaptureThread
60
Teil IV.
Auswertung
Zusammenfassung
Da, die in den vorangegangenen Kapiteln vorgestellten Tests, im Wesentlichen auf Schwächen
der Ethernet- und TCP/IP-Implementierung beruhen, beschäftigt sich dieser Abschnitt mit den
einzelnen Betriebssystemen und wie sie auf SAD reagieren. Es werden die gängigsten U NIX und W INDOWS-Derivate getestet und ausgewertet.
Des Weiteren wird der LATENCY-Test ausgewertet und ein Blick in die Zukunft von SAD geworfen.
13. Vorhandene Tools
Es war von vornherein klar, dass wir nicht die Einzigen sind, welche auf die Idee gekommen
sind, einen Promiscuous Mode Detector zu schreiben. Folgende Tools wurden unter die Lupe
genommen:
A NTI S NIFF[5]
Es bestand keine Möglichkeit, dieses Tool unter L INUX zum Laufen zu bringen. Auch unter
W INDOWS 2000/XP hatten wir keine Chance. W INDOWS 98 bot dann zum ersten Mal, die
Möglichkeit A NTI S NIFF zu untersuchen. Das Ergebnis fiel ziemlich nüchtern aus: Ausser dem,
zum Teil erfolgreichen, ARP-Test und einem zugefluteten Netzwerk, schaute nicht viel heraus.
NEPED [6]
&
NEPED - LIBNET [7]
Dieses Programm gibt es in zwei verschiedenen Versionen. Eine davon wurde mittels ioctl()1
realisiert, die andere beruht auf LIBNET.
Leider funktionierte hier der einzig angebotene Test (ARP) bei beiden Versionen nicht. Auch die
Projekthomepage scheint tot zu sein und das Tool ist nur in einschlägigen Archiven auffindbar.
SENTINEL [8]
SENTINEL ist das funktionsreichste Tool, dass wir finden konnten. Der ARP- und ICMP-Test
waren teilweise erfolgreich. Der DNS-Test funktionierte, solange man ihn nur einmal ausführte.
Ein grosses Manko von SENTINEL ist ganz klar das Design und die Übersichtlichkeit des Quellcodes.
1
man 2 ioctl
63
14.
SAD
Als das Tool die erste Phase der Entwicklung hinter sich hatte, wurde es einem Praxistest unterzogen. Die folgende Tabelle dient als Übersicht über die getesteten Betriebssysteme und deren
Variationen.
W INDOWS 2000 SP4
W INDOWS XP SP1
W INDOWS XP SP2
L INUX 2.2
L INUX 2.4
L INUX 2.6
O PEN BSD 3.6
F REE BSD 4.6
M AC OSX Darwin Kernel 7.5.0
S UN OS 5.7
ARP
—
ICMP
—
—
—
—
—
—
Tabelle 14.1.: Analysierte Betriebssysteme
DNS
14.1. LATENCY-Test
Wie schon im vorderen Teil dieses Dokumentes angekündigt, ist der LATENCY-Test sehr subjektiv. Man muss einige Tests machen um zu sehen, wie hoch man die Schwelle setzen kann,
damit man herausfindet, ob ein Rechner im promiscuous mode läuft, oder ob überhaupt eine
solche Schwelle existiert.
Den LATENCY-Test, den wir implementiert haben, basiert darauf ICMP Antwortzeiten zu messen. Dies einmal in einem unbelasteten und danach im belasteten Netzwerk.
14.1.1. Messungen
Um eine aussagekräftige Statistik zu erhalten, haben wir für beide Szenarien (promiscuous mode
und normal mode) je 10 Tests gemacht.
64
14.1. LATENCY-Test
Anzahl Wiederholungen pro Test
Anzahl ICMP Requests pro Wiederholung ohne flooding
Anzahl Telnet Pakete pro Wiederholung fürs flooding
Grösse der Telnet Daten
Anzahl ICMP Requests pro Wiederholung mit flooding
10
50
500000
713 Byte
50
Tabelle 14.2.: Angaben zur Messreihe
regular Network
drop count
averrage RTD
normal promisc normal promisc
0
0
162.8
186.5
0
0
163.6
181.9
0
0
162.1
167.1
0
0
167.9
165.9
0
0
165.5
166.3
0
0
162.4
166.0
0
0
162.4
166.6
0
0
163.9
165.8
0
0
162.5
165.5
0
0
180.5
171.0
0
0
165.4
170.3
flooded Network
drop count
averrage RTD
normal promisc
normal promisc
8.5
6.3 10658.9
1197.0
7.2
7.0 16998.0
3100.3
6.5
5.6 18780.2 31798.1
7.5
6.7 12569.4 13052.8
6.3
8.1 24574.8 10475.3
5.7
6.6 23406.8
9833.2
7.1
7.5 16300.8 10907.4
7.4
7.3 10672.2
9310.4
7.6
6.9 16994.1 37485.0
6.8
4.7
9120.1 99440.0
7.0
6.7 16007.5 22660.0
Tabelle 14.3.: Durschnittswerte der 10 Tests
Schauen wir uns die Ergebnisse etwas genauer an. Die blaue gestrichelte Linie steht für die
Messreihe im normalen Modus, die rote durchgezogene Linie für den promiscuous mode.
Abbildung 14.1 zeigt die durchschnittliche Antwortzeit im unbelasteten Netz in µs. Man kann
erkennen, dass hier kein deutlicher Unterschied zwischen den beiden Modi auszumachen ist.
65
14.1. LATENCY-Test
Abbildung 14.1.: Durchschnittliche Antwortzeit im unbelasteten Netzwerk
In Abbildung 14.2 ist dasselbe Szenario wie vorhin, aber in einem belasteten Netzwerk. Es sind
deutliche Unterschiede zu erkennen, das Problem ist nur, dass nicht festzustellen ist, ob die
höhere Latenzzeit nun dem promiscuous mode zuzuordnen ist.
Abbildung 14.2.: Durchschnittliche Antwortzeit im belasteten Netzwerk
Zum Schluss ist in Abbildung 14.3 noch dargestellt, wie sich die durchschnittliche Verlustrate
der Antworten verhaltet. Es ist eindeutlich zu sehen, dass kein Unterschied besteht.
66
14.1. LATENCY-Test
Abbildung 14.3.: Durchschnittliche Drops im belasteten Netzwerk
Abbildung 14.4.: Erzeugte Netzlast
14.1.2. Fazit
Obwohl wir eine starke Netzwerkbelastung (siehe Abbildung 14.4) erzeugt haben, konnten wir
keine, für unser Tool brauchbaren Resultate erzielen.
Die Tatsache, dass ICMP Anfragen mit zu hoher Priorität und sehr früh im Kernel behandelt
werden, ziehen wir als Ursache in Betracht.
Ein Lösungsansatz für dieses Problem wäre, die Anfrage-Antwort-Routine für die Zeitmessung
auf ein anderes Protokoll zu verlegen. Zum Beispiel einen TCP 3-Way Handshake zu simulieren
oder noch besser etwas auf Layer 7, wie etwa einen HTTP-Request. Denn je höher die Anfragen
im Networkstack nach oben gehen, desto mehr gibt es zu rechnen. Jeder Context-Switch bringt
zusätzliche Verluste.
67
15. Ausnahmen
15.1. Phänomen Surecom Router
Ein Student hat einen Router mit einem integrierten USB-Printserver am Schulnetz angeschlossen, der aus unbekannten Gründen unsere gefakten IP-Pakete nochmals, mit einer MulticastAdresse versehen, ins Netz stellt. Das folgende Listing zeigt ein von uns erstellten ICMP Request mit einer “falschen” Ethernet-Ziel-Adresse.
E t h e r n e t I I , S r c : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5 , D s t : f f : f f : 0 0 : 0 0 : 0 0 : 0 0
Destination : ff : ff :00:00:00:00 ( ff : ff :00:00:00:00)
S o u r c e : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5 ( CompaqCo_99 : 4 2 : 0 5 )
Type : I P ( 0 x0800 )
I n t e r n e t P r o t o c o l , S r c Addr : s t d r e u s s h a l . zhwin . ch ( 1 6 0 . 8 5 . 1 6 3 . 7 4 ) ,
D s t Addr : s t d v e s e l r a n . zhwin . ch ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
I n t e r n e t C o n t r o l Message P r o t o c o l
Listing 15.1: fake ICMP Request
Der zu untersuchende Host (stdveselran.zhwin.ch) befindet sich im promiscuous mode und gibt
erwartungsgemäss eine ICMP-Antwort.
E t h e r n e t I I , S r c : 0 0 : 0 6 : 1 b : c a : e a : 2 3 , D s t : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5
D e s t i n a t i o n : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5 ( CompaqCo_99 : 4 2 : 0 5 )
Source : 0 0 : 0 6 : 1 b : ca : ea :23 ( P o r t a b l e _ c a : ea : 2 3 )
Type : I P ( 0 x0800 )
T r a i l e r : 00000000000000000000000000000000...
I n t e r n e t P r o t o c o l , S r c Addr : s t d v e s e l r a n . zhwin . ch ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ) ,
D s t Addr : s t d r e u s s h a l . zhwin . ch ( 1 6 0 . 8 5 . 1 6 3 . 7 4 )
I n t e r n e t C o n t r o l Message P r o t o c o l
Listing 15.2: Erwartete Antwort
Nun schaltet sich der S URECOM Router ein. Er stellt den gleichen ICMP Request nochmals ins
Netz, ändert aber die Ethernet-Ziel-Adresse zu einer Multicast-Adresse. Dieser Router mappt
die IP-Adresse in eine Multicast-Adresse.
E t h e r n e t I I , S r c : 0 0 : 0 2 : 4 4 : 7 9 : a f : ab , D s t : 0 1 : 0 0 : 5 e : 5 5 : a4 : e a
D e s t i n a t i o n : 0 1 : 0 0 : 5 e : 5 5 : a4 : e a ( 0 1 : 0 0 : 5 e : 5 5 : a4 : e a )
S o u r c e : 0 0 : 0 2 : 4 4 : 7 9 : a f : ab ( SurecomT_79 : a f : ab )
Type : I P ( 0 x0800 )
T r a i l e r : 00000000000000000000000000000000...
68
15.2. false positives
I n t e r n e t P r o t o c o l , S r c Addr : s t d r e u s s h a l . zhwin . ch ( 1 6 0 . 8 5 . 1 6 3 . 7 4 ) ,
D s t Addr : s t d v e s e l r a n . zhwin . ch ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 )
I n t e r n e t C o n t r o l Message P r o t o c o l
Listing 15.3: Multicast korrigiertes Paket
Da das Paket an eine Multicast-Adresse gesendet wurde und sich der Host immer noch im promiscuous mode befindet, verarbeitet er auch diese Anfrage und sendet eine Antwort zurück.
E t h e r n e t I I , S r c : 0 0 : 0 6 : 1 b : c a : e a : 2 3 , D s t : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5
D e s t i n a t i o n : 0 0 : 0 2 : a5 : 9 9 : 4 2 : 0 5 ( CompaqCo_99 : 4 2 : 0 5 )
Source : 0 0 : 0 6 : 1 b : ca : ea :23 ( P o r t a b l e _ c a : ea : 2 3 )
Type : I P ( 0 x0800 )
T r a i l e r : 00000000000000000000000000000000...
I n t e r n e t P r o t o c o l , S r c Addr : s t d v e s e l r a n . zhwin . ch ( 1 6 0 . 8 5 . 1 6 4 . 2 3 4 ) ,
D s t Addr : s t d r e u s s h a l . zhwin . ch ( 1 6 0 . 8 5 . 1 6 3 . 7 4 )
I n t e r n e t C o n t r o l Message P r o t o c o l
Listing 15.4: Zweite Antwort
Das Problem ist nun, dass diese Antworten nicht zu unterscheiden sind. Die beiden Antworten
sind identisch, was bedeutet, dass wir doppelt so viele Replies zurückbekommen, wie wir Requests abgesendet haben.
Unser Tool SAD kann mit diesem Problem umgehen, indem wir nur schauen ob Antworten
zurückkommen und nicht wie viele.
15.2. false positives
Während unserer Testphase sind uns einige false positives aufgefallen.
Folgende Hardware hat, ohne im promiscuous mode zu sein, Reaktionen auf unsere Tests gezeigt. Alle haben einen Fehler im Hardware-Filter. Falls das group bit gesetzt ist, wird die ganze
Adresse als Multicast interpretiert und nicht verworfen.
Z Y XEL ADSL-Router
Versionen:
ZyNOS F/W Version: V2.50(AJ.9) | 07/09/2002
ZyNOS F/W Version: V3.40(FU.4) | 11/26/2002
AXIS Network Printserver
Version: AXIS OfficeBasic 6.15
69
15.2. false positives
Netzwerkarten
HP Omnibook xe4500, NatSemi DP8315
Diese Netzwerkkarte hat überhaupt keinen Hardware-Filter!!!
70
16. Ausblick
16.1. Anti-SAD
Dieser Abschnitt soll beschreiben, was unternommen werden kann, um
machen. Schauen wir uns kurz die vier Methoden an:
SAD
unbrauchbar zu
ARP
Die ARP-Routine1 im Kernel muss überprüfen, ob ein ARP Request an die richtige BroadcastAdresse (FF:FF:FF:FF:FF:FF) gesendet wurde.
ICMP
Die IP-Routine2 im Kernel muss überprüfen, ob Ziel-IP und MAC ein gültiges Paar bilden.
DNS
Falls der Sniffer die Namensauflösung deaktiviert, ist der DNS-Test machtlos.
LATENCY
Gegen den LATENCY-Test gibt es kein wirkungsvolles Mittel, da die Rechner im Vergleich
zu den verfügbaren Bandbreiten aber immer schneller werden, wird es in Zukunft schwer sein,
einen erfolgreichen LATENCY-Test durchzuführen.
Was aber nicht heissen soll, dass unser Tool schnell unbrauchbar sein wird. Denn für die oben genannten Gegenmassnahmen sind tiefere Kerneleingriffe notwendig, welche auch nicht ganz ohne sind, weil immer noch überprüft werden muss, ob es sich um registrierte Multicast-Adressen
handelt.
16.2. Zukunft von SAD
Wir werden das Projekt ganz bestimmt weiterhin betreuen und wollen es gerne unter der GPLLizenz auf SOURCE FORGE[4] betreiben.
Folgende Änderungen oder Erweiterungen sind in naher Zukunft geplant:
1
2
L INUX: arp_rcv()
L INUX: ip_rcv()
71
16.2. Zukunft von SAD
• LatencyCT ist ein dirty workarround für das LATENCY-Plugin → CaptureT flexibler
gestalten, sodass LatencyCT überflüssig wird.
• Einen LATENCY-Test auf TCP-Ebene implementieren.
• Beim ARP-Test einen stärken Filter bauen, sodass keine false positives bei Tests in eine
andere Broadcast-Domäne entstehen.
• Differenzierterer Umgang mit den Exceptions.
• Die Möglichkeit ein ganzes Subnetz oder einen Range zu scannen.
• Umstieg auf GLIB um die Plattformunabhängigkeit zu verbessern (Laden der Plugins)
• Auf AUTOTOOLS umsteigen.
• Erstellen von Binärpaketen für .rpm, .deb.
• Evtl. B OOST::Thread durch eine andere Thread Bibliothek ersetzten.
72
Schlusswort
Irgendwie sind wir froh, dass diese Diplomarbeit endlich fertig gestellt und es sauber abgeschlossen ist. Auf der anderen Seite ist es auch traurig, dass die Zeit schon um ist.
Denn trotz einiger Stunden, in denen unsere Köpfe rauchten und wir kurz vor dem Gang zur
Klapsmühle standen, hatten wir jede Menge Spass. Nicht nur das es eine wahnsinnig interessante Aufgabe war, die wir zu lösen versuchten, nein, es war auch eine sehr gute Zusammenarbeit,
in der es nicht nur beim Kaffee viel zu lachen gab.
Die Betreuung durch Herr S TEFFEN war sehr gut. Obwohl unsere Meetings doch immer etwas
kurz ausfielen, wussten wir es zu schätzen, dass Herr S TEFFEN jederzeit zur Stelle gewesen war,
wenn Probleme oder Fragen auftraten. Des Weiteren verhinderten die regelmässigen Treffen,
dass wir vom Weg abkamen.
Die Implementierung unseres Tools SAD war wirklich eine Freude. Obwohl wir teilweise das
Gefühl hatten wir würden die einen Netzwerkprotokolle Byte für Byte auswendig kennen, kam
schon bald etwas Brauchbares heraus. Zum Schluss brachten uns noch einige ZHW-Netz-Eigenheiten zum Schwitzen. Aber wir denken, das muss so sein, ansonsten wäre es ja langweilig ;-)
Unser Ziel ist, dass SAD im systemadministrativen Umfeld eingesetzt werden kann, dafür müssen wir aber nochmals ein wenig Zeit investieren.
Trotz3 der anspruchsvollen Aufgabe und den zahlreichen Abenden, die wir an der ZHW verbrachten, hatten wir einen riesigen Spass mit der Arbeit. Wir gehen sogar so weit, zu behaupten,
dass der Spass je länger je grösser wurde.
Auch wenn wir zum Schluss noch einen kleinen Kampf gegen die Zeit führten, um die Dokumentation fertig zustellen, haben wir doch noch einen Sieg über den Projektplan erzielen können.
3
oder gerade wegen?
73
Teil V.
Anhang
Zusammenfassung
Dieser Teil beinhaltet den Projektplan, einen einfachen L INUX-Sniffer, einen kleinen Exkurs in
den L INUX-Networkstack und die Quellen.
A. Projektplan
Der Projektplan kann unter http://www.corleone.ch/sad/projektplan angeschaut werden.
75
B. Ein einfacher L INUX-Sniffer
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
# include
< s t d i o . h>
< s t r i n g . h>
< e r r n o . h>
< u n i s t d . h>
< s y s / s o c k e t . h>
< s y s / t y p e s . h>
< l i n u x / i n . h>
< l i n u x / i f _ e t h e r . h>
< n e t / i f . h>
< l i n u x / f i l t e r . h>
< s y s / i o c t l . h>
i n t main ( i n t a r g c , char ∗∗ a r g v )
{
i n t sock , n ;
char b u f f e r [ 2 0 4 8 ] ;
u n s i g n e d char ∗ i p h e a d , ∗ e t h h e a d ;
struct ifreq ethreq ;
/ ∗ Unser F i l t e r
∗ tcpdump N o t a t i o n : udp and p o r t 53 and d s t h o s t 1 6 0 . 8 5 . 1 9 5 . 1 9 5
∗ tcpdump −d l i e f e r t den BPF−Code i n m e n s c h e n l e s b a r e r Form
∗ tcpdump −dd l i e f e r t f o l g e n d e s C−Programm Fragment :
∗/
s t r u c t s o c k _ f i l t e r BPF_code [ ] = {
{ 0 x28 , 0 , 0 , 0 x0000000c } ,
{ 0 x15 , 1 3 , 0 , 0 x000086dd } ,
{ 0 x15 , 0 , 1 2 , 0 x00000800 } ,
{ 0 x30 , 0 , 0 , 0 x00000017 } ,
{ 0 x15 , 0 , 1 0 , 0 x00000011 } ,
{ 0 x28 , 0 , 0 , 0 x00000014 } ,
{ 0 x45 , 8 , 0 , 0 x 0 0 0 0 1 f f f } ,
{ 0 xb1 , 0 , 0 , 0 x0000000e } ,
{ 0 x48 , 0 , 0 , 0 x0000000e } ,
{ 0 x15 , 2 , 0 , 0 x00000035 } ,
{ 0 x48 , 0 , 0 , 0 x00000010 } ,
{ 0 x15 , 0 , 3 , 0 x00000035 } ,
{ 0 x20 , 0 , 0 , 0 x0000001e } ,
{ 0 x15 , 0 , 1 , 0 x a 0 5 5 c 3 c 3 } ,
{ 0x6 , 0 , 0 , 0 x00000060 } ,
{ 0x6 , 0 , 0 , 0 x00000000 } ,
};
struct sock_fprog F i l t e r ;
F i l t e r . len = 16;
F i l t e r . f i l t e r = BPF_code ;
i f ( ( s o c k = s o c k e t ( PF_PACKET , SOCK_RAW, h t o n s ( ETH_P_IP ) ) ) < 0 )
{
perror ( " socket " ) ;
exit (1);
}
/ ∗ N e t z w e r k k a r t e i n den p r o m i s c u o u s mode v e r s e t z e n ∗ /
77
s t r n c p y ( e t h r e q . i f r _ n a m e , " e t h 0 " , IFNAMSIZ ) ;
i f ( i o c t l ( sock , SIOCGIFFLAGS,& e t h r e q )== −1)
{
perror ( " ioctl " );
c l o s e ( sock ) ;
exit (1);
}
e t h r e q . i f r _ f l a g s | = IFF_PROMISC ;
i f ( i o c t l ( sock , SIOCSIFFLAGS ,& e t h r e q )== −1)
{
perror ( " ioctl " );
c l o s e ( sock ) ;
exit (1);
}
/ ∗ F i l t e r dem S o c k e t h i n z u f u e g e n ∗ /
i f ( s e t s o c k o p t ( sock , SOL_SOCKET , SO_ATTACH_FILTER , &F i l t e r , s i z e o f ( F i l t e r ) ) < 0 )
{
perror ( " setsockopt " );
c l o s e ( sock ) ;
exit (1);
}
while ( 1 )
{
n = r e c v f r o m ( sock , b u f f e r , 2 0 4 8 , 0 ,NULL, NULL ) ;
p r i n t f ( "%d b y t e s r e a d \ n " , n ) ;
/ ∗ U e b e r p r u e f e , ob d a s P a k e t m i n d e s t e n s k o m p l e t t e
∗ E t h e r n e t ( 1 4 ) , IP ( 2 0 ) und TCP /UDP ( 8 )
∗ Header e n t h a l t e n .
∗/
i f ( n < 42 )
{
p e r r o r ( " recvfrom ( ) : " ) ;
p r i n t f ( " I n c o m p l e t e p a c k e t ( e r r n o i s %d ) \ n " , e r r n o ) ;
c l o s e ( sock ) ;
exit (0);
}
ethhead = buffer ;
p r i n t f ( " S o u r c e MAC a d d r e s s : "
"%02x :%02 x :%02 x :%02 x :%02 x :%02 x \ n " ,
ethhead [0] , ethhead [1] , ethhead [2] ,
ethhead [3] , ethhead [4] , ethhead [ 5 ] ) ;
p r i n t f ( " D e s t i n a t i o n MAC a d d r e s s : "
"%02x :%02 x :%02 x :%02 x :%02 x :%02 x \ n " ,
ethhead [6] , ethhead [7] , ethhead [8] ,
ethhead [9] , ethhead [10] , ethhead [ 1 1 ] ) ;
iphead = b u f f e r +14;
/ ∗ Ü b e r s p r i n g e E t h e r n e t −Header ∗ /
i f ( ∗ i p h e a d ==0 x45 )
/ ∗ Üü b e r p r f e ob I P v 4 ohne O p t i o n s ∗ /
{
p r i n t f ( " S o u r c e h o s t %d.%d.%d.%d \ n " ,
iphead [12] , iphead [13] ,
iphead [14] , iphead [ 1 5 ] ) ;
p r i n t f ( " D e s t h o s t %d.%d.%d.%d \ n " ,
iphead [16] , iphead [17] ,
iphead [18] , iphead [ 1 9 ] ) ;
p r i n t f ( " S o u r c e , D e s t p o r t s %d ,%d \ n " ,
( i p h e a d [ 2 0 ] < <8 ) + i p h e a d [ 2 1 ] ,
( i p h e a d [ 2 2 ] < <8 ) + i p h e a d [ 2 3 ] ) ;
78
p r i n t f ( " Layer −4 p r o t o c o l %d \ n " , i p h e a d [ 9 ] ) ;
}
}
}
Listing B.1: Minisniffer
# ./ minisniffer
66 b y t e s r e a d
S o u r c e MAC a d d r e s s : 0 0 : d0 : 0 3 : 2 2 : 7 c : 0 a
D e s t i n a t i o n MAC a d d r e s s : 0 0 : 0 6 : 1 b : c a : e a : 2 3
Source host 160.85.191.180
Dest h o st 6 4. 236 .3 4. 196
Source , Dest p o r t s 32777 ,80
Layer −4 p r o t o c o l 6
...
Listing B.2: Ausgabe
79
C. L INUX Networkstack-Walkthrough
In diesem Kapital wird möglichst kurz und einfach beschrieben, wie ein Paket, das von der Netzwerkkarte empfangen wurde, durch den L INUX Netzwerkstack hindurchgereicht wird.
Es werden nicht alle Funktionen bis ins Detail besprochen und um das Dokument nicht unnötig
aufzublähen, widmet sich das Kapitel vor allem dem Empfang von Paketen. Das Ziel liegt darin
zu erklären, warum unsere Methoden, die auf Schwächen des Netzwerkstacks basieren, überhaupt funktionieren. Auch für den ICMP-Latency- und LATENCY-Test muss man sich kurz mit
diesem Thema auseinander setzen.
C.1. Ethernet Card and Lower-Kernel Reception — Layer 1
Wie schon bekannt, hat jede Netzwerkkarte, meistens eine fixe, Link-Layer oder MAC Adresse.
Wenn die Netzwerkkarte nun ein Paket sieht, das an seine oder an die Broadcast-Adresse adressiert ist, beginnt sie das Paket in den FIFO-Buffer rx_ring zu laden.
Falls nun aber die Netzwerkkarte in den promiscuous mode versetzt wurde, beginnt sie jedes
empfangene Paket in den Speicher zu laden.
Sobald ein Paket eingelesen wurde, generiert die Netzwerkkarte einen Interrupt-Request. Die
ISR, die diesen Request bearbeitet, ist meistens der Netzwerkkarten-Treiber selbst, welcher im
Modus interrupt disabled abläuft und folgende Operationen durchführt:
• Platz für eine neue sk_buff Struktur1 allozieren, welche die Sicht des Kernels auf das
Frame repräsentiert.
• Daten aus dem Netzwerkkarten-Buffer holen und in die frisch allozierte sk_buff Struktur kopieren, evtl. mit Hilfe von DMA.
• Die protokollunabhängige Empfangssteuerungsfunktion netif_rx() oder
netif_rx_schedule() ausführen.
• Interrupts aktivieren.
Um einen echten Ethernet-Treiber in Aktion zu sehen, sollte man sich die Funktionen
ei_interrupt() und ei_receive() in drivers/net/8390.c ansehen.
1
Das Herz des L INUX Netzwerkcodes
80
C.2. Network Core Processing — Layer 2
C.2. Network Core Processing — Layer 2
C.2.1. NAPI
Der Interrupt Mechanismus führt zu einem Phänomen namens “Überlastkollaps”. Dies tritt auf,
wenn so viele Pakete ankommen, dass vor lauter Interrupts so viel Zeit aufgefressen wird, dass
der Prozessor keine anderen Aufgaben mehr erledigen kann. DoS-Attacken können so wirkungsvoll sein.
Für die Lösung dieses Problems bietet das N EW API2 , dass folgende Strategie implementiert:
Anstatt das die Netzwerkkarte jedes Mal den Prozessor unterbricht, wenn ein Frame ankommt,
wird das Interface bei einer Poll-List registriert und die Interrupts werden ausgeschaltet. Diese
Poll-List wird nun durch einen Scheduler abgearbeitet, wobei gewisse Quotas per Interface zur
Verfügung stehen.
Die beiden folgenden Grafiken sollen die Unterschiede zwischen der alten und der neuen API
aufzeigen. Die Grafiken dienen auch zum besseren Verständnis der unten beschrieben Funktionen.
Abbildung C.1.: Old API: Kernel <2.4.19
2
ab Kernel 2.4.19
81
C.2. Network Core Processing — Layer 2
Abbildung C.2.: New API (NAPI): Kernel ≥ 2.4.19
C.2.2. netif_rx() und netif_rx_schedule()
Diese beiden Funktionen bereiten den Kernel für den nächsten Empfangsschritt vor.
Bei der alten API wird netif_rx() aufgerufen, die folgende Funktionen ausführt:
Sie hängt die allozierte sk_buff Struktur in die Empfangsqueue (backlog) für die
aktuelle CPU. Falls die Queue voll ist, wird dieses Frame verworfen und gewartet,
bis die Queue ganz leer ist. Da diese Funktion im Kontext der ISR läuft, muss sie
möglichst einfach und kurz sein, da sonst ankommende Pakete nicht bearbeitet werden können, deshalb wird zum Schluss die Empfangsroutine (Soft-IRQ3 ) angekickt.
Diese Funktion gibt einen so genannten “Überlast-Level” zurück:
NET_RX_SUCCESS, NET_RX_CN_LOW, NET_RX_CN_MOD,
NET_RX_CN_HIGH oder NET_RX_DROP.
Der NAPI-Treiber funktioniert nach einem anderen Prinzip:
Der Interrupt-Handler ruft die Methode netif_rx_schedule() auf. Anstatt
das Paket der Queue hinzuzufügen, wird eine Referenz auf das Device in der receive poll list des aktuellen Prozessors angelegt. Wie bei der alten API wird ein
Software-Interrupt gestartet.
Dies ist der einzige negative Punkt des NAPI. Dadurch, dass ein Device immer nur
mit einer CPU assoziiert wird, ist die SMP-Fähigkeit bei nur einem Device sehr
3
Es werden Soft-IRQs anstatt Bottom-Halves verwendet, das die Sequenzialisierung bei SMP so vermieden wird
82
C.3. Ausgewählte Passagen aus den Kernelsourcen
eingeschränkt.
Um Rückwärtskompatibilität zu gewährleisten, wird der backlog der alten API als
ein Device behandelt.
C.2.3. NET_RX softirq net_rx_action()
Sobald die vorher gestartete Funktion ihre Arbeit wieder aufnimmt, erledigt sie einfach gesagt
folgende Operationen:
Bei älteren Kernelversionen:
• Ein Paket aus der backlog queue herausnehmen.
• Die Liste (Hashtable) der vorhandenen Packet-Handler z.B. für ARP oder IP hindurchiterieren und die dafür zuständige Funktion
(arp_rcv(), ip_rcv(), icmp_rcv(), ...) aufrufen.
Falls die Queue mehr als ein Paket enthaltet, führt rx_action() eine Schleife über alle Pakete aus, bis entweder ein Maximum an Paketen (netdev_max_backlog) erreicht wurde oder
zu viel Zeit verbraucht wurde4 .
Bei Kernelversionen, die das NAPI enthalten:
• Durch die, für den aktuellen Prozessor, receive poll list hindurchiterieren und für jedes
Device alle empfangenen Pakete aus dem rx_ring oder aus dem backlog holen.
• Die poll Methode für das backlog device ist process_backlog(), welche die Pakete vorbereitet, um von netif_receive_skb aufgerufen zu werden. Für alle anderen
Devices wird, für jedes Paket die Methode netif_receive_skb direkt aufgerufen.
• Diese Routine ruft im eigentlichen Sinne wieder für jeden Paket-Typ die richtige Funktion
auf.
C.3. Ausgewählte Passagen aus den Kernelsourcen
/∗∗
∗ d e v _ s e t _ p r o m i s c u i t y − u p d a t e p r o m i s c u i t y c o u n t on a d e v i c e
∗ @dev : d e v i c e
∗ @inc : m o d i f i e r
∗
∗ Add o r remove p r o m s i c u i t y f r o m a d e v i c e . W h i l e t h e c o u n t i n t h e d e v i c e
∗ r e m a i n s a b o v e z e r o t h e i n t e r f a c e r e m a i n s p r o m i s c u o u s . Once i t h i t s z e r o
∗ t h e d e v i c e r e v e r t s back t o normal f i l t e r i n g o p e r a t i o n . A n e g a t i v e i n c
∗ v a l u e i s u s e d t o d r o p p r o m i s c u i t y on t h e d e v i c e .
∗/
v o i d d e v _ s e t _ p r o m i s c u i t y ( s t r u c t n e t _ d e v i c e ∗ dev , i n t i n c )
{
u n s i g n e d s h o r t o l d _ f l a g s = dev−> f l a g s ;
4
1 jiffy, 10ms bei den meisten Kernel
83
C.3. Ausgewählte Passagen aus den Kernelsourcen
dev−> f l a g s | = IFF_PROMISC ;
i f ( ( dev−> p r o m i s c u i t y += i n c ) == 0 )
dev−> f l a g s &= ~IFF_PROMISC ;
i f ( dev−> f l a g s ^ o l d _ f l a g s ) {
d e v _ mc _ u p l o ad ( dev ) ;
p r i n t k ( KERN_INFO " d e v i c e %s %s p r o m i s c u o u s mode \ n " ,
dev−>name , ( dev−> f l a g s & IFF_PROMISC ) ? " e n t e r e d " :
" left " );
}
}
Listing C.1: net/core/dev.c
In diesem Abschnitt ist gut zu sehen, wie sich der Kernel merkt, ob er sich im promiscuous mode
befindet oder nicht.
u n s i g n e d s h o r t e t h _ t y p e _ t r a n s ( s t r u c t s k _ b u f f ∗ skb , s t r u c t n e t _ d e v i c e ∗ dev )
{
...
i f ( ∗ e t h −>h _ d e s t &1)
{
i f ( memcmp ( e t h −>h _ d e s t , dev−>b r o a d c a s t , ETH_ALEN) = = 0 )
skb −>p k t _ t y p e =PACKET_BROADCAST ;
else
skb −>p k t _ t y p e =PACKET_MULTICAST ;
}
/∗
∗
∗
∗
∗
∗
∗/
T h i s ALLMULTI c h e c k s h o u l d be r e d u n d a n t by 1 . 4
s o don ’ t f o r g e t t o remove i t .
Seems , you f o r g o t t o remove i t . A l l s i l l y d e v i c e s
s e e m s t o s e t IFF_PROMISC .
e l s e i f ( 1 / ∗ dev−> f l a g s&IFF_PROMISC ∗ / )
{
i f ( memcmp ( e t h −>h _ d e s t , dev−>d e v _ a d d r , ETH_ALEN ) )
skb −>p k t _ t y p e =PACKET_OTHERHOST ;
}
...
Listing C.2: net/ethernet/eth.c
Die Funktion eth_type_trans() wird von vielen Treibern aufgerufen, um einzelne Werte
der sk_buff Struktur abzufüllen.
Das erste if überprüft, ob das erste Byte der Ethernet-Ziel-Adresse ungerade ist, danach wird
geprüft ob diese Adresse der Broadcast-Adresse (FF:FF:FF:FF:FF:FF) entspricht, falls nicht
wird der pkt_type auf PACKET_MULTICAST gesetzt !!!
Falls das erste Byte gerade ist, wird weiter unten noch überprüft, ob die Ethernet-Ziel-Adresse
der eigenen MAC-Adresse entspricht.
i n t a r p _ r c v ( s t r u c t s k _ b u f f ∗ skb , s t r u c t n e t _ d e v i c e ∗ dev , s t r u c t p a c k e t _ t y p e ∗ p t )
{
...
a r p = skb −>nh . a r p h ;
i f ( a r p −> a r _ h l n ! = dev−>a d d r _ l e n | |
dev−> f l a g s & IFF_NOARP | |
skb −>p k t _ t y p e == PACKET_OTHERHOST | |
84
C.3. Ausgewählte Passagen aus den Kernelsourcen
skb −>p k t _ t y p e == PACKET_LOOPBACK | |
a r p −> a r _ p l n ! = 4 )
goto f r e e s k b ;
...
Listing C.3: net/ipv4/arp.c
In der arp_rcv() Funktion wird nur auf PACKET_OTHERHOST geprüft, deshalb funktioniert
der ARP-Test bei L INUX!
/∗
∗ Main IP R e c e i v e r o u t i n e .
∗/
i n t i p _ r c v ( s t r u c t s k _ b u f f ∗ skb , s t r u c t n e t _ d e v i c e ∗ dev , s t r u c t p a c k e t _ t y p e ∗ p t )
{
struct iphdr ∗iph ;
/ ∗ When t h e i n t e r f a c e i s i n p r o m i s c . mode , d r o p a l l t h e c r a p
∗ t h a t i t r e c e i v e s , do n o t t r y t o a n a l y s e i t .
∗/
i f ( skb −>p k t _ t y p e == PACKET_OTHERHOST)
goto drop ;
...
Listing C.4: net/ipv4/ip_input.c
Falls ein Paket vom Typ ETH_P_IP ankommt, wird die Funktion ip_rcv() aufgerufen.
Hier wird auch nur auf PACKET_OTHERHOST geprüft, deshalb funktioniert der ICMP-Test bei
L INUX!
85
D. Glossar
API
ARP
BPF
CSMA/CD
DMA
DNS
DoS
HTTP
ICMP
IP
ISR
LAN
LPF
MAC
MSB
NAPI
OS
pid
RTD
Rx
SAD
SMP
SNMP
TCP
Tx
UDP
UTC
Application Program(ming) Interface
Address Resolution Protocol
Berkeley Packet Filter
Carrier Sense Multiple Access/Collision Detect(ion)
Direct Memory Access
Domain Name System
Denial Of Service
Hyper Text Transfer Protocol
Internet Control Message Protocol
Internet Protocol
Interrupt Service Routine
Local Area Network
L INUX Packet Filter
Media Access Control
Most Significant Bit
New Application Program(ming) Interface
Operating System
Process ID
Round-Trip Delay
Receive
S NIFF A ND D IE
Symmetric Multi-Processor
Simple Network Management Protocol
Transmission Control Protocol
Transmit
User Datagram Protocol
Coordinated Universal Time
86
Literaturverzeichnis
[1] H ELMUT KOPKA: LATEX 2ε Einführung Band 1, A DDISON -W ESLEY Verlag, 3. überarbeitete Auflage, 2000, ISBN 3-8273-1557-3
[2] W. R ICHARD S TEVENS: TCP/IP Illustrated Volume I: The Protocols, A DDISON W ESLEY, 1994, ISBN 3-8266-5042-5
[3] GNU Lesser General Public License
[4]
SOURCE FORGE. NET
[5] A NTI S NIFF, L0pht Heavy Industries, Inc.
[6]
NEPED
[7]
NEPED - LIBNET
[8]
SENTINEL
[9] Design Patterns
[10] Program Library HOWTO
[11] C++ dlopen mini HOWTO
[12] Shared objects for the object disoriented!
[13] B OOST::Thread (Version: 1.31.0-7)
[14] B JARNE S TROUSTRUP: Die C++ Programmiersprache, A DDISON -W ESLEY Verlag, 4.
aktualisierte Auflage, 2000, ISBN 0-8273-1660-X
[15] R AY L ISCHNER: C++ in a Nutshell, O’R EILLY Verlag, May 2003,
ISBN 0-596-00298-X
[16] The Libnet Packet Construction Library (Version: 1.1.2.1-1)
[17] Building packets for dummies and others with libnet
87
Literaturverzeichnis
[18] The Libnet Reference Manual v.01
[19] The Libpcap Library (Version: 0.8.3-4)
[20] Programming with pcap
[21] libConfuse (Version: 2.2-1)
[22] DAIJI S ANAI, Detection of Promiscuous Nodes Using ARP Packets, 2001
[23] M UDGE, Tactics to Discover “Passive” Monitoring Devices
[24] The L INUX Kernel Archives
[25] V INCENT G UFFENS: Path of a packet in the L INUX kernel, 2003
[26] L INUX Network Stack Walkthrough
[27] L INUX 2.6 network stack
[28] The L INUX Socket Filter: Sniffing Bytes over the Network Part I
[29] Inside the L INUX Packet Filter Part II
88
E. The GNU General Public License
Version 2, June 1991
c
Copyright 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies of this license document, but
changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to share and
change it. By contrast, the GNU General Public License is intended to guarantee
your freedom to share and change free software—to make sure the software is free
for all its users. This General Public License applies to most of the Free Software
Foundation’s software and to any other program whose authors commit to using
it. (Some other Free Software Foundation software is covered by the GNU Library
General Public License instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General
Public Licenses are designed to make sure that you have the freedom to distribute
copies of free software (and charge for this service if you wish), that you receive
source code or can get it if you want it, that you can change the software or use
pieces of it in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny
you these rights or to ask you to surrender the rights. These restrictions translate
to certain responsibilities for you if you distribute copies of the software, or if you
modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee,
you must give the recipients all the rights that you have. You must make sure that
they, too, receive or can get the source code. And you must show them these terms
so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you
this license which gives you legal permission to copy, distribute and/or modify the
software.
Also, for each author’s protection and ours, we want to make certain that everyone
understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they
89
have is not the original, so that any problems introduced by others will not reflect
on the original authors’ reputations.
Finally, any free program is threatened constantly by software patents. We wish to
avoid the danger that redistributors of a free program will individually obtain patent
licenses, in effect making the program proprietary. To prevent this, we have made it
clear that any patent must be licensed for everyone’s free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
GNU G ENERAL P UBLIC L ICENSE
T ERMS AND C ONDITIONS F OR C OPYING , D ISTRIBUTION AND
M ODIFICATION
0. This License applies to any program or other work which contains a notice placed by
the copyright holder saying it may be distributed under the terms of this General Public
License. The “Program”, below, refers to any such program or work, and a “work based
on the Program” means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it, either verbatim or with
modifications and/or translated into another language. (Hereinafter, translation is included
without limitation in the term “modification”.) Each licensee is addressed as “you”.
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the
output from the Program is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program). Whether that is true
depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program’s source code as you receive
it, in any medium, provided that you conspicuously and appropriately publish on each
copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices
that refer to this License and to the absence of any warranty; and give any other recipients
of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your
option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a
work based on the Program, and copy and distribute such modifications or work under the
terms of Section 1 above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that you changed
the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in part
contains or is derived from the Program or any part thereof, to be licensed as a
whole at no charge to all third parties under the terms of this License.
c) If the modified program normally reads commands interactively when run, you must
cause it, when started running for such interactive use in the most ordinary way, to
print or display an announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide a warranty) and that
users may redistribute the program under these conditions, and telling the user how
to view a copy of this License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on the Program is
not required to print an announcement.)
These requirements apply to the modified work as a whole. If identifiable sections of that
work are not derived from the Program, and can be reasonably considered independent
and separate works in themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you distribute the same
sections as part of a whole which is a work based on the Program, the distribution of the
whole must be on the terms of this License, whose permissions for other licensees extend
to the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work
written entirely by you; rather, the intent is to exercise the right to control the distribution
of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program
(or with a work based on the Program) on a volume of a storage or distribution medium
does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in object
code or executable form under the terms of Sections 1 and 2 above provided that you also
do one of the following:
a) Accompany it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give any third
party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium customarily used
for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with
such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications
to it. For an executable work, complete source code means all the source code for all
modules it contains, plus any associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a special exception, the
source code distributed need not include anything that is normally distributed (in either
source or binary form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component itself accompanies
the executable.
If distribution of executable or object code is made by offering access to copy from a
designated place, then offering equivalent access to copy the source code from the same
place counts as distribution of the source code, even though third parties are not compelled
to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute
the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not
have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However, nothing
else grants you permission to modify or distribute the Program or its derivative works.
These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate
your acceptance of this License to do so, and all its terms and conditions for copying,
distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient
automatically receives a license from the original licensor to copy, distribute or modify
the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients’ exercise of the rights granted herein. You are not responsible
for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any
other reason (not limited to patent issues), conditions are imposed on you (whether by
court order, agreement or otherwise) that contradict the conditions of this License, they
do not excuse you from the conditions of this License. If you cannot distribute so as to
satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if
a patent license would not permit royalty-free redistribution of the Program by all those
who receive copies directly or indirectly through you, then the only way you could satisfy
both it and this License would be to refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is
intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other property
right claims or to contest validity of any such claims; this section has the sole purpose
of protecting the integrity of the free software distribution system, which is implemented
by public license practices. Many people have made generous contributions to the wide
range of software distributed through that system in reliance on consistent application
of that system; it is up to the author/donor to decide if he or she is willing to distribute
software through any other system and a licensee cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of
the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program
under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded.
In such case, this License incorporates the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General
Public License from time to time. Such new versions will be similar in spirit to the present
version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version
number of this License which applies to it and “any later version”, you have the option of
following the terms and conditions either of that version or of any later version published
by the Free Software Foundation. If the Program does not specify a version number of this
License, you may choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distribution
conditions are different, write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free Software Foundation;
we sometimes make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and of promoting the
sharing and reuse of software generally.
N O WARRANTY
11. B ECAUSE
THE PROGRAM IS LICENSED FREE OF CHARGE , THERE IS NO WARRAN -
TY FOR THE PROGRAM , TO THE EXTENT PERMITTED BY APPLICABLE LAW.
E XCEPT
WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND / OR OTHER
PARTIES PROVIDE THE PROGRAM “AS IS ” WITHOUT WARRANTY OF ANY KIND , EITHER EXPRESSED OR IMPLIED , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WAR RANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .
T HE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
YOU .
S HOULD
THE PROGRAM PROVE DEFECTIVE , YOU ASSUME THE COST OF ALL
NECESSARY SERVICING , REPAIR OR CORRECTION .
12. I N
NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER , OR ANY OTHER PARTY WHO MAY MODIFY AND / OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE , BE LIABLE TO YOU FOR DA MAGES , INCLUDING ANY GENERAL , SPECIAL , INCIDENTAL OR CONSEQUENTIAL DA MAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM ( INCLUDING
BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO
OPERATE WITH ANY OTHER PROGRAMS ), EVEN IF SUCH HOLDER OR OTHER PARTY
HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES .
E ND OF T ERMS AND C ONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the
best way to achieve this is to make it free software which everyone can redistribute and change
under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of
each source file to most effectively convey the exclusion of warranty; and each file should have
at least the “copyright” line and a pointer to where the full notice is found.
<one line to give the program’s name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an interactive
mode:
Gnomovision version 69, Copyright (C) <year> <name of author>
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type ‘show
w’.
This is free software, and you are welcome to redistribute it under certain conditions; type ‘show c’ for details.
The hypothetical commands show w and show c should show the appropriate parts of the
General Public License. Of course, the commands you use may be called something other than
show w and show c; they could even be mouse-clicks or menu items—whatever suits your
program.
You should also get your employer (if you work as a programmer) or your school, if any, to sign
a “copyright disclaimer” for the program, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
‘Gnomovision’ (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking
proprietary applications with the library. If this is what you want to do, use the GNU Library
General Public License instead of this License.
F. Code
Der hier abgedruckte Code unterliegt den Bestimmungen der GPL welche im Anhang E beigefügt ist.
97
F.1. Makefile
F.1. Makefile
# ##############################################################################
# M a k e f i l e − Sad
#
# Author :
Ranko V e s e l i n o v i c <v e s e l r a n @ z h w i n . ch>
#
Halm R e u s s e r <r e u s s h a l @ z h w i n . ch>
# Date :
05.10.2004
#
#−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
#
# C o p y r i g h t (C) 2004
Ranko V e s e l i n o v i c <v e s e l r a n @ z h w i n . ch>
#
Halm R e u s s e r <r e u s s h a l @ z h w i n . ch>
#
# T h i s program i s f r e e s o f t w a r e ; you can r e d i s t r i b u t e i t and / o r
# m o d i f y i t u n d e r t h e t e r m s o f t h e GNU G e n e r a l P u b l i c L i c e n s e
# a s p u b l i s h e d by t h e F r e e S o f t w a r e F o u n d a t i o n ; e i t h e r v e r s i o n 2
# o f t h e L i c e n s e , o r ( a t y o u r o p t i o n ) any l a t e r v e r s i o n .
#
# T h i s program i s d i s t r i b u t e d i n t h e hope t h a t i t w i l l be u s e f u l ,
# b u t WITHOUT ANY WARRANTY ; w i t h o u t e v e n t h e i m p l i e d w a r r a n t y o f
# MERCHANTABILITY o r FITNESS FOR A PARTICULAR PURPOSE . S e e t h e
# GNU G e n e r a l P u b l i c L i c e n s e f o r more d e t a i l s .
#
# You s h o u l d h a v e r e c e i v e d a c o p y o f t h e GNU G e n e r a l P u b l i c L i c e n s e
# a l o n g w i t h t h i s program ; i f n o t , w r i t e t o t h e F r e e S o f t w a r e
# F o u n d a t i o n , I n c . , 59 Temple P l a c e − S u i t e 3 3 0 , B o s t o n , MA 02111 −1307 , USA .
# ##############################################################################
SHELL = / b i n / b a s h
CXX = g++
CXXFLAGS = −g −W −Wall #−O3
LIBFLAGS = −f P I C −s h a r e d −Wl,−soname ,
TRDFLAGS = −D_REENTRANT
LDFLAGS = − l d l −l b o o s t _ t h r e a d − l n e t −l p c a p −l c o n f u s e −l c
VPATH = . / p l u g i n s
# c o n t a i n s t h e source−f i l e s i n t h e sad / s r c d i r e c t o r y
f r a m e w o r k = $ ( w i l d c a r d ∗ . cpp )
# c o n t a i n s t h e source−f i l e s i n t h e sad / s r c / p l u g i n d i r e c t o r y
p l u g i n s = $ ( n o t d i r $ ( w i l d c a r d $ (VPATH ) / ∗ . cpp ) )
# c o n t a i n s a l l source−f i l e s from sad / s r c /∗
s o u r c e s = $ ( framework ) $ ( p l u g i n s )
p o b j e c t s = $ ( p a t s u b s t %. cpp , % . o , $ ( p l u g i n s ) )
f o b j e c t s = $ ( p a t s u b s t %. cpp , % . o , $ ( f r a m e w o r k ) )
fmodules = S c a n S t r a t e g y . o captureT . o i n j e c t i o n T . o optionMgr . o latencyCT . o
. PHONY: c l e a n i n s t a l l
a l l : $ ( p o b j e c t s ) $ ( f o b j e c t s ) sad
$( pobjects ): $( plugins ) $( fobjects )
$ (CXX) $ (CXXFLAGS) $ ( LIBFLAGS ) l i b $ ∗ . s o . 0 −o l i b $ ∗ . s o . 0 . 0 $ (VPATH ) / $ ∗ . cpp \
$ ( f m o d u l e s ) $ (LDFLAGS)
$ ( f o b j e c t s ) : $ ( framework )
$ (CXX) −c $ (CXXFLAGS) $ (TRDFLAGS) $ ∗ . cpp
98
F.1. Makefile
sad : $ ( f o b j e c t s )
$ (CXX) $ (CXXFLAGS) $ (TRDFLAGS) −o $@ $ ( f o b j e c t s ) $ (LDFLAGS)
install :
i n s t a l l −g r o o t −o r o o t −m 500 s a d / u s r / l o c a l / s b i n
i n s t a l l −d −g r o o t −o r o o t −m 700 / u s r / l o c a l / l i b / s a d /
i n s t a l l −g r o o t −o r o o t −m 700 $ ( w i l d c a r d ∗ . s o . ∗ ) / u s r / l o c a l / l i b / s a d /
/ s b i n / l d c o n f i g −n / u s r / l o c a l / l i b / s a d /
i n s t a l l −d −g r o o t −o r o o t −m 700 / e t c / s a d /
i n s t a l l −g r o o t −o r o o t −m 600 s a d . c o n f / e t c / s a d /
i n s t a l l −d −g r o o t −o r o o t −m 755 / u s r / l o c a l / i n c l u d e / s a d
i n s t a l l −g r o o t −o r o o t −m 644 $ ( w i l d c a r d ∗ . hpp ) / u s r / l o c a l / i n c l u d e / s a d /
uninstall :
rm −f
rm − r f
rm − r f
rm − r f
/ usr /
/ usr
/ usr
/ etc
l o c a l / sbin / sad
/ l o c a l / l i b / sad
/ l o c a l / i n c l u d e / sad
/ sad
clean :
rm − r f ∗ . o s a d ∗ . s o ∗
99
F.2. Framework
F.2. Framework
F.2.1. optionMgr.hpp
# i f n d e f OPTIONMGR_HPP
# d e f i n e OPTIONMGR_HPP
# i n c l u d e " o p t i o n . hpp "
# i n c l u d e <map>
# include < string >
u s i n g namespace s t d ;
/ ∗ ∗∗
∗ T h i s Class i s r e a l i s e d as a S i n g l e t o n g
∗∗ ∗ /
c l a s s OptionMgr
{
private :
OptionMgr ( ) ;
s t a t i c OptionMgr ∗ i n s t a n c e ;
multimap < s t r i n g , O p t i o n > o p t i o n s ;
public :
s t a t i c OptionMgr ∗ g e t I n s t a n c e ( v o i d ) ;
~ OptionMgr ( v o i d ) ;
void addOption ( s t r i n g , Option ) ;
c o n s t multimap < s t r i n g , O p t i o n > ∗ c o n s t g e t O p t i o n s ( v o i d ) c o n s t ;
friend class console ;
};
# endif
F.2.2. optionMgr.cpp
# i f n d e f OPTIONMGR_HPP
# d e f i n e OPTIONMGR_HPP
# i n c l u d e " o p t i o n . hpp "
# i n c l u d e <map>
# include < string >
u s i n g namespace s t d ;
/ ∗ ∗∗
∗ T h i s Class i s r e a l i s e d as a S i n g l e t o n g
∗∗ ∗ /
c l a s s OptionMgr
{
private :
OptionMgr ( ) ;
s t a t i c OptionMgr ∗ i n s t a n c e ;
multimap < s t r i n g , O p t i o n > o p t i o n s ;
public :
s t a t i c OptionMgr ∗ g e t I n s t a n c e ( v o i d ) ;
~ OptionMgr ( v o i d ) ;
void addOption ( s t r i n g , Option ) ;
c o n s t multimap < s t r i n g , O p t i o n > ∗ c o n s t g e t O p t i o n s ( v o i d ) c o n s t ;
100
F.2. Framework
friend class console ;
};
# endif
F.2.3. Option
# i f n d e f OPTION_HPP
# d e f i n e OPTION_HPP
# include < string >
# i n c l u d e <map>
u s i n g namespace s t d ;
enum a r g {NO_ARG, REQ_ARG} ;
s t r u c t Option
{
string sopt ;
string lopt ;
arg has_arg ;
s t r i n g argument ;
string description ;
/ / S h o r t O p t i o n ; e . g . −h
/ / Long O p t i o n ; e . g . −−h e l p
/ / D e f a u l t V a l u e o f Argument ; e . g . 1 2 7 . 0 . 0 . 1
/ / D e s c r i p t i o n o f O p t i o n ; e . g . p r i n t s o u t t h e Help
Option ( s t r i n g s , s t r i n g l , arg at , s t r i n g a , s t r i n g d )
: s o p t ( s ) , l o p t ( l ) , h a s _ a r g ( a t ) , a r g u m e n t ( a ) , d e s c r i p t i o n ( d ) {}
};
# endif
101
F.2. Framework
F.2.4. cfgParser.hpp
# i f n d e f CFGPARSER_HPP
# d e f i n e CFGPARSER_HPP
# include < string >
# include <vector >
# i n c l u d e <map>
u s i n g namespace s t d ;
e x t e r n "C"
{
# i n c l u d e < c o n f u s e . h>
}
/ ∗ ∗∗
∗ T h i s Class i s r e a l i s e d as a S i n g l e t o n g
∗∗ ∗ /
class cfgParser
{
private :
cfgParser ( ) ;
static cfgParser ∗instance ;
s t a t i c cfg_opt_t sad_opts [ ] ;
static cfg_opt_t opts [ ] ;
static string cfgfile_ ;
struct cfgval
{
s t r i n g path ;
float trust ;
cfg_bool_t evaluation ;
};
map< s t r i n g , c f g v a l > p l u g i n ;
public :
s t a t i c c f g P a r s e r ∗ g e t I n s t a n c e ( void ) ;
~ c f g P a r s e r ( void ) ;
vector < s t r i n g > g e t P a t h ( void ) ;
vector < s t r i n g > getPlugInName ( void ) ;
float getTrust ( string );
bool g e t E v a l u a t i o n ( s t r i n g ) ;
};
# endif
F.2.5. cfgParser.cpp
# i n c l u d e " c f g P a r s e r . hpp "
# include < string >
# include <vector >
# i n c l u d e <map>
u s i n g namespace s t d ;
e x t e r n "C"
{
# i n c l u d e < c o n f u s e . h>
}
102
F.2. Framework
cfgParser ∗ cfgParser : : instance = 0;
s t r i n g c f g P a r s e r : : c f g f i l e _ = " / e t c / sad / sad . conf " ;
c f g P a r s e r ∗ c f g P a r s e r : : g e t I n s t a n c e ( void )
{
i f ( i n s t a n c e == 0 )
i n s t a n c e = new c f g P a r s e r ;
return i n s t a n c e ;
}
cfg_opt_t cfgParser : : sad_opts [] =
{
CFG_STR ( " p a t h " , 0 , CFGF_NONE ) ,
CFG_FLOAT ( " t r u s t " , 0 , CFGF_NONE ) ,
CFG_BOOL( " e v a l u a t i o n " , c f g _ t r u e , CFGF_NONE ) ,
CFG_END ( )
};
cfg_opt_t cfgParser : : opts [] =
{
CFG_SEC ( " p l u g i n " , s a d _ o p t s , CFGF_TITLE | CFGF_MULTI ) ,
CFG_END ( )
};
cfgParser : : cfgParser ()
{
c f g _ t ∗ cfg , ∗ c f g _ s a d ;
c f g v a l tmp ;
c f g = c f g _ i n i t ( o p t s , CFGF_NONE ) ;
c f g _ p a r s e ( cfg , c f g f i l e _ . c _ s t r ( ) ) ;
f o r ( u n s i g n e d i n t i = 0 ; i < c f g _ s i z e ( c f g , " p l u g i n " ) ; i ++)
{
c f g _ s a d = c f g _ g e t n s e c ( cfg , " p l u g i n " , i ) ;
tmp . p a t h = c f g _ g e t s t r ( c f g _ s a d , " p a t h " ) ;
tmp . t r u s t = c f g _ g e t f l o a t ( c f g _ s a d , " t r u s t " ) ;
tmp . e v a l u a t i o n = c f g _ g e t b o o l ( c f g _ s a d , " e v a l u a t i o n " ) ;
p l u g i n [ c f g _ t i t l e ( c f g _ s a d ) ] = tmp ;
}
}
c f g P a r s e r : : ~ c f g P a r s e r ( void )
{
delete instance ;
}
/ ∗ ∗∗
∗ paths of plugins
∗∗ ∗ /
vector < s t r i n g > c f g P a r s e r : : g e t P a t h ( void )
{
vector < string > path ;
f o r ( map< s t r i n g , c f g v a l > : : c o n s t _ i t e r a t o r
i t e r ! = p l u g i n . end ( ) ; ++ i t e r )
{
p a t h . p u s h _ b a c k ( i t e r −>s e c o n d . p a t h ) ;
}
return path ;
}
103
i t e r = plugin . begin ( ) ;
F.2. Framework
/ ∗ ∗∗
∗ r e t u r n s v e c t o r w i t h t h e P l u g i n −Names
∗∗ ∗ /
vector < s t r i n g > c f g P a r s e r : : getPlugInName ( void )
{
v e c t o r < s t r i n g > name ;
f o r ( map< s t r i n g , c f g v a l > : : c o n s t _ i t e r a t o r i t e r = p l u g i n . b e g i n ( ) ;
i t e r ! = p l u g i n . end ( ) ; ++ i t e r )
{
name . p u s h _ b a c k ( i t e r −> f i r s t ) ;
}
r e t u r n name ;
}
f l o a t c f g P a r s e r : : g e t T r u s t ( s t r i n g pname )
{
r e t u r n p l u g i n [ pname ] . t r u s t ;
}
b o o l c f g P a r s e r : : g e t E v a l u a t i o n ( s t r i n g pname )
{
r e t u r n p l u g i n [ pname ] . e v a l u a t i o n ;
}
104
F.2. Framework
F.2.6. console.hpp
# i f n d e f CONSOLE_HPP
# d e f i n e CONSOLE_HPP
# i n c l u d e " o p t i o n M g r . hpp "
# include < string >
# include <vector >
e x t e r n "C"
{
# i n c l u d e < g e t o p t . h>
}
class console
{
private :
OptionMgr ∗ o p t s _ ;
s t r i n g whichPlugIn ( s t r i n g &);
public :
console ( ) ;
~ console ( void ) ;
i n t c m d p a r s e ( i n t , char ∗ ∗ ) ; / / r e t u r n s 0 on s u c c e s s
};
# endif
F.2.7. console.cpp
# include
# include
# include
# include
" c o n s o l e . hpp "
" o p t i o n M g r . hpp "
" o p t i o n . hpp "
" sadEx . hpp "
# include
# include
# include
# include
<map>
<string >
<vector >
<cctype >
u s i n g namespace s t d ;
console : : console ()
{
o p t s _ = OptionMgr : : g e t I n s t a n c e ( ) ;
}
console : : ~ console ( void )
{
}
s t r i n g console : : whichPlugIn ( s t r i n g &s t r )
{
s t r i n g tmp ;
f o r ( multimap < s t r i n g , O p t i o n > : : i t e r a t o r m i t e r = o p t s _ −> o p t i o n s . b e g i n ( ) ;
m i t e r ! = o p t s _ −> o p t i o n s . end ( ) ; ++ m i t e r )
{
i f ( m i t e r −>s e c o n d . s o p t == s t r | | m i t e r −>s e c o n d . l o p t == s t r )
{
tmp = m i t e r −>s e c o n d . l o p t . s u b s t r ( 2 , m i t e r −>s e c o n d . l o p t . s i z e ( ) − 2 ) ;
f o r ( u n s i g n e d i n t i = 0 ; i < tmp . l e n g t h ( ) ; i ++)
105
F.2. Framework
tmp [ i ] = t o u p p e r ( tmp [ i ] ) ;
i f ( tmp == m i t e r −> f i r s t )
r e t u r n m i t e r −> f i r s t ;
}
}
r e t u r n "SAD" ;
}
i n t c o n s o l e : : c m d p a r s e ( i n t a r g c , char ∗∗ a r g v )
{
int i = 1;
bool t i p s e t = f a l s e ;
string s , plugin ;
while ( i < argc )
{
/ / 1 . Which P l u g i n ? I f no P l u g I n −> t h r o w e x c e p t i o n ! ! !
s = argv [ i ] ;
plugin = whichPlugIn ( s ) ;
i f ( p l u g i n ! = "SAD" )
{
/ / Set PlugIn to e x p l i c i t
f o r ( multimap < s t r i n g , O p t i o n > : : i t e r a t o r m i t e r =
o p t s _ −> o p t i o n s . l o w e r _ b o u n d ( p l u g i n ) ;
m i t e r ! = o p t s _ −> o p t i o n s . u p p e r _ b o u n d ( p l u g i n ) ; ++ m i t e r )
{
i f ( s == m i t e r −>s e c o n d . s o p t | | s == m i t e r −>s e c o n d . l o p t )
m i t e r −>s e c o n d . a r g u m e n t = " e x p l i c i t " ;
}
/ / 2. get next option
i f (++ i >= a r g c )
break ;
s = argv [ i ] ;
}
/ / 3 . go i n t o P l u g I n
f o r ( multimap < s t r i n g , O p t i o n > : : i t e r a t o r m i t e r =
o p t s _ −> o p t i o n s . l o w e r _ b o u n d ( p l u g i n ) ;
m i t e r ! = o p t s _ −> o p t i o n s . u p p e r _ b o u n d ( p l u g i n ) ; ++ m i t e r )
{
/ / 4. option of PlugIn ?
i f ( s == m i t e r −>s e c o n d . s o p t | | s == m i t e r −>s e c o n d . l o p t &&
m i t e r −>s e c o n d . s o p t ! = "− t i p " )
{
/ / 5 . t r u e −> g e t & a s s i g n V a l u e
i f ( m i t e r −>s e c o n d . h a s _ a r g == REQ_ARG)
{
i f (++ i >= a r g c )
throw C o n s o l e E x ( s + " u s a g e ! " ) ;
s = argv [ i ] ;
i f ( s [ 0 ] == ’− ’ )
throw C o n s o l e E x ( s + " no v a l i d a r g u m e n t " ) ;
m i t e r −>s e c o n d . a r g u m e n t = s ;
i f (++ i >= a r g c )
{
if ( tipset )
return 0; / / e x i t success
else
throw C o n s o l e E x ( " no I P " ) ;
106
F.2. Framework
}
s = argv [ i ] ;
m i t e r = o p t s _ −> o p t i o n s . l o w e r _ b o u n d ( p l u g i n ) ;
continue ;
}
e l s e i f ( m i t e r −>s e c o n d . h a s _ a r g == NO_ARG)
{
m i t e r −>s e c o n d . a r g u m e n t = " t r u e " ;
i f (++ i >= a r g c )
{
if ( tipset )
return 0; / / e x i t success
else
throw C o n s o l e E x ( " no I P " ) ;
}
s = argv [ i ] ;
m i t e r = o p t s _ −> o p t i o n s . l o w e r _ b o u n d ( p l u g i n ) ;
continue ;
}
}
e l s e i f ( p l u g i n == "SAD" && m i t e r −>s e c o n d . s o p t == "− t i p " && ! t i p s e t )
{
i f ( a r g v [ a r g c − 1 ] [ 0 ] == ’− ’ )
throw C o n s o l e E x ( s + " no I P " ) ;
else
m i t e r −>s e c o n d . a r g u m e n t = a r g v [ a r g c −1];
t i p s e t = true ;
−−a r g c ;
continue ;
}
}
i f ( p l u g i n == "SAD" && i < a r g c )
throw C o n s o l e E x ( " no s u c h a r g u m e t n " ) ;
}
return 0;
}
107
F.2. Framework
F.2.8. sadThread.hpp
# i f n d e f SADTHREAD_HPP
# d e f i n e SADTHREAD_HPP
c l a s s SadThread
{
protected :
S a d T h r e a d ( ) {}
v i r t u a l ~ S a d T h r e a d ( ) {}
v i r t u a l void operator ( ) ( ) {};
};
# endif
F.2.9. captureT.hpp
# i f n d e f CAPTURET_HPP
# d e f i n e CAPTURET_HPP
# i n c l u d e " s a d T h r e a d . hpp "
# include < string >
# include <vector >
e x t e r n "C"
{
# i n c l u d e < p c a p . h>
# i n c l u d e <pcap−b p f . h>
}
u s i n g namespace s t d ;
c l a s s CaptureT : public SadThread
{
protected :
pcap_t ∗handle ;
char e r r b u f [ PCAP_ERRBUF_SIZE ] ;
s t r u c t bpf_program f i l t e r ;
/ / p c a p _ d u m p e r _ t ∗dump ;
int sleep ;
int max_attempts ;
int finish ;
i n t ∗ examines ;
s t a t i c c o n s t i n t PSIZE = 6 5 5 3 5 ;
s t a t i c c o n s t i n t PROMISC = 1 ;
s t a t i c c o n s t i n t NONBLOCK_TRUE = 1 ;
public :
C a p t u r e T ( char ∗ , s t r i n g , i n t
/∗ Device :
∗ BPF F i l t e r S t r i n g :
∗ Z e i t i n ms :
∗
∗ Anzahl Versuche :
∗
∗ VorzeitigerAbbruch :
∗
∗ üRckgabewert :
∗/
v i r t u a l ~CaptureT ( ) ;
, int , int , i n t &);
zB " e t h 0 "
man tcpdump
Z e i t , d i e nach e i n e m e r f o l g l o s e n p c a p _ n e x t
b i s zum ä n c h s t e n V e r s u c h g e w a r t e t w i r d .
Wird f o r t l a u f e n d d e k r e m e n t i e r t .
V e r s u c h e = 0 −−> Abbruch
Nachdem d i e s A n z a h l P a k e t e g e f a n g e n wurde −−>
V o r z e i t i g e r Abbruch
Anzahl gefangener Pakete
108
F.2. Framework
v i r t u a l void operator ( ) ( ) ;
};
# endif
F.2.10. captureT.cpp
# i n c l u d e " c a p t u r e T . hpp "
# i n c l u d e " sadEx . hpp "
# i n c l u d e < b o o s t / t h r e a d / t h r e a d . hpp >
# i n c l u d e < b o o s t / t h r e a d / x t i m e . hpp >
# include <vector >
# include <iostream >
e x t e r n "C"
{
# i n c l u d e < p c a p . h>
# i n c l u d e <pcap−b p f . h>
# i n c l u d e < s y s / t i m e . h>
# i n c l u d e < t i m e . h>
}
u s i n g namespace s t d ;
C a p t u r e T : : C a p t u r e T ( char ∗ dev , s t r i n g u s e r _ f i l t e r , i n t ms , i n t a t t e m p t s ,
i n t f i n , i n t &ex )
: s l e e p ( ms ) , m a x _ a t t e m p t s ( a t t e m p t s ) , f i n i s h ( f i n ) , e x a m i n e s (& ex )
{
i f ( ! ( h a n d l e = p c a p _ o p e n _ l i v e ( dev , C a p t u r e T : : PSIZE , C a p t u r e T : : PROMISC , 0 , e r r b u f ) ) )
throw L i b p c a p E x ( e r r b u f ) ;
i f ( p c a p _ c o m p i l e ( h a n d l e , & f i l t e r , c o n s t _ c a s t < char ∗ >( u s e r _ f i l t e r . c _ s t r ( ) ) , 0 , 0 )
< 0)
throw L i b p c a p E x ( p c a p _ g e t e r r ( h a n d l e ) ) ;
i f ( p c a p _ s e t f i l t e r ( handle , &f i l t e r ) < 0)
throw L i b p c a p E x ( p c a p _ g e t e r r ( h a n d l e ) ) ;
//
p c a p _ f r e e c o d e (& f i l t e r ) ; FIXME
/∗ s e t nonblocking ∗/
i f ( p c a p _ s e t n o n b l o c k ( h a n d l e , C a p t u r e T : : NONBLOCK_TRUE, e r r b u f ) < 0 )
throw L i b p c a p E x ( e r r b u f ) ;
//
//
}
i f ( ( dump = pcap_dump_open ( h a n d l e , " − " ) ) == NULL )
throw LibpcapEx ( p c a p _ g e t e r r ( handle ) ) ;
CaptureT : : ~ CaptureT ( )
{
/∗ Destruktor ∗/
i f ( ! handle )
{
pcap_close ( handle ) ;
handle = 0;
}
//
}
p c a p _ d u m p _ c l o s e ( dump ) ;
109
F.2. Framework
void CaptureT : : operator ( ) ( )
{
struct pcap_pkthdr header ;
boost : : xtime xt ;
c o n s t u _ c h a r ∗p ;
//
//
//
w h i l e ( m a x _ a t t e m p t s && f i n i s h )
{
i f ( ( p = p c a p _ n e x t ( h a n d l e , &h e a d e r ) ) ! = NULL)
{
pcap_dump ( ( u _ c h a r ∗ ) dump , &h e a d e r , p ) ;
i f ( p c a p _ d u m p _ f l u s h ( dump ) < 0 )
throw LibpcapEx ( " pcap_dump_flush " ) ;
−−f i n i s h ;
(∗ examines )++;
}
else
{
−−m a x _ a t t e m p t s ;
if ( sleep )
{
/∗ Sleep ∗/
i f ( b o o s t : : x t i m e _ g e t (& x t , b o o s t : : TIME_UTC ) ! = b o o s t : : TIME_UTC )
throw BoostEx ( " x t i m e _ g e t " ) ;
x t . n s e c += ( s l e e p ∗ 1 0 0 0 ∗ 1 0 0 0 ) ;
boost : : thread : : sleep ( xt ) ;
}
}
}
}
110
F.2. Framework
F.2.11. injectionT.hpp
# i f n d e f INJECTIONT_HPP
# d e f i n e INJECTIONT_HPP
# i n c l u d e " s a d T h r e a d . hpp "
# include < string >
# include < l i s t >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
# i n c l u d e < s y s / t i m e . h>
# i n c l u d e < t i m e . h>
}
u s i n g namespace s t d ;
c l a s s I n j e c t i o n T : public SadThread
{
private :
l i s t < l i b n e t _ t ∗> p a c k e t s ;
int sleep ;
public :
InjectionT ();
InjectionT ( int );
~ InjectionT () {};
void addPacket ( l i b n e t _ t ∗ ) ;
v i r t u a l void operator ( ) ( ) ;
};
# endif
F.2.12. injectionT.cpp
# i n c l u d e " sadEx . hpp "
# i n c l u d e " i n j e c t i o n T . hpp "
# i n c l u d e < b o o s t / t h r e a d / t h r e a d . hpp >
# i n c l u d e < b o o s t / t h r e a d / x t i m e . hpp >
# include <iostream >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
# i n c l u d e < s y s / t i m e . h>
# i n c l u d e < t i m e . h>
}
u s i n g namespace s t d ;
InjectionT : : InjectionT ( ) : sleep (0)
{
/∗ Konstruktor ∗/
}
InjectionT : : InjectionT ( int s ): sleep ( s )
{
/∗ Konstruktor ∗/
111
F.2. Framework
}
void I n j e c t i o n T : : addPacket ( l i b n e t _ t ∗ packet )
{
p a c k e t s . push_back ( packet ) ;
}
void I n j e c t i o n T : : operator ( ) ( )
{
boost : : xtime xt ;
l i s t < l i b n e t _ t ∗ >:: i t e r a t o r i t e r ;
f o r ( i t e r = p a c k e t s . b e g i n ( ) ; i t e r ! = p a c k e t s . end ( ) ; ++ i t e r )
{
i f ( l i b n e t _ w r i t e (∗ i t e r ) < 0)
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( ∗ i t e r ) ) ;
if ( sleep )
{
/∗ Sleep ∗/
i f ( b o o s t : : x t i m e _ g e t (& x t , b o o s t : : TIME_UTC ) ! = b o o s t : : TIME_UTC )
throw BoostEx ( " x t i m e _ g e t " ) ;
x t . n s e c += ( s l e e p ∗ 1 0 0 0 ∗ 1 0 0 0 ) ;
boost : : thread : : sleep ( xt ) ;
}
l i b n e t _ d i a g _ d u m p _ c o n t e x t (& i t e r −>s e c o n d ) ;
//
}
}
112
F.2. Framework
F.2.13. latencyCT.hpp
# i f n d e f LATENCYCT_HPP
# d e f i n e LATENCYCT_HPP
# i n c l u d e " c a p t u r e T . hpp "
# include < string >
# include <vector >
e x t e r n "C"
{
# i n c l u d e < s y s / t i m e . h>
# i n c l u d e < t i m e . h>
}
u s i n g namespace s t d ;
c l a s s LatencyCT : p u b l i c C a p t u r e T
{
private :
timeval∗ arrive ;
t i m e v a l ∗ send ;
public :
LatencyCT ( char ∗ , s t r i n g , i n t , i n t , i n t & ) ;
/ ∗ D e v i c e zB " e t h 0 "
∗ BPF F i l t e r S t r i n g
∗ Anzahl Versuche , b i s Abgebrochen wird
∗ A n z a h l e r f o l g r e i c h e r C a p t u r e s , s o d a s s v o r z e i t i g e r Abbruch ö m g l i c h i s t
∗ üRckgabewert ü f r Auswertung
∗/
v i r t u a l ~ LatencyCT ( ) ;
void setTimeval ( t i m e v a l ∗ , t i m e v a l ∗ ) ;
v i r t u a l void operator ( ) ( ) ;
};
# endif
F.2.14. latencyCT.cpp
# i n c l u d e " l a t e n c y C T . hpp "
# i n c l u d e " sadEx . hpp "
# i n c l u d e < b o o s t / t h r e a d / t h r e a d . hpp >
# i n c l u d e < b o o s t / t h r e a d / x t i m e . hpp >
# include <vector >
# include <cstring >
# include <iostream >
e x t e r n "C"
{
# include
# include
# include
# include
}
< p c a p . h>
<pcap−b p f . h>
< s y s / t i m e . h>
< t i m e . h>
u s i n g namespace s t d ;
LatencyCT : : LatencyCT ( char ∗ dev , s t r i n g u s e r _ f i l t e r , i n t a t t e m p t s , i n t f i n , i n t &ex )
113
F.2. Framework
: C a p t u r e T ( dev , u s e r _ f i l t e r , 0 , a t t e m p t s , f i n , ex )
{
/∗ Konstruktor ∗/
}
LatencyCT : : ~ LatencyCT ( )
{
/∗ Destruktor ∗/
}
v o i d LatencyCT : : s e t T i m e v a l ( t i m e v a l ∗ s , t i m e v a l ∗ a )
{
send = s ;
arrive = a ;
}
v o i d LatencyCT : : o p e r a t o r ( ) ( )
{
struct pcap_pkthdr header ;
c o n s t u _ c h a r ∗p ;
unsigned short seq = 0 ;
u n s i g n e d char t y p e = 0 ;
w h i l e ( m a x _ a t t e m p t s && f i n i s h )
{
i f ( ( p = p c a p _ n e x t ( h a n d l e , &h e a d e r ) ) ! = NULL)
{
/ ∗ g e t s e q u e n c e number ∗ /
s e q = ∗ ( p + 4 0 ) ; s e q <<= 8 ; s e q | = ∗ ( p + 4 1 ) ;
/ ∗ g e t ICMP Echo t y p e ∗ /
type = ∗( p +34);
i f ( t y p e == 8 )
/∗ request ∗/
memcpy ( ( v o i d ∗)& s e n d [ s e q ] , ( v o i d ∗)& h e a d e r . t s , s i z e o f ( t i m e v a l ) ) ;
e l s e i f ( t y p e == 0 ) / ∗ r e p l y ∗ /
memcpy ( ( v o i d ∗)& a r r i v e [ s e q ] , ( v o i d ∗)& h e a d e r . t s , s i z e o f ( t i m e v a l ) ) ;
−−f i n i s h ;
(∗ examines )++;
}
else
{
−−m a x _ a t t e m p t s ;
}
}
}
114
F.2. Framework
F.2.15. ScanStrategy.hpp
# i f n d e f SCANSTRATEGY_HPP
# d e f i n e SCANSTRATEGY_HPP
# include
# include
# include
# include
# include
# include
# include
" o p t i o n M g r . hpp "
" o p t i o n . hpp "
" s a d T h r e a d . hpp "
<vector >
<deque >
<string >
<sstream >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
}
class ScanStrategy
{
private :
deque < S a d T h r e a d ∗> t h r e a d s ;
protected :
s t r i n g name ;
OptionMgr ∗ o p t m g r ;
/∗ Global Val ∗/
bool verbose ;
int loop ;
char ∗ d e v i c e ;
u_int32_t ip_src , ip_dst ;
/∗ Libnet S t u f f ∗/
libnet_t ∗context ;
char e r r b u f [ LIBNET_ERRBUF_SIZE ] ;
/∗ Libpcap S t u f f ∗/
stringstream f i l t e r ;
void addThread ( SadThread &);
void s t a r t T h r e a d s ( ) ;
void pushOpt ( Option ) ;
v i r t u a l void s e t L o c a l V a l ( void ) = 0;
void s e t G l o b a l V a l ( void ) ;
s t r i n g getUnique ( string , i n t ) ;
s t r i n g mac2string ( u_int8_t ∗);
//
public :
S c a n S t r a t e g y ( s t r i n g , OptionMgr ∗ ) ;
virtual ~ScanStrategy ( ) ;
void usage ( ) const ;
v i r t u a l double scan ( void ) = 0 ;
};
/∗ Class Factories ∗/
t y p e d e f S c a n S t r a t e g y ∗ c r e a t e S S _ t ( c o n s t char ∗ , OptionMgr ∗ ) ;
typedef void d e s t r o y S S _ t ( S c a n S t r a t e g y ∗ ) ;
# endif
115
F.2. Framework
F.2.16. ScanStrategy.cpp
# include
# include
# include
# include
# include
# include
# include
# include
" S c a n S t r a t e g y . hpp "
" s a d T h r e a d . hpp "
" i n j e c t i o n T . hpp "
" c a p t u r e T . hpp "
" sadEx . hpp "
" o p t i o n M g r . hpp "
" o p t i o n . hpp "
" l a t e n c y C T . hpp "
# include
# include
# include
# include
# include
# include
# include
# include
# include
<iostream >
<iomanip >
<sstream >
<vector >
<deque >
<map>
<string >
< b o o s t / t h r e a d / e x c e p t i o n s . hpp >
< b o o s t / t h r e a d / t h r e a d . hpp >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
}
u s i n g namespace s t d ;
S c a n S t r a t e g y : : S c a n S t r a t e g y ( s t r i n g n , OptionMgr ∗ OptionMgr_ ) :
name ( n ) , o p t m g r ( OptionMgr_ )
{
}
ScanStrategy ::~ ScanStrategy ()
{
/∗ Destruktor ∗/
}
v o i d S c a n S t r a t e g y : : a d d T h r e a d ( S a d T h r e a d &t )
{
i f ( dynamic_cast < C a p t u r e T ∗>(& t ) )
t h r e a d s . p u s h _ f r o n t (& t ) ;
e l s e i f ( dynamic_cast < I n j e c t i o n T ∗>(& t ) )
t h r e a d s . p u s h _ b a c k (& t ) ;
}
void S c a n S t r a t e g y : : s t a r t T h r e a d s ( )
{
try
{
boost : : thread_group threadg ;
deque < S a d T h r e a d ∗ > : : i t e r a t o r d i ;
f o r ( d i = t h r e a d s . b e g i n ( ) ; d i ! = t h r e a d s . end ( ) ; ++ d i )
{
i f ( LatencyCT ∗ c t = dynamic_cast < LatencyCT ∗>
( r e i n t e r p r e t _ c a s t < S a d T h r e a d ∗ >(∗ d i ) ) )
{
t h r e a d g . c r e a t e _ t h r e a d (∗ c t ) ;
}
e l s e i f ( C a p t u r e T ∗ c t = dynamic_cast < C a p t u r e T ∗>
( r e i n t e r p r e t _ c a s t < S a d T h r e a d ∗ >(∗ d i ) ) )
116
F.2. Framework
{
i f ( verbose )
c o u t << " [ S c a n S t r a t e g y ] s t a r t i n g c a p t u r e t h r e a d
t h r e a d g . c r e a t e _ t h r e a d (∗ c t ) ;
. . . " << e n d l ;
}
i f ( I n j e c t i o n T ∗ i t = dynamic_cast < I n j e c t i o n T ∗>
( r e i n t e r p r e t _ c a s t < S a d T h r e a d ∗ >(∗ d i ) ) )
{
i f ( verbose )
c o u t << " [ S c a n S t r a t e g y ] s t a r t i n g i n j e c t i o n t h r e a d
t h r e a d g . c r e a t e _ t h r e a d (∗ i t ) ;
}
. . . " << e n d l ;
}
threadg . join_all ( ) ;
i f ( verbose )
c o u t << " [ S c a n S t r a t e g y ] t h r e a d s j o i n e d
. . . " << e n d l ;
/ ∗ remove a l l t h r e a d s ∗ /
threads . clear ( ) ;
}
c a t c h ( b o o s t : : t h r e a d _ r e s o u r c e _ e r r o r bex )
{
throw BoostEx ( " t h r e a d _ r e s o u r c e _ e r r o r " ) ;
}
}
void S c a n S t r a t e g y : : pushOpt ( Option opt )
{
optmgr −>a d d O p t i o n ( name , o p t ) ;
}
void S c a n S t r a t e g y : : s e t G l o b a l V a l ( void )
{
/∗ Defaults ∗/
device = 0;
verbose = false ;
multimap < s t r i n g , O p t i o n > : : c o n s t _ i t e r a t o r
iter ;
/∗ get the i n t e r f a c e ∗/
f o r ( i t e r = optmgr −>g e t O p t i o n s ()−> l o w e r _ b o u n d ( "SAD" ) ;
i t e r ! = optmgr −>g e t O p t i o n s ()−> u p p e r _ b o u n d ( "SAD" ) ; + + i t e r )
{
i f ( i t e r −>s e c o n d . s o p t == "− i f " )
d e v i c e = c o n s t _ c a s t < char ∗ >( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ;
}
/ ∗ L i b n e t i n i t f o r g e t t i n g some d e f a u l t a d r e s s e s ∗ /
i f ( ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_LINK , d e v i c e , e r r b u f ) ) == 0 )
throw L i b n e t E x ( e r r b u f ) ;
/ ∗ s e t d e f a u l t IP s o u r c e ∗ /
i f ( ( i p _ s r c = l i b n e t _ g e t _ i p a d d r 4 ( c o n t e x t ) ) == ( u _ i n t 3 2 _ t ) ( − 1 ) )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
/ ∗ s e t d e f a u l t IP t a r g e t ∗ /
ip_dst = ip_src ;
117
F.2. Framework
f o r ( i t e r = optmgr −>g e t O p t i o n s ()−> l o w e r _ b o u n d ( "SAD" ) ;
i t e r ! = optmgr −>g e t O p t i o n s ()−> u p p e r _ b o u n d ( "SAD" ) ; + + i t e r )
{
i f ( i t e r −>s e c o n d . s o p t == "−v " && i t e r −>s e c o n d . a r g u m e n t == " t r u e " )
verbose = true ;
i f ( ( i t e r −>s e c o n d . s o p t == "−s i p " ) && ( i t e r −>s e c o n d . a r g u m e n t ! = " " ) )
i f (( ip_src = libnet_name2addr4 ( context ,
c o n s t _ c a s t < char ∗ >( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ,
LIBNET_RESOLVE ) ) == ( u _ i n t 3 2 _ t ) ( − 1 ) )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
i f ( ( i t e r −>s e c o n d . s o p t == "− t i p " ) && ( i t e r −>s e c o n d . a r g u m e n t ! = " " ) )
i f (( ip_dst = libnet_name2addr4 ( context ,
c o n s t _ c a s t < char ∗ >( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ,
LIBNET_RESOLVE ) ) == ( u _ i n t 3 2 _ t ) ( − 1 ) )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
}
/∗ destroy the context ∗/
libnet_destroy ( context );
i f ( verbose )
{
c o u t << " [ S c a n S t r a t e g y ]
c o u t << " [ S c a n S t r a t e g y ]
LIBNET_RESOLVE )
c o u t << " [ S c a n S t r a t e g y ]
LIBNET_RESOLVE )
}
D e v i c e : " << d e v i c e << e n d l ;
S o u r c e−I P : " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ s r c ,
<< e n d l ;
D e s t i n a t i o n −I P : " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ d s t ,
<< e n d l ;
}
void S c a n S t r a t e g y : : usage ( ) const
{
multimap < s t r i n g , O p t i o n > : : c o n s t _ i t e r a t o r i t e r ;
c o u t << name << " O p t i o n s : " << e n d l ;
f o r ( i t e r = optmgr −>g e t O p t i o n s ()−> l o w e r _ b o u n d ( name ) ;
i t e r ! = optmgr −>g e t O p t i o n s ()−> u p p e r _ b o u n d ( name ) ; + + i t e r )
{
c o u t << s e t w ( 2 ) << " " ;
c o u t << l e f t << s e t w ( 8 ) << i t e r −>s e c o n d . s o p t << s e t w ( 2 0 )
<< i t e r −>s e c o n d . l o p t ;
i f ( i t e r −>s e c o n d . h a s _ a r g ! = NO_ARG)
c o u t << " < " ;
c o u t << i t e r −>s e c o n d . d e s c r i p t i o n ;
i f ( i t e r −>s e c o n d . h a s _ a r g ! = NO_ARG)
c o u t << " > " ;
c o u t << e n d l ;
}
c o u t << e n d l ;
}
/∗
s t r i n g ScanStrategy : : getUnique ( s t r i n g s , i n t i )
{
s t a t i c s t r i n g s t r e a m stream ;
stream . s t r ( " " ) ;
s t r e a m << s << s e t w ( 6 ) << s e t f i l l ( ’ 0 ’ ) << i ;
return stream . s t r ( ) ;
}
∗/
118
F.2. Framework
s t r i n g S c a n S t r a t e g y : : m a c 2 s t r i n g ( u _ i n t 8 _ t ∗mac )
{
s t a t i c s t r i n g s t r e a m stream ;
stream . s t r ( " " ) ;
f o r ( i n t i = 0 ; i < 5 ; ++ i )
s t r e a m << s e t w ( 2 ) << s e t f i l l ( ’ 0 ’ ) << hex << ( i n t ) ∗ ( mac ++) << " : " ;
s t r e a m << s e t w ( 2 ) << s e t f i l l ( ’ 0 ’ ) << hex << ( i n t ) ∗ mac ;
return stream . s t r ( ) ;
}
119
F.2. Framework
F.2.17. sadEx.hpp
# i f n d e f SADEX_HPP
# d e f i n e SADEX_HPP
# include < string >
using s t d : : s t r i n g ;
c l a s s SadEx
{
protected :
s t r i n g errorMessage ;
public :
SadEx ( s t r i n g e ) : e r r o r M e s s a g e ( e ) {}
s t r i n g operator ( ) ( ) { return errorMessage ; }
};
c l a s s L i b n e t E x : p u b l i c SadEx
{
public :
L i b n e t E x ( s t r i n g e ) : SadEx ( " L i b n e t : " + e ) {}
};
c l a s s L i b p c a p E x : p u b l i c SadEx
{
public :
L i b p c a p E x ( s t r i n g e ) : SadEx ( " L i b p c a p : " + e ) {}
};
c l a s s BoostEx : p u b l i c SadEx
{
public :
BoostEx ( s t r i n g e ) : SadEx ( " B o o s t : " + e ) {}
};
c l a s s C o n s o l e E x : p u b l i c SadEx
{
public :
C o n s o l e E x ( s t r i n g e ) : SadEx ( " C o n s o l e : " + e ) { }
};
# endif
120
F.2. Framework
F.2.18. sad.cpp
# include
# include
# include
# include
# include
" S c a n S t r a t e g y . hpp "
" s a d . hpp "
" sadEx . hpp "
" c f g P a r s e r . hpp "
" c o n s o l e . hpp "
# include
# include
# include
# include
# include
<iostream >
<map>
<iomanip >
<string >
<vector >
# include < cstdlib >
# include <cstring >
e x t e r n "C" {
# i n c l u d e < d l f c n . h>
# i n c l u d e < u n i s t d . h>
# i n c l u d e < s y s / t y p e s . h>
}
v o i d u s a g e ( OptionMgr ∗ , map< s t r i n g , S c a n S t r a t e g y ∗> & ) ;
d o u b l e g e t R e s u l t ( c f g P a r s e r ∗ , map< s t r i n g , double > & ) ;
u s i n g namespace s t d ;
i n t main ( i n t a r g c , char ∗ a r g v [ ] )
{
map< s t r i n g , S c a n S t r a t e g y ∗> s s t r a t ;
soManager mgr ;
c f g P a r s e r ∗cfgp = c f g P a r s e r : : g e t I n s t a n c e ( ) ;
v e c t o r < s t r i n g > p a t h = c f g p −> g e t P a t h ( ) ;
v e c t o r < s t r i n g > pname ;
c o n s o l e cmd ;
map< s t r i n g , double > s c a n r e s u l t s ;
OptionMgr ∗ optMgr = OptionMgr : : g e t I n s t a n c e ( ) ;
//
//
//
//
//
//
//
//
PlugIns
libmanager
c o n f i g F i l e −P a r s e r
paths of Plugins
PlugInNames
command l i n e p a r s e r
scan r e s u l t s
P o i n t e r t o O p t i o n Manager
optMgr −>a d d O p t i o n ( "SAD" , O p t i o n ( "− i f " , "−− i n t e r f a c e " ,
REQ_ARG, " e t h 0 " , " S c a n n i n g d e v i c e " ) ) ;
optMgr −>a d d O p t i o n ( "SAD" , O p t i o n ( "− t i p " , "−−t a r g e t −i p " ,
REQ_ARG, " " , " t a r g e t I P " ) ) ;
optMgr −>a d d O p t i o n ( "SAD" , O p t i o n ( "−s i p " , "−−s o u r c e −i p " ,
REQ_ARG, " " , " s o u r c e I P " ) ) ;
optMgr −>a d d O p t i o n ( "SAD" , O p t i o n ( "−v " , "−−v e r b o s e " ,
NO_ARG, " f a l s e " , " v e r b o s e o u t p u t " ) ) ;
/ / u s e r == r o o t ?
i f ( g e t u i d ( ) != 0)
{
c e r r << " You must be r o o t t o r u n " << a r g v [ 0 ] << e n d l ;
e x i t ( EXIT_FAILURE ) ;
}
/ / loading PlugIns
int i = 0;
f o r ( v e c t o r < s t r i n g > : : i t e r a t o r i t e r = p a t h . b e g i n ( ) ; i t e r ! = p a t h . end ( ) ; ++ i t e r )
{
/ / PlugInPointer
mgr . p p t r . p u s h _ b a c k ( d l o p e n ( i t e r −> c _ s t r ( ) , RTLD_LAZY ) ) ;
i f ( ! mgr . p p t r [ i ] )
{
121
F.2. Framework
c e r r << " C a n n o t l o a d l i b r a r y " << d l e r r o r ( ) << e n d l ;
e x i t ( EXIT_FAILURE ) ;
}
//
Create− & D e s t r o y F u n c t i o n s
mgr . c f u n c . p u s h _ b a c k ( ( c r e a t e S S _ t ∗ ) dlsym ( mgr . p p t r [ i ] , " c r e a t e " ) ) ;
mgr . d f u n c . p u s h _ b a c k ( ( d e s t r o y S S _ t ∗ ) dlsym ( mgr . p p t r [ i ] , " d e s t r o y " ) ) ;
i f ( ! mgr . c f u n c [ i ] | | ! mgr . d f u n c [ i ] )
{
c e r r << " C a n n n o t l o a d s y m b o l s [ " << ∗ i t e r << " ] : " << d l e r r o r ( ) << e n d l ;
}
++ i ;
}
/ / creating Objects
pname = c f g p −>g e t P l u g I n N a m e ( ) ;
i = 0;
f o r ( v e c t o r < c r e a t e S S _ t ∗ > : : c o n s t _ i t e r a t o r i t e r = mgr . c f u n c . b e g i n ( ) ;
i t e r ! = mgr . c f u n c . end ( ) ; ++ i t e r )
{
s s t r a t [ pname [ i ] ] = ( ( ∗ i t e r ) ( pname [ i ] . c _ s t r ( ) , optMgr ) ) ;
++ i ;
}
i f ( argc < 2)
{
u s a g e ( optMgr , s s t r a t ) ;
e x i t ( EXIT_FAILURE ) ;
}
e l s e i f ( s t r c m p ( a r g v [ 1 ] , "−h " ) == 0 | | s t r c m p ( a r g v [ 1 ] , "−−h e l p " ) == 0 )
{
u s a g e ( optMgr , s s t r a t ) ;
e x i t ( EXIT_SUCCESS ) ;
}
try
{
cmd . c m d p a r s e ( a r g c , a r g v ) ;
}
c a t c h ( C o n s o l e E x ex )
{
c e r r << ex ( ) << e n d l ;
u s a g e ( optMgr , s s t r a t ) ;
e x i t ( EXIT_FAILURE ) ;
}
/ / i s t option e x p l i c i t ?
v e c t o r < s t r i n g > exp ;
f o r ( multimap < s t r i n g , O p t i o n > : : c o n s t _ i t e r a t o r i t e r = optMgr −>g e t O p t i o n s ()−> b e g i n ( ) ;
i t e r ! = optMgr −>g e t O p t i o n s ()−> end ( ) ; ++ i t e r )
{
i f ( i t e r −>s e c o n d . a r g u m e n t == " e x p l i c i t " && i t e r −> f i r s t ! = "SAD" )
exp . p u s h _ b a c k ( i t e r −> f i r s t ) ;
}
/ / j a −> s c a n n u r d i e s e r p l u g i n s
try
{
i f ( ! exp . empty ( ) )
{
f o r ( v e c t o r < s t r i n g > : : i t e r a t o r i t e r = exp . b e g i n ( ) ; i t e r ! = exp . end ( ) ; ++ i t e r )
{
s c a n r e s u l t s [ ∗ i t e r ] = s s t r a t [ ∗ i t e r ]−> s c a n ( ) ;
122
F.2. Framework
}
}
else
{
/ / s c a n −> a l l e
f o r ( v e c t o r < s t r i n g > : : i t e r a t o r i t e r = pname . b e g i n ( ) ;
i t e r ! = pname . end ( ) ; ++ i t e r )
s c a n r e s u l t s [ ∗ i t e r ] = s s t r a t [ ∗ i t e r ]−> s c a n ( ) ;
}
}
c a t c h ( SadEx ex )
{
c e r r << ex ( ) << e n d l ;
e x i t ( EXIT_FAILURE ) ;
}
catch ( . . . )
{
u s a g e ( optMgr , s s t r a t ) ;
e x i t ( EXIT_FAILURE ) ;
}
/ / p r i n t i n g out s c a n r e s u l t s
c o u t << " S c a n R e s u l t s : " << e n d l ;
c o u t << s e t w ( 8 0 ) << s e t f i l l ( ’− ’ ) << " " << e n d l ;
c o u t << s e t f i l l ( ’ ’ ) << s e t w ( 2 2 ) << l e f t << " Method " << s e t w ( 1 7 ) << r i g h t
<< " T e s t r e s u l t %" << s e t w ( 1 5 ) << r i g h t
<< " T r u s t " << s e t w ( 1 8 ) << r i g h t << " E v a l u a t i o n " << e n d l ;
c o u t << s e t w ( 8 0 ) << s e t f i l l ( ’− ’ ) << " " << e n d l ;
f o r ( map< s t r i n g , double > : : c o n s t _ i t e r a t o r i t e r = s c a n r e s u l t s . b e g i n ( ) ;
i t e r ! = s c a n r e s u l t s . end ( ) ; ++ i t e r )
{
c o u t << s e t w ( 2 ) << s e t f i l l ( ’ ’ ) << " " ;
c o u t << s e t w ( 2 0 ) << l e f t << s e t f i l l ( ’ ’ ) << i t e r −> f i r s t ;
c o u t << s e t w ( 1 5 ) << r i g h t << s e t f i l l ( ’ ’ ) << s e t p r e c i s i o n ( 5 )
<< i t e r −>s e c o n d ∗100 << " %" ;
c o u t << s e t w ( 1 5 ) << r i g h t << s e t f i l l ( ’ ’ )
<< c f g p −> g e t T r u s t ( i t e r −> f i r s t ) ;
c o u t << s e t w ( 1 8 ) << r i g h t << s e t f i l l ( ’ ’ )
<< c f g p −> g e t E v a l u a t i o n ( i t e r −> f i r s t ) << e n d l ;
}
c o u t << s e t w ( 8 0 ) << s e t f i l l ( ’− ’ ) << " " << e n d l ;
c o u t << s e t w ( 2 ) << s e t f i l l ( ’ ’ ) << " " << s e t w ( 5 0 ) << l e f t
<< "Sum : " << s e t w ( 1 8 ) << r i g h t
<< s e t p r e c i s i o n ( 5 ) << 100 ∗ g e t R e s u l t ( c f g p , s c a n r e s u l t s )
<< " %" << e n d l ;
/ / destroying all objects
i = 0;
for ( vector < destroySS_t ∗ >:: c o n s t _ i t e r a t o r
i t e r ! = mgr . d f u n c . end ( ) ; ++ i t e r )
{
( ∗ i t e r ) ( s s t r a t [ pname [ i ] ] ) ;
++ i ;
}
i t e r = mgr . d f u n c . b e g i n ( ) ;
/ / closing all Libraries
f o r ( v e c t o r < v o i d ∗ > : : c o n s t _ i t e r a t o r i t e r = mgr . p p t r . b e g i n ( ) ;
i t e r ! = mgr . p p t r . end ( ) ; ++ i t e r )
{
123
F.2. Framework
d l c l o s e (∗ i t e r ) ;
}
}
v o i d u s a g e ( OptionMgr ∗o , map< s t r i n g , S c a n S t r a t e g y ∗> &s )
{
multimap < s t r i n g , O p t i o n > : : c o n s t _ i t e r a t o r i t e r ;
c o u t << " Usage : s a d [− PluginName ] [ P l u g I n O p t s i o n s ] [ s a d O p t i o n s ] T a r g e t I P "
<< e n d l << e n d l ;
c o u t << s e t w ( 2 ) << " " << l e f t << s e t w ( 8 ) << "−h " << s e t w ( 2 0 ) << "−−h e l p "
<< " p r i n t t h i s m e s s a g e " << e n d l << e n d l ;
c o u t << "SAD" << " O p t i o n s : " << e n d l ;
f o r ( i t e r = o−>g e t O p t i o n s ()−> l o w e r _ b o u n d ( "SAD" ) ;
i t e r ! = o−>g e t O p t i o n s ()−> u p p e r _ b o u n d ( "SAD" ) ; + + i t e r )
{
c o u t << s e t w ( 2 ) << " " ;
c o u t << l e f t << s e t w ( 8 ) << i t e r −>s e c o n d . s o p t << s e t w ( 2 0 ) << i t e r −>s e c o n d . l o p t ;
i f ( i t e r −>s e c o n d . h a s _ a r g ! = NO_ARG)
c o u t << " < " ;
c o u t << i t e r −>s e c o n d . d e s c r i p t i o n ;
i f ( i t e r −>s e c o n d . h a s _ a r g ! = NO_ARG)
c o u t << " > " ;
c o u t << e n d l ;
}
c o u t << e n d l ;
f o r ( map< s t r i n g , S c a n S t r a t e g y ∗ > : : c o n s t _ i t e r a t o r
i t e r ! = s . end ( ) ; ++ i t e r )
{
i t e r −>s e c o n d −>u s a g e ( ) ;
}
i t e r = s . begin ( ) ;
}
d o u b l e g e t R e s u l t ( c f g P a r s e r ∗c , map< s t r i n g , double > &s r )
{
i n t num = 0 ;
double r e s = 0 ;
f o r ( map< s t r i n g , double > : : c o n s t _ i t e r a t o r i t e r = s r . b e g i n ( ) ;
i t e r ! = s r . end ( ) ; ++ i t e r )
{
i f ( c−> g e t E v a l u a t i o n ( i t e r −> f i r s t ) )
{
r e s += i t e r −>s e c o n d ∗ s t a t i c _ c a s t < double > ( c−> g e t T r u s t ( i t e r −> f i r s t ) ) ;
++num ;
}
}
i f ( num )
r e t u r n r e s / num ;
else
return 0 . 0 ;
}
124
F.3. Plugins
F.3. Plugins
F.3.1. arp.hpp
# i f n d e f ARP_HPP
# d e f i n e ARP_HPP
# i n c l u d e " . . / S c a n S t r a t e g y . hpp "
# i n c l u d e " . . / o p t i o n M g r . hpp "
# include < string >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
}
u s i n g namespace s t d ;
class arp : public ScanStrategy
{
private :
/∗ arp s p e c i f i c ∗/
u _ i n t 8 _ t zero_mac [ 6 ] ;
u_int8_t ∗eth_src , ∗ eth_dst ;
v i r t u a l void s e t L o c a l V a l ( ) ;
public :
a r p ( s t r i n g , OptionMgr ∗ ) ;
virtual ~arp ( ) ;
v i r t u a l double scan ( void ) ;
};
e x t e r n "C"
{
S c a n S t r a t e g y ∗ c r e a t e ( char ∗ , OptionMgr ∗ ) ;
v o i d d e s t r o y ( S c a n S t r a t e g y ∗p ) ;
}
# endif
F.3.2. arp.cpp
# include
# include
# include
# include
# include
# include
" a r p . hpp "
" . . / sadEx . hpp "
" . . / S c a n S t r a t e g y . hpp "
" . . / o p t i o n M g r . hpp "
" . . / i n j e c t i o n T . hpp "
" . . / c a p t u r e T . hpp "
# include
# include
# include
# include
<iostream >
<string >
<vector >
<cstdlib >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
}
u s i n g namespace s t d ;
125
F.3. Plugins
a r p : : a r p ( s t r i n g n , OptionMgr ∗ o p t ) : S c a n S t r a t e g y ( n , o p t )
{
/∗ Declare Options ∗/
p u s h O p t ( O p t i o n ( "−a " , "−−a r p " ,
NO_ARG, " " , " A c t i v a t e ARP−T e s t " ) ) ;
p u s h O p t ( O p t i o n ( "−c " , "−−c o u n t " ,
REQ_ARG, " 10 " , " Count t o r u n ARP−T e s t " ) ) ;
p u s h O p t ( O p t i o n ( "−fm " , "−−f a k e −mac " ,
REQ_ARG, " FF : FF : 0 0 : 0 0 : 0 0 : 0 0 " , " Faked D e s t i n a t i o n MAC" ) ) ;
p u s h O p t ( O p t i o n ( "−sm " , "−−s o u r c e −mac " ,
REQ_ARG, " " , " s o u r c e MAC" ) ) ;
}
arp : : ~ arp ( )
{
/∗ Destruktor ∗/
if (! eth_src )
{
delete ( eth_src );
e t h _ s r c =0;
}
if (! eth_dst )
{
delete ( eth_dst );
e t h _ d s t =0;
}
}
void arp : : s e t L o c a l V a l ( )
{
/∗ Defaults ∗/
memset ( ( v o i d ∗ ) zero_mac , 0 x00 , 6 ) ;
/∗ Libnet i n i t for g e t t i n g d e f a u l t addresses ∗/
i f ( ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_LINK , d e v i c e , e r r b u f ) ) == 0 )
throw L i b n e t E x ( e r r b u f ) ;
/ ∗ S e t d e f a u l t MAC S o u r c e ∗ /
i f ( ( e t h _ s r c = ( u _ i n t 8 _ t ∗ ) l i b n e t _ g e t _ h w a d d r ( c o n t e x t ) ) == 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
i n t dummy ;
multimap < s t r i n g , O p t i o n > : : c o n s t _ i t e r a t o r i t e r ;
f o r ( i t e r = optmgr −>g e t O p t i o n s ()−> l o w e r _ b o u n d ( name ) ;
i t e r ! = optmgr −>g e t O p t i o n s ()−> u p p e r _ b o u n d ( name ) ; + + i t e r )
{
i f ( i t e r −>s e c o n d . s o p t == "−c " )
l o o p = a t o i ( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ;
i f ( i t e r −>s e c o n d . s o p t == "−fm " )
if (( eth_dst = libnet_hex_aton (
r e i n t e r p r e t _ c a s t < i n t 8 _ t ∗ >( c o n s t _ c a s t < char ∗>
( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ) , &dummy ) ) == 0 )
throw L i b n e t E x ( " [ARP] s e t L o c a l V a l : l i b n e t _ h e x _ a t o n " ) ;
i f ( ( i t e r −>s e c o n d . s o p t == "−sm " ) && ( i t e r −>s e c o n d . a r g u m e n t ! = " " ) )
if (( eth_src = libnet_hex_aton (
r e i n t e r p r e t _ c a s t < i n t 8 _ t ∗ >( c o n s t _ c a s t < char ∗>
( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ) , &dummy ) ) == 0 )
throw L i b n e t E x ( " [ARP] s e t L o c a l V a l : l i b n e t _ h e x _ a t o n " ) ;
}
126
F.3. Plugins
/∗ Destroy the context ∗/
libnet_destroy ( context );
}
double arp : : scan ( void )
{
/∗ Set Global Values & D e f a u l t s ∗/
setGlobalVal ( ) ;
/∗ Set Local Values ∗/
setLocalVal ( ) ;
i f ( verbose )
{
c o u t << " [ARP] S o u r c e−MAC: " << m a c 2 s t r i n g ( e t h _ s r c ) << e n d l ;
c o u t << " [ARP] Fake−MAC: " << m a c 2 s t r i n g ( e t h _ d s t ) << e n d l ;
c o u t << " [ARP] Loop : " << l o o p << e n d l ;
}
/∗ Libnet I n i t ∗/
i f ( ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_LINK , d e v i c e , e r r b u f ) ) == 0 )
throw L i b n e t E x ( e r r b u f ) ;
/ ∗ B u i l d Fake ARP R e q u e s t ∗ /
i f ( l i b n e t _ a u t o b u i l d _ a r p ( ARPOP_REQUEST ,
e t h _ s r c , ( u _ i n t 8 _ t ∗)& i p _ s r c , zero_mac ,
( u _ i n t 8 _ t ∗)& i p _ d s t , c o n t e x t ) < 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
/∗ Build Ethernet ∗/
i f ( l i b n e t _ b u i l d _ e t h e r n e t ( e t h _ d s t , e t h _ s r c , ETHERTYPE_ARP , 0 , 0 , c o n t e x t , 0 ) < 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
//
i f ( verbose )
{
c o u t << " [ARP] R e q u e s t P a c k e t : " << e n d l ;
libnet_diag_dump_context ( context );
}
/∗ I n j e c t i o n ∗/
I n j e c t i o n T fakeArp ;
f o r ( i n t i = 0 ; i < l o o p ; ++ i )
fakeArp . addPacket ( c o n t e x t ) ;
/∗ Capture ∗/
i n t examines = 0;
/∗ Build F i l t e r ∗/
f i l t e r << " a r p [ 7 ] = = 0 x02 and " ;
f i l t e r << " s r c h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ d s t , LIBNET_RESOLVE ) << " and " ;
f i l t e r << " d s t h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ s r c , LIBNET_RESOLVE ) ;
i f ( verbose )
c o u t << " [ARP] F i l t e r : " << f i l t e r . s t r ( ) << e n d l ;
CaptureT arpcap ( device ,
f i l t e r . s t r ( ) , 2 , 1000 , loop , examines ) ;
/ ∗ Add T h r e a d s ∗ /
addThread ( fakeArp ) ;
addThread ( arpcap ) ;
127
F.3. Plugins
/∗ S t a r t Threads ∗/
startThreads ();
/ ∗ CleanUp I n j e c t i o n ∗ /
libnet_destroy ( context );
/ ∗ Examine ∗ /
i f ( verbose )
c o u t << " [ARP] Examines c o u n t : " << e x a m i n e s << e n d l ;
/ ∗ ARP T e s t R e s u l t ∗ /
i f ( examines )
return 1 . 0 ;
else
return 0;
}
e x t e r n "C" S c a n S t r a t e g y ∗ c r e a t e ( char ∗n , OptionMgr ∗ o p t )
{
r e t u r n new a r p ( n , o p t ) ;
}
e x t e r n "C" v o i d d e s t r o y ( S c a n S t r a t e g y ∗p )
{
delete p ;
}
128
F.3. Plugins
F.3.3. icmp.hpp
# i f n d e f ICMP_HPP
# d e f i n e ICMP_HPP
# i n c l u d e " . . / S c a n S t r a t e g y . hpp "
# i n c l u d e " . . / o p t i o n M g r . hpp "
# include < string >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
}
u s i n g namespace s t d ;
c l a s s icmp : p u b l i c S c a n S t r a t e g y
{
private :
/ ∗ icmp s p e c i f i c ∗ /
u_int16_t id ;
u_int8_t ∗eth_src , ∗ eth_dst ;
v i r t u a l void s e t L o c a l V a l ( ) ;
public :
icmp ( s t r i n g , OptionMgr ∗ ) ;
v i r t u a l ~ icmp ( ) ;
v i r t u a l double scan ( void ) ;
};
e x t e r n "C"
{
S c a n S t r a t e g y ∗ c r e a t e ( char ∗ , OptionMgr ∗ ) ;
v o i d d e s t r o y ( S c a n S t r a t e g y ∗p ) ;
}
# endif
F.3.4. icmp.cpp
# include
# include
# include
# include
# include
# include
" icmp . hpp "
" . . / sadEx . hpp "
" . . / S c a n S t r a t e g y . hpp "
" . . / o p t i o n M g r . hpp "
" . . / i n j e c t i o n T . hpp "
" . . / c a p t u r e T . hpp "
# include
# include
# include
# include
<iostream >
<string >
<vector >
<cstdlib >
e x t e r n "C"
{
# i n c l u d e < s y s / t y p e s . h>
# i n c l u d e < u n i s t d . h>
# i n c l u d e < l i b n e t . h>
}
u s i n g namespace s t d ;
129
F.3. Plugins
icmp : : icmp ( s t r i n g n , OptionMgr ∗ o p t ) : S c a n S t r a t e g y ( n , o p t )
{
/∗ Declare Options ∗/
p u s h O p t ( O p t i o n ( "−i " , "−−icmp " ,
NO_ARG, " " , " A c t i v a t e ICMP−T e s t " ) ) ;
p u s h O p t ( O p t i o n ( "−c " , "−−c o u n t " ,
REQ_ARG, " 10 " , " Count t o r u n ICMP−T e s t " ) ) ;
p u s h O p t ( O p t i o n ( "−fm " , "−−f a k e −mac " ,
REQ_ARG, " FF : FF : 0 0 : 0 0 : 0 0 : 0 0 " , " Faked D e s t i n a t i o n MAC" ) ) ;
p u s h O p t ( O p t i o n ( "−sm " , "−−s o u r c e −mac " ,
REQ_ARG, " " , " s o u r c e MAC" ) ) ;
}
icmp : : ~ icmp ( )
{
/∗ Destruktor ∗/
if (! eth_src )
{
delete ( eth_src );
e t h _ s r c =0;
}
if (! eth_dst )
{
delete ( eth_dst );
e t h _ d s t =0;
}
}
v o i d icmp : : s e t L o c a l V a l ( )
{
/∗ Defaults ∗/
id = getpid ( ) ;
/ ∗ L i b n e t I n i t f o r g e t t i n g some d e f a u l t a d r e s s e s ∗ /
i f ( ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_LINK , d e v i c e , e r r b u f ) ) == 0 )
throw L i b n e t E x ( e r r b u f ) ;
/ ∗ S e t d e f a u l t MAC S o u r c e ∗ /
i f ( ( e t h _ s r c = ( u _ i n t 8 _ t ∗ ) l i b n e t _ g e t _ h w a d d r ( c o n t e x t ) ) == 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
i n t dummy ;
multimap < s t r i n g , O p t i o n > : : c o n s t _ i t e r a t o r i t e r ;
f o r ( i t e r = optmgr −>g e t O p t i o n s ()−> l o w e r _ b o u n d ( name ) ;
i t e r ! = optmgr −>g e t O p t i o n s ()−> u p p e r _ b o u n d ( name ) ; + + i t e r )
{
i f ( i t e r −>s e c o n d . s o p t == "−c " )
l o o p = a t o i ( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ;
i f ( i t e r −>s e c o n d . s o p t == "−fm " )
if (( eth_dst = libnet_hex_aton (
r e i n t e r p r e t _ c a s t < i n t 8 _ t ∗ >( c o n s t _ c a s t < char ∗>
( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ) , &dummy ) ) == 0 )
throw L i b n e t E x ( " [ ICMP ] s e t L o c a l V a l : l i b n e t _ h e x _ a t o n " ) ;
i f ( ( i t e r −>s e c o n d . s o p t == "−sm " ) && ( i t e r −>s e c o n d . a r g u m e n t ! = " " ) )
if (( eth_src = libnet_hex_aton (
r e i n t e r p r e t _ c a s t < i n t 8 _ t ∗ >( c o n s t _ c a s t < char ∗>
( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ) , &dummy ) ) == 0 )
throw L i b n e t E x ( " [ARP] s e t L o c a l V a l : l i b n e t _ h e x _ a t o n " ) ;
}
130
F.3. Plugins
/∗ Destroy the context ∗/
libnet_destroy ( context );
}
d o u b l e icmp : : s c a n ( v o i d )
{
/∗ Set Global Values & Defauls ∗/
setGlobalVal ( ) ;
/∗ Set Local Values ∗/
setLocalVal ( ) ;
i f ( verbose )
{
c o u t << " [ ICMP ] S o u r c e−MAC: " << m a c 2 s t r i n g ( e t h _ s r c ) << e n d l ;
c o u t << " [ ICMP ] Fake−MAC: " << m a c 2 s t r i n g ( e t h _ d s t ) << e n d l ;
c o u t << " [ ICMP ] Loop : " << l o o p << e n d l ;
}
/∗ Libnet I n i t ∗/
i f ( ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_LINK , d e v i c e , e r r b u f ) ) == 0 )
throw L i b n e t E x ( e r r b u f ) ;
/ ∗ B u i l d ICMP e c h o r e q u e s t ∗ /
i f ( l i b n e t _ b u i l d _ i c m p v 4 _ e c h o ( ICMP_ECHO , 0 , 0 , i d , 0 , 0 , 0 , c o n t e x t , 0 ) < 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
/ ∗ B u i l d IP p a c k e t ∗ /
i f ( l i b n e t _ b u i l d _ i p v 4 ( LIBNET_IPV4_H + LIBNET_ICMPV4_ECHO_H , 0 , i d , 0 , 8 ,
IPPROTO_ICMP , 0 , i p _ s r c , i p _ d s t , 0 , 0 , c o n t e x t , 0 ) < 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
/∗ Build Ethernet ∗/
i f ( l i b n e t _ b u i l d _ e t h e r n e t ( e t h _ d s t , e t h _ s r c , ETHERTYPE_IP , 0 , 0 , c o n t e x t , 0 ) < 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
/∗ I n j e c t i o n ∗/
I n j e c t i o n T fakeICMP ;
f o r ( i n t i = 0 ; i < l o o p ; ++ i )
fakeICMP . a d d P a c k e t ( c o n t e x t ) ;
/∗ Capture ∗/
i n t examines = 0;
/∗ Build F i l t e r ∗/
f i l t e r << " icmp [ i c m p t y p e ] = icmp−e c h o r e p l y and "
<< " s r c h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ d s t , LIBNET_RESOLVE ) << " and "
<< " d s t h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ s r c , LIBNET_RESOLVE ) << " and "
<< " icmp [ 4 : 2 ] = = " << i d << " and " << " icmp [ 6 : 2 ] = = 0 " ;
i f ( verbose )
c o u t << " [ ICMP ] F i l t e r : " << f i l t e r . s t r ( ) << e n d l ;
CaptureT icmpcap ( device ,
f i l t e r . s t r ( ) , 2 , 1000 , loop , examines ) ;
/ ∗ Add T h r e a d s ∗ /
a d d T h r e a d ( fakeICMP ) ;
addThread ( icmpcap ) ;
/∗ S t a r t Threads ∗/
startThreads ();
131
F.3. Plugins
/ ∗ CleanUp I n j e c t i o n ∗ /
libnet_destroy ( context );
/∗ Examines ∗/
i f ( verbose )
c o u t << " [ ICMP ] Examines c o u n t : " << e x a m i n e s << e n d l ;
/ ∗ ICMP T e s t R e s u l t ∗ /
i f ( examines )
return 1 . 0 ;
else
return 0;
}
e x t e r n "C" S c a n S t r a t e g y ∗ c r e a t e ( char ∗n , OptionMgr ∗ o p t )
{
r e t u r n new icmp ( n , o p t ) ;
}
e x t e r n "C" v o i d d e s t r o y ( S c a n S t r a t e g y ∗p )
{
delete p ;
}
132
F.3. Plugins
F.3.5. dns.hpp
# i f n d e f DNS_HPP
# d e f i n e DNS_HPP
# include
# include
# include
# include
# include
" . . / S c a n S t r a t e g y . hpp "
" . . / o p t i o n M g r . hpp "
<string >
<sstream >
<vector >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
}
u s i n g namespace s t d ;
c l a s s dns : publ ic S c a n S t r a t e g y
{
private :
/∗ dns s p e c i f i c ∗/
s t a t i c stringstream queryip ;
u_int16_t id ;
u _ i n t 1 6 _ t seq ;
v e c t o r < l i b n e t _ t ∗> gc ; / / ; −) ü G r s s e an J a v a
v i r t u a l void s e t L o c a l V a l ( void ) ;
void b u i l d F i l t e r ( void ) ;
public :
d n s ( s t r i n g , OptionMgr ∗ ) ;
v i r t u a l ~dns ( ) ;
v i r t u a l double scan ( void ) ;
};
e x t e r n "C" {
S c a n S t r a t e g y ∗ c r e a t e ( char ∗ , OptionMgr ∗ ) ;
v o i d d e s t r o y ( S c a n S t r a t e g y ∗p ) ;
}
# endif
F.3.6. dns.cpp
# include
# include
# include
# include
# include
# include
" d n s . hpp "
" . . / sadEx . hpp "
" . . / S c a n S t r a t e g y . hpp "
" . . / o p t i o n M g r . hpp "
" . . / i n j e c t i o n T . hpp "
" . . / c a p t u r e T . hpp "
# include
# include
# include
# include
# include
<string >
<vector >
<sstream >
<cstdlib >
<ctime >
# include <iostream >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
133
F.3. Plugins
# i n c l u d e < s y s / t y p e s . h>
# i n c l u d e < u n i s t d . h>
}
u s i n g namespace s t d ;
s t r i n g s t r e a m dns : : q u e r y i p ;
d n s : : d n s ( s t r i n g n , OptionMgr ∗ o p t ) : S c a n S t r a t e g y ( n , o p t )
{
/∗ Declare Options ∗/
p u s h O p t ( O p t i o n ( "−d " , "−−d n s " , NO_ARG, " " , " A c t i v a t e DNS−T e s t " ) ) ;
p u s h O p t ( O p t i o n ( "−c " , "−−c o u n t " , REQ_ARG, " 5 " , " Count t o r u n DNS−T e s t " ) ) ;
}
dns : : ~ dns ( )
{
/∗ Destruktor ∗/
vector < l i b n e t _ t ∗ >:: i t e r a t o r i t e r ;
f o r ( i t e r = gc . b e g i n ( ) ; i t e r ! = gc . b e g i n ( ) ; ++ i t e r )
l i b n e t _ d e s t r o y (∗ i t e r ) ;
}
void dns : : s e t L o c a l V a l ( )
{
multimap < s t r i n g , O p t i o n > : : c o n s t _ i t e r a t o r i t e r ;
f o r ( i t e r = optmgr −>g e t O p t i o n s ()−> l o w e r _ b o u n d ( name ) ;
i t e r ! = optmgr −>g e t O p t i o n s ()−> u p p e r _ b o u n d ( name ) ; + + i t e r )
{
i f ( i t e r −>s e c o n d . s o p t == "−c " )
l o o p = a t o i ( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ;
}
}
double dns : : scan ( void )
{
v e c t o r <CaptureT > caps ;
InjectionT fakePing ;
i n t examines = 0;
/ / Set Global Values & D e f a u l t s
setGlobalVal ( ) ;
/ / Set Local Values
setLocalVal ( ) ;
s r a n d ( s t a t i c _ c a s t <unsigned int >( time ( 0 ) ) ) ;
f o r ( i n t i = 0 ; i < l o o p ; ++ i )
{
/ / Libnet I n i t
i f ( ! ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_RAW4 , d e v i c e , e r r b u f ) ) )
throw L i b n e t E x ( e r r b u f ) ;
/ / B u i l d Fake ICMP−Header
id = getpid ( ) ;
seq = i ;
queryip . s t r ( " " ) ;
queryip . clear ( ) ;
q u e r y i p << r a n d ( ) % 200 + 1 << " . " << r a n d ( ) % 255 << " . " << r a n d ( ) % 255
<< " . " << r a n d ( ) % 2 5 5 ;
134
F.3. Plugins
i f ( verbose )
c o u t << " [DNS] q u e r y−I P : " << q u e r y i p . s t r ( ) << e n d l ;
i f ( l i b n e t _ b u i l d _ i c m p v 4 _ e c h o ( ICMP_ECHO , 0 , 0 , i d , seq , 0 , 0 , c o n t e x t , 0 ) < 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
/ / B u i l d Fake IP−Header
u_int32_t tqip = libnet_name2addr4 ( context ,
c o n s t _ c a s t < char ∗ >( q u e r y i p . s t r ( ) . c _ s t r ( ) ) , LIBNET_RESOLVE ) ;
i f ( t q i p == ( u _ i n t 3 2 _ t ) −1)
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
i f ( l i b n e t _ b u i l d _ i p v 4 ( LIBNET_IPV4_H + LIBNET_ICMPV4_ECHO_H + 0 , 0 , i d , 0 , 6 4 ,
IPPROTO_ICMP , 0 , i p _ s r c , t q i p , 0 , 0 , c o n t e x t , 0 ) < 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
// Injection
fakePing . addPacket ( context ) ;
buildFilter ();
i f ( verbose )
c o u t << " [DNS] F i l t e r : " << f i l t e r . s t r ( ) << e n d l ;
caps . push_back ( CaptureT ( device ,
gc . p u s h _ b a c k ( c o n t e x t ) ;
f i l t e r . s t r ( ) , 1 , 2000 , 1 , examines ) ) ;
}
for ( v e c t o r <CaptureT > : : i t e r a t o r
addThread (∗ i t e r ) ;
i t e r = caps . begin ( ) ;
i t e r ! = c a p s . end ( ) ; ++ i t e r )
addThread ( fakePing ) ;
startThreads ();
/ ∗ DNS T e s t R e s u l t ∗ /
i f ( examines )
return 1 . 0 ;
else
return 0;
}
void dns : : b u i l d F i l t e r ( void )
{
filter . str ("" );
f i l t e r . clear ();
/ / Building Filter
unsigned i n t pos [ 4 ] , u o f f s e t = 21;
string s [4];
f o r ( i n t i = 3 ; i >= 0 ; −−i )
{
g e t l i n e ( queryip , s [ i ] , ’ . ’ ) ;
pos [ i ] = s [ i ] . s i z e ( ) ;
}
f i l t e r << " d s t p o r t 53 " << " and " << " s r c h o s t "
<< l i b n e t _ a d d r 2 n a m e 4 ( i p _ d s t , LIBNET_RESOLVE ) ;
f o r ( u n s i g n e d i n t i = 0 ; i < 4 ; ++ i )
{
f o r ( u n s i g n e d i n t j = 0 ; j < s [ i ] . s i z e ( ) ; ++ j )
{
f i l t e r << " and " << " udp [ " << u o f f s e t << " ]== "
135
F.3. Plugins
<< s t a t i c _ c a s t < i n t > ( s [ i ] . a t ( j ) ) ;
u o f f s e t ++;
}
++ u o f f s e t ;
}
}
e x t e r n "C" S c a n S t r a t e g y ∗ c r e a t e ( char ∗n , OptionMgr ∗ o p t )
{
r e t u r n new d n s ( n , o p t ) ;
}
e x t e r n "C" v o i d d e s t r o y ( S c a n S t r a t e g y ∗p )
{
delete p ;
}
136
F.3. Plugins
F.3.7. latency.hpp
# i f n d e f LATENCY_HPP
# d e f i n e LATENCY_HPP
# include
# include
# include
# include
" . . / S c a n S t r a t e g y . hpp "
" . . / o p t i o n M g r . hpp "
<string >
<fstream >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
# i n c l u d e < s y s / t i m e . h>
# i n c l u d e < t i m e . h>
}
u s i n g namespace s t d ;
class latency : public ScanStrategy
{
private :
/∗ latency s p e c i f i c ∗/
char e r r b u f t c p [ LIBNET_ERRBUF_SIZE ] ;
u_short src_port , dst_port ;
u_int8_t ∗payload ;
u_short payload_s ;
u_int32_t ip_fake ;
u_int16_t id ;
l i b n e t _ t ∗flood ;
s t a t i c c o n s t u n s i g n e d i n t PACKETS = 5 0 0 0 0 0 ;
s t a t i c c o n s t u n s i g n e d i n t ACOUNT = 5 0 ;
t i m e v a l t v b [ACOUNT] , t v e [ACOUNT ] ;
l i b n e t _ t ∗ i p a c k [ACOUNT ] ;
ofstream f i l e ;
v i r t u a l void s e t L o c a l V a l ( ) ;
v o i d buildICMP ( v o i d ) ;
void buildTCP ( void ) ;
void r e s e t T i m e r ( void ) ;
unsigned i n t average ( void ) ;
public :
l a t e n c y ( s t r i n g , OptionMgr ∗ ) ;
virtual ~latency ( ) ;
v i r t u a l double scan ( void ) ;
};
e x t e r n "C"
{
S c a n S t r a t e g y ∗ c r e a t e ( char ∗ , OptionMgr ∗ ) ;
v o i d d e s t r o y ( S c a n S t r a t e g y ∗p ) ;
}
# endif
F.3.8. latency.cpp
137
F.3. Plugins
# include
# include
# include
# include
# include
# include
" l a t e n c y . hpp "
" . . / l a t e n c y C T . hpp "
" . . / sadEx . hpp "
" . . / S c a n S t r a t e g y . hpp "
" . . / o p t i o n M g r . hpp "
" . . / i n j e c t i o n T . hpp "
# include < string >
# include <vector >
# include < cstdlib >
# include <iostream >
# include <fstream >
# i n c l u d e <iomanip >
e x t e r n "C"
{
# i n c l u d e < l i b n e t . h>
# i n c l u d e < s y s / t i m e . h>
# i n c l u d e < s y s / t y p e s . h>
# i n c l u d e < t i m e . h>
# i n c l u d e < u n i s t d . h>
}
u s i n g namespace s t d ;
l a t e n c y : : l a t e n c y ( s t r i n g n , OptionMgr ∗ o p t ) : S c a n S t r a t e g y ( n , o p t )
{
/∗ Declare Options ∗/
p u s h O p t ( O p t i o n ( "−l " , "−−l a t e n c y " , NO_ARG, " " , " A c t i v a t e L a t e n c y −T e s t " ) ) ;
p u s h O p t ( O p t i o n ( "−c " , "−−c o u n t " , REQ_ARG, " 1 " , " Count t o r u n L a t e n c y −T e s t " ) ) ;
p u s h O p t ( O p t i o n ( "−s p " , "−−s o u r c e −p o r t " , REQ_ARG, " 23 " ,
"TCP−S o u r c e−P o r t o f t h e f l o o d i n g T h r e a d " ) ) ;
p u s h O p t ( O p t i o n ( "−dp " , "−−d e s t i n a t i o n −p o r t " , REQ_ARG, " 23 " ,
"TCP−D e s t i o n a t i o n −P o r t o f t h e f l o o d i n g T h r e a d " ) ) ;
p u s h O p t ( O p t i o n ( "−p " , "−−p a y l o a d " , REQ_ARG, " p a s s w o r d : Buhhh − G o t c h a ! ! ! " ,
" P a y l o a d you want t o s e n d ( i n \ " Double Quote \ " ) " ) ) ;
p u s h O p t ( O p t i o n ( "−f i p " , "−−f a k e −i p " , REQ_ARG, " 1 . 1 . 1 . 1 " , " Fake−I P " ) ) ;
id = getpid ( ) ;
f i l e . open ( " R e p o r t . t x t " , i o s : : app ) ;
f i l e << "ND\ tNA \ tFD \ tFA " << e n d l ;
}
latency ::~ latency ()
{
/∗ Destruktor ∗/
f i l e . close ( ) ;
}
void l a t e n c y : : s e t L o c a l V a l ( )
{
i f ( ( c o n t e x t = l i b n e t _ i n i t ( LIBNET_LINK , d e v i c e , e r r b u f ) ) == 0 )
throw L i b n e t E x ( e r r b u f ) ;
multimap < s t r i n g , O p t i o n > : : c o n s t _ i t e r a t o r i t e r ;
f o r ( i t e r = optmgr −>g e t O p t i o n s ()−> l o w e r _ b o u n d ( name ) ;
i t e r ! = optmgr −>g e t O p t i o n s ()−> u p p e r _ b o u n d ( name ) ; + + i t e r )
{
i f ( i t e r −>s e c o n d . s o p t == "−c " )
138
F.3. Plugins
l o o p = a t o i ( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ;
e l s e i f ( i t e r −>s e c o n d . s o p t == "−s p " )
s r c _ p o r t = s t a t i c _ c a s t < u _ s h o r t > ( a t o i ( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ) ;
e l s e i f ( i t e r −>s e c o n d . s o p t == "−dp " )
d s t _ p o r t = s t a t i c _ c a s t < u _ s h o r t > ( a t o i ( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ) ;
e l s e i f ( i t e r −>s e c o n d . s o p t == "−p " )
{
p a y l o a d = r e i n t e r p r e t _ c a s t < u _ i n t 8 _ t ∗>
( c o n s t _ c a s t < char ∗ >( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ) ;
p a y l o a d _ s = i t e r −>s e c o n d . a r g u m e n t . s i z e ( ) ;
}
e l s e i f ( i t e r −>s e c o n d . s o p t == "−f i p " )
{
i f (( ip_fake = libnet_name2addr4 ( context ,
c o n s t _ c a s t < char ∗ >( i t e r −>s e c o n d . a r g u m e n t . c _ s t r ( ) ) ,
LIBNET_RESOLVE ) ) == ( u _ i n t 3 2 _ t ) ( − 1 ) )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( c o n t e x t ) ) ;
}
}
libnet_destroy ( context );
}
v o i d l a t e n c y : : buildICMP ( v o i d )
{
f o r ( u n s i g n e d i n t i = 0 ; i < l a t e n c y : : ACOUNT; ++ i )
{
/ / Libnet I n i t
i f ( ! ( i p a c k [ i ] = l i b n e t _ i n i t ( LIBNET_RAW4 , d e v i c e , e r r b u f ) ) )
throw L i b n e t E x ( e r r b u f ) ;
/ / B u i l d i n g ICMP−Header
i f ( l i b n e t _ b u i l d _ i c m p v 4 _ e c h o ( ICMP_ECHO , 0 , 0 , i d ,
s t a t i c _ c a s t < u _ i n t 1 6 _ t >( i ) , 0 , 0 , i p a c k [ i ] , 0) < 0)
throw L i b n e t E x ( e r r b u f ) ;
/ / B u i l d i n g IP−Header
i f ( l i b n e t _ b u i l d _ i p v 4 ( LIBNET_IPV4_H + LIBNET_ICMPV4_ECHO_H + 0 , 0 , i d , 0 , 6 4 ,
IPPROTO_ICMP , 0 , i p _ s r c , i p _ d s t , 0 , 0 , i p a c k [ i ] , 0 ) < 0 )
throw L i b n e t E x ( l i b n e t _ g e t e r r o r ( i p a c k [ i ] ) ) ;
}
}
void l a t e n c y : : buildTCP ( void )
{
i f ( ! ( f l o o d = l i b n e t _ i n i t ( LIBNET_RAW4 , d e v i c e , e r r b u f t c p ) ) )
throw L i b n e t E x ( e r r b u f t c p ) ;
i f ( l i b n e t _ b u i l d _ t c p ( s r c _ p o r t , d s t _ p o r t , 0 x01010101 , 0 x02020202 , TH_ACK | TH_PUSH ,
3 2 7 6 7 , 0 , 0 , LIBNET_TCP_H + p a y l o a d _ s , p a y l o a d , p a y l o a d _ s ,
flood , 0) < 0)
throw L i b n e t E x ( e r r b u f t c p ) ;
i f ( l i b n e t _ b u i l d _ i p v 4 ( LIBNET_IPV4_H + LIBNET_TCP_H + p a y l o a d _ s , 0 , 2 4 2 ,
0 , 6 4 , IPPROTO_TCP , 0 , i p _ s r c , i p _ f a k e , NULL, 0 , f l o o d , 0 ) < 0 )
throw L i b n e t E x ( e r r b u f t c p ) ;
}
unsigned i n t l a t e n c y : : average ( void )
{
u n s i g n e d i n t avg = 0 ;
int valid = 0 , drops = 0;
139
F.3. Plugins
i f ( verbose )
{
f o r ( u n s i g n e d i n t i = 0 ; i < l a t e n c y : : ACOUNT; ++ i )
{
i f ( t v e [ i ] . t v _ s e c && t v b [ i ] . t v _ s e c )
c o u t << i << " D e l t a : "
<< 1 0 0 0 0 0 0 ∗ ( t v e [ i ] . t v _ s e c − t v b [ i ] . t v _ s e c ) +
( t v e [ i ] . t v _ u s e c − t v b [ i ] . t v _ u s e c ) << e n d l ;
else
c o u t << i << " d r o p p e d " << e n d l ;
}
}
f o r ( u n s i g n e d i n t i = 0 ; i < l a t e n c y : : ACOUNT; ++ i )
{
i f ( t v e [ i ] . t v _ s e c && t v b [ i ] . t v _ s e c )
{
avg += 1 0 0 0 0 0 0 ∗ ( t v e [ i ] . t v _ s e c − t v b [ i ] . t v _ s e c ) +
( tve [ i ] . tv_usec − tvb [ i ] . tv_usec ) ;
++ v a l i d ;
}
else
++ d r o p s ;
}
i f ( verbose )
c o u t << " Droped : " << d r o p s << " V a l i d : " << v a l i d << e n d l ;
f i l e << d r o p s << " \ t " << avg / v a l i d << " \ t " ;
r e t u r n avg / v a l i d ;
}
double l a t e n c y : : scan ( void )
{
i n t examines = 0;
setGlobalVal ( ) ;
setLocalVal ( ) ;
buildICMP ( ) ;
buildTCP ( ) ;
filter . str ("" );
f i l t e r . clear ();
f i l t e r << " ( icmp [ i c m p t y p e ] = icmp−e c h o and "
<< " s r c h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ s r c ,
<< " d s t h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ d s t ,
<< " ) o r ( " ;
f i l t e r << " icmp [ i c m p t y p e ] = icmp−e c h o r e p l y and "
<< " s r c h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ d s t ,
<< " d s t h o s t " << l i b n e t _ a d d r 2 n a m e 4 ( i p _ s r c ,
f i l t e r << " and icmp [ 4 : 2 ] = = " << i d ;
LIBNET_RESOLVE ) << " and "
LIBNET_RESOLVE )
LIBNET_RESOLVE ) << " and "
LIBNET_RESOLVE ) << " ) " ;
i f ( verbose )
c o u t << " [LATENCY] F i l t e r : " << f i l t e r . s t r ( ) << e n d l ;
f o r ( i n t i = 0 ; i < l o o p ; ++ i )
{
examines = 0;
LatencyCT c a p ( d e v i c e , f i l t e r . s t r ( ) , 1 0 0 0 0 0 0 0 , 2∗ l a t e n c y : : ACOUNT, e x a m i n e s ) ;
resetTimer ( ) ;
cap . s e t T i m e v a l ( tvb , t v e ) ;
I n j e c t i o n T ping ( 2 0 0 ) ;
140
F.3. Plugins
f o r ( u n s i g n e d i n t k = 0 ; k < l a t e n c y : : ACOUNT; ++k )
ping . addPacket ( ipack [ k ] ) ;
addThread ( cap ) ;
addThread ( ping ) ;
startThreads ();
i f ( verbose )
c o u t << " [LATENCY NORMAL] A v e r a g e : " << a v e r a g e ( ) << e n d l ;
examines = 0;
I n j e c t i o n T floodT ;
i f ( verbose )
c o u t << " [LATENCY] B u i l d i n g Flood−P a c k e t s " << e n d l ;
f o r ( u n s i g n e d i n t k = 0 ; k < l a t e n c y : : PACKETS ; ++k )
floodT . addPacket ( flood ) ;
i f ( verbose )
c o u t << " [LATENCY] done " << e n d l ;
resetTimer ( ) ;
addThread ( floodT ) ;
addThread ( ping ) ;
addThread ( cap ) ;
startThreads ();
i f ( verbose )
c o u t << " [LATENCY FLOOD] A v e r a g e : " << a v e r a g e ( ) << e n d l ;
f i l e << e n d l ;
}
libnet_destroy ( flood ) ;
f o r ( u n s i g n e d i n t k = 0 ; k < l a t e n c y : : ACOUNT; ++k )
libnet_destroy ( ipack [ k ] ) ;
return 0 . 0 ;
}
void l a t e n c y : : r e s e t T i m e r ( void )
{
f o r ( u n s i g n e d i n t i = 0 ; i < l a t e n c y : : ACOUNT; ++ i )
{
tvb [ i ] . tv_sec = tve [ i ] . tv_sec = 0;
tvb [ i ] . tv_usec = tve [ i ] . tv_usec = 0;
}
}
e x t e r n "C" S c a n S t r a t e g y ∗ c r e a t e ( char ∗n , OptionMgr ∗ o p t )
{
r e t u r n new l a t e n c y ( n , o p t ) ;
}
e x t e r n "C" v o i d d e s t r o y ( S c a n S t r a t e g y ∗p )
{
delete p ;
}
141

Documentos relacionados