Justin Seitz ist als leitender Sicherheitsexperte bei der Firma Immunity, Inc. beschäftigt, wo er seine Zeit mit Fehlersuche, Reverse Engineering, der Entwicklung von Exploits und dem Programmieren in Python verbringt. Er ist der Autor von »Hacking mit Python – Fehlersuche, Programmanalyse, Reverse Engineering« (dpunkt.verlag, 2009), dem ersten Buch, in dem Python zur Sicherheitsanalyse eingesetzt worden ist.
Zu diesem Buch – sowie zu vielen weiteren dpunkt.büchern – können Sie auch das entsprechende E-Book im PDF-Format herunterladen. Werden Sie dazu einfach Mitglied bei dpunkt.plus+: www.dpunkt.de/plus |
Eigene Tools entwickeln für Hacker und Pentester
Lektorat: René Schönfeldt
Copy-Editing: Ursula Zimpfer, Herrenberg
Herstellung: Nadine Thiele
Umschlaggestaltung: Helmut Kraus, www.exclam.de
Druck und Bindung: M.P. Media-Print Informationstechnologie GmbH, 33100 Paderborn
Bibliografische Information der Deutschen Nationalbibliothek
Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie;
detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar.
ISBN:
Buch 978-3-86490-286-4
PDF 978-3-86491-752-3
ePub 978-3-86491-753-0
mobi 978-3-86491-754-7
Copyright © 2015 dpunkt.verlag GmbH
Wieblinger Weg 17
69123 Heidelberg
© 2015 by Justin Seitz
Black Hat Python – Python Programming for Hackers and Pentesters
No Starch Press, Inc. · 38 Ringold Street, San Francisco, CA 94103 · http://www.nostarch.com/
ISBN 978-1-59327-590-7
Die vorliegende Publikation ist urheberrechtlich geschützt. Alle Rechte vorbehalten. Die Verwendung der Texte und Abbildungen, auch auszugsweise, ist ohne die schriftliche Zustimmung des Verlags urheberrechtswidrig und daher strafbar. Dies gilt insbesondere für die Vervielfältigung, Übersetzung oder die Verwendung in elektronischen Systemen.
Es wird darauf hingewiesen, dass die im Buch verwendeten Soft- und Hardware-Bezeichnungen sowie Markennamen und Produktbezeichnungen der jeweiligen Firmen im Allgemeinen warenzeichen-, marken- oder patentrechtlichem Schutz unterliegen.
Alle Angaben und Programme in diesem Buch wurden mit größter Sorgfalt kontrolliert. Weder Autor noch Verlag können jedoch für Schäden haftbar gemacht werden, die in Zusammenhang mit der Verwendung dieses Buches stehen.
5 4 3 2 1 0
Für Pat
Obwohl wir uns nie getroffen haben, bin ich für jedes Mitglied deiner wunderbaren Familie dankbar, das du mir gegeben hast.
Canadian Cancer Society
www.cancer.ca
Python ist in der Welt der Informationssicherheit immer noch die vorherrschende Sprache, auch wenn Diskussionen über die von einem selbst bevorzugte Sprache eher etwas von Religionskriegen haben. Python-basierte Tools umfassen alle Arten von Fuzzern, Proxies und gelegentlich sogar einen Exploit. Exploit-Frameworks wie CANVAS sind in Python geschrieben, ebenso die etwas »dunkleren« Tools wie PyEmu oder Sulley.
Nahezu jeder von mir entwickelte Fuzzer oder Exploit ist in Python geschrieben. Tatsächlich umfasst die von Chris Valasek und mir jüngst durchgeführte Forschungsarbeit im Bereich Automobil-Hacking eine Bibliothek, die CANNachrichten mittels Python in Ihr Automobil-Netzwerk einschleust!
Wenn Sie im Bereich Informationssicherheit arbeiten wollen, lohnt es sich, Python zu lernen, weil es eine große Anzahl von Reverse-Engineering- und Exploitation-Bibliotheken gibt, die Sie direkt einsetzen können. Wenn auch noch die Metasploit-Entwickler zur Besinnung kämen und von Ruby auf Python wechseln würden, wäre unsere Community vereint.
In diesem neuen Buch behandelt Justin eine Vielzahl von Themen, die einem aufstrebenden jungen Hacker den Weg ebnen. Er zeigt, wie man Netzwerkpakete liest und schreibt, wie man im Netzwerk lauscht, aber auch was man braucht, um eine Webanwendung zu prüfen (oder anzugreifen). Er verwendet viel Zeit auf Code, der die Eigenheiten beim Angriff auf Windows-Systeme beschreibt. Es macht Spaß, »Mehr Hacking mit Python« zu lesen. Und auch wenn es aus Ihnen vielleicht keinen Super-Hacker macht, so zeigt es doch den richtigen Weg auf. Denken Sie daran, dass der Unterschied zwischen einem Skript-Kiddie und einem Profi darin besteht, ob man bloß die Tools anderer Leute nutzt oder ob man seine eigenen entwickelt.
Charlie Miller
St. Louis, Missouri
September 2014
Ich möchte meiner Familie – meiner wunderbaren Frau Clare und meinen fünf Kindern Emily, Carter, Cohen, Brady und Mason – für die Unterstützung und Toleranz danken, während ich eineinhalb Jahre meines Lebens an diesem Buch geschrieben habe. Meine Brüder, meine Schwester, meine Eltern und Paulette sorgten auch für viel Motivation, um egal was voranzutreiben. Ich liebe euch alle.
An all die Leute bei Immunity (ich würde jeden Einzelnen auflisten, wenn ich Platz genug hätte): Danke, dass ihr mich jeden Tag aufs Neue toleriert. Ihr seid eine tolle Truppe, mit der ich da arbeiten darf. An das Team von No Starch – Tyler, Bill, Serena und Leigh –: Danke für all die harte Arbeit, die Ihr in dieses Buch (und in all die anderen) gesteckt habt. Wir alle wissen das zu schätzen.
Ich möchte auch meinen Gutachtern Dan Frisch und Cliff Janzen danken. Diese Jungs haben jede einzelne Codezeile eingetippt und kritisiert, Hilfscode entwickelt, Korrekturen vorgenommen und während des gesamten Prozesses eine unglaubliche Unterstützung geboten. Jeder, der ein Buch zur Informationssicherheit schreibt, sollte sich diese Jungs ins Boot holen. Sie sind großartig und noch einiges mehr.
Für die restlichen Rabauken, die Getränke, Lacher und Gchats mit mir teilen: Danke dafür, dass ich bei euch meinen Frust über das Schreiben dieses Buches loswerden konnte.
1 Einführung
2 Ihre Python-Umgebung einrichten
2.1 Kali Linux installieren
2.2 WingIDE
3 Das Netzwerk: Grundlagen
3.1 Python-Networking – kurz und knapp
3.2 TCP-Client
3.3 UDP-Client
3.4 TCP-Server
3.5 Netcat ersetzen
3.6 Einen TCP-Proxy entwickeln
3.7 SSH mit Paramiko
3.8 SSH-Tunneling
4 Das Netzwerk: Raw Sockets und Sniffing
4.1 Ein UDP-Host-Discovery-Tool entwickeln
4.2 Paket-Sniffing unter Windows und Linux
4.3 Decodierung der IP-Schicht
4.4 ICMP decodieren
5 MIT SCAPY das Netzwerk übernehmen
5.1 E-Mail-Passwörter stehlen
5.2 ARP-Cache-Poisoning mit Scapy
5.3 PCAP-Verarbeitung
6 Hacking im Web
6.1 Die Socket-Bibliothek für das Web: urllib2
6.2 Open-Source-Webanwendungen
6.3 Brute-Forcing von Verzeichnissen und Dateien
6.4 Brute-Forcing der HTML-Formular-Authentifizierung
7 Den Burp-Proxy erweitern
7.1 Setup
7.2 Burp Fuzzing
7.3 Bing für Burp
7.4 Website-Inhalte in Passwort-Gold verwandeln
8 Command and Control per Github
8.1 Einen GitHub-Account einrichten
8.2 Module anlegen
8.3 Trojaner-Konfiguration
8.4 Einen GitHub-fähigen Trojaner entwickeln
9 Typische Trojaner-Aufgaben unter Windows
9.1 Keylogging
9.2 Screenshots
9.3 Shellcode ausführen
9.4 Sandbox-Erkennung
10 Hacking-Spaß mit dem Internet Explorer
10.1 Eine Art Man-in-the-Browser-Angriff
10.2 Daten ausschleusen per IE-COM
11 Windows-Rechte ausweiten
11.1 Voraussetzungen schaffen
11.2 Einen Prozessmonitor entwickeln
11.3 Windows-Token-Rechte
11.4 Das Rennen gewinnen
11.5 Code-Injection
12 Offensive Forensik automatisieren
12.1 Installation
12.2 Profile
12.3 Passwort-Hashes abgreifen
12.4 Direkte Code-Injection
Python-Hacker. Mit diesen beiden Wörtern können Sie mich tatsächlich beschreiben. Bei Immunity habe ich das Glück, mit Leuten zu arbeiten, die wirklich wissen, wie man in Python programmiert. Ich gehöre nicht zu diesen Leuten. Ich verbringe einen Großteil meiner Zeit mit Penetrationstests und das verlangt die rasche Entwicklung von Python-Tools, deren Fokus auf der Ausführung und der schnellen Lieferung von Ergebnissen liegt (nicht notwendigerweise auf Schönheit, Optimierung oder gar Stabilität). Im Verlauf dieses Buches werden Sie sehen, dass das meine Art der Programmierung ist, doch ich glaube, dass dies auch dazu beiträgt, mich zu einem guten Pentester zu machen. Ich hoffe, dass diese Philosphie und dieser Stil auch Ihnen helfen werden.
Während Sie das Buch durchlesen, werden Sie auch feststellen, dass ich in keines der Themen wirklich tief einsteige. Das ist durchaus gewollt: Ich versorge Sie mit dem fundamentalen Grundwissen und rege ein wenig Ihren Appetit an. Zusätzlich bringe ich einige Ideen ein und stelle Ihnen einige Übungsaufgaben, damit sich Ihre Gedanken in eine eigene Richtung entwickeln können. Ich möchte, dass Sie diese Ideen untersuchen, und freue mich, von Ihren eigenen Implementierungen, Tools und Übungsaufgaben zu hören.
Wie bei jedem technischen Buch werden Leser mit unterschiedlichem Wissen zu Python (oder generell Informationssicherheit) dieses Buch anders erleben. Einige werden sich einfach die Kapitel herausgreifen, die für ihren aktuellen Job gerade von Interesse sind, andere werden es von vorne bis hinten durcharbeiten. Als (fortgeschrittener) Anfänger in der Python-Programmierung würde ich Ihnen empfehlen, mit dem ersten Kapitel zu beginnen und nacheinander alle Kapitel durchzugehen. Sie werden dabei einige gute Bausteine kennenlernen.
Zu Beginn schaffe ich einige Netzwerk-Grundlagen (Kapitel 3) und arbeite mich langsam durch Raw Sockets (Kapitel 4) vor zur Nutzung von Scapy (Kapitel 5) und einigen interessanteren Netzwerktools. Im nächsten Teil des Buches befasse ich mich mit dem Hacking von Webanwendungen. Ich beginne mit der Entwicklung eigener Werkzeuge (Kapitel 6) und erweitere dann die beliebte Burp-Suite (Kapitel 7). Danach werden wir uns eingehend mit Trojanern beschäftigen. Das beginnt mit GitHubs »Command and Control« (Kapitel 8) und endet mit einigen Tricks, um die Windows-Rechte auszuweiten (Kapitel 11). Im letzten Kapitel nutzen wir Volatility, um einige offensive Speicherforensiktechniken zu automatisieren.
Ich versuche, die Beispiele kurz zu halten und auf den Punkt zu bringen, was auch für die Erklärungen gilt. Falls Sie Python-Neuling sind, empfehle ich Ihnen, jede einzelne Zeile einzutippen, damit sich Ihre »Coding-Muskeln« entwickeln können. Den Quellcode aller Beispiele finden Sie auf http://www.dpunkt.de/mehr-python-hacking.
Los geht‘s!
Das ist der langweiligste, aber dennoch ein sehr wichtiger Teil dieses Buches. Hier richten wir eine Umgebung ein, in der Sie Python-Programme entwickeln und testen können. Wir absolvieren einen Crashkurs zur Einrichtung einer Kali Linux-VM (virtuellen Maschine) und installieren eine nette IDE, sodass Sie alles haben, was Sie zur Entwicklung von Code benötigen. Am Ende dieses Kapitels sollten Sie alle Übungen und Codebeispiele in Angriff nehmen können, die im Rest des Buches auf Sie zukommen.
Bevor Sie loslegen, müssen Sie den VMWare Player1 herunterladen und installieren. Sie sollten auch einige Windows-VMs vorbereiten, einschließlich Windows XP und Windows 7, vorzugsweise in der 32-Bit-Version.
Kali ist der Nachfolger der von Offensive Security entwickelten BackTrack-Linux-Distribution, die von Grund auf als Penetrationstest-Betriebssystem konzipiert wurde. Es wird mit einer ganzen Reihe vorinstallierter Tools ausgeliefert und basiert auf Debian Linux, d.h., Sie können eine Vielzahl von Tools und Bibliotheken nachinstallieren.
Besorgen Sie sich zuerst ein Kali-VM-Image von der folgenden URL: http://images.kali.org/Kali-Linux-1.1.0c-vm-486.7z2. Laden Sie das Image herunter und entpacken Sie es. Durch einen Doppelklick wird es dann im VMWare Player gestartet. Der Standardbenutzername lautet root und das Passwort toor. Sie sollten in einer vollständigen Kali-Desktop-Umgebung landen (siehe Abbildung 2–1).
Abb. 2–1 Der Kali-Linux-Desktop
Zuerst wollen wir nun sicherstellen, dass die korrekte Version von Python installiert ist. Im gesamten Buch arbeiten wir mit Python 2.7. In der Shell (Applications › Accessories › Terminal) führen Sie den folgenden Befehl aus:
root@kali:~# python --version
Python 2.7.3
root@kali:~#
Wenn Sie das von mir weiter oben empfohlene Image heruntergeladen haben, wird Python 2.7 automatisch installiert. Bitte beachten Sie, dass einige Codebeispiele aus diesem Buch mit anderen Versionen von Python nicht funktionieren.
Nun wollen wir nützliche Python-Paketmanagement-Tools in Form von easy_install und pip installieren. Diese ähneln dem Paketmanager apt, da sie es erlauben, Python-Bibliotheken direkt zu installieren, ohne sie manuell herunterladen, entpacken und installieren zu müssen. Wir installieren beide Pakete durch Eingabe des folgenden Befehls:
root@kali:~#: apt-get install python-setuptools python-pip
Sobald die Pakete installiert sind, können wir einen kurzen Test machen, indem wir das Modul installieren, das wir in Kapitel 8 verwenden, um einen GitHub-basierten Trojaner zu bauen. Geben Sie den folgenden Befehl in Ihrem Terminal ein:
root@kali:~#: pip install github3.py
Die Ausgabe im Terminal sollte anzeigen, dass die Bibliothek heruntergeladen und installiert wurde.
Dann öffnen wir eine Python-Shell und prüfen, ob die Bibliothek korrekt installiert wurde:
root@kali:~#: python
Python 2.7.3 (default, Mar 14 2014, 11:57:14)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import github3
>>> exit()
Sind Ihre Ergebnisse nicht mit diesen identisch, ist Ihre Python-Umgebung nicht korrekt konfiguriert und Sie haben große Schande über uns gebracht! In diesem Fall müssen Sie sicherstellen, dass alle obigen Schritte ausgeführt wurden und die korrekte Kali-Version installiert wurde.
Denken Sie daran, dass der Code für die meisten Beispiele in diesem Buch in verschiedenen Umgebungen entwickelt werden kann, einschließlich Mac, Linux und Windows. Es gibt einige Windows-spezifische Kapitel, aber das lasse ich Sie zu Beginn des jeweiligen Kapitels wissen.
Nachdem wir nun eine virtuelle Maschine für das Hacking eingerichtet haben, wollen wir eine Python-IDE für die Entwicklung installieren.
Eigentlich bin ich kein Verfechter kommerzieller Software, doch WingIDE ist die beste IDE, mit der ich in den letzten sieben Jahren bei Immunity gearbeitet habe. WingIDE bietet alle gängigen IDE-Funktionalitäten wie Autovervollständigung und die Beschreibung von Funktionsparametern, doch sind es vor allem die Debugging-Fähigkeiten, die es von anderen IDEs abhebt. Im Folgenden gebe ich einen kurzen Überblick über die kommerzielle Version von WingIDE, aber natürlich können Sie die Version nutzen, die sich für Sie am besten eignet.3
Sie können WingIDE von http://www.wingware.com/ herunterladen; ich empfehle die Testversion (Trial), damit Sie aus erster Hand einige der Features erleben können, die in der kommerziellen Version zur Verfügung stehen.
Sie können auf jeder gewünschten Plattform entwickeln, doch zumindest am Anfang sollten Sie WingIDE auf Ihrer Kali-VM installieren. Wenn Sie meinen
Anweisungen bis hierhin gefolgt sind, sollten Sie das 32-Bit-deb-Paket für WingIDE herunterladen und in Ihrem Benutzerverzeichnis speichern. Öffnen Sie dann ein Terminal und führen Sie den folgenden Befehl aus:
root@kali:~# dpkg -i wingide5_5.0.9-1_i386.deb
Damit sollte WingIDE problemlos installiert werden. Kommt es zu Installationsfehlern, sind möglicherweise einige Abhängigkeiten nicht erfüllt. In diesem Fall führen Sie einfach den folgenden Befehl aus:
root@kali:~# apt-get -f install
Damit sollten alle fehlenden Abhängigkeiten aufgelöst und WingIDE installiert werden. Um sicherzustellen, dass es korrekt installiert wurde, starten Sie das Programm über den Kali-Desktop (siehe Abb. 2–2).
Abb. 2–2 WingIDE im Kali-Desktop starten
Öffnen Sie nun eine neue (leere) Python-Datei. Folgen Sie mir nun bei einem kurzen Überblick einiger nützlicher Features. Erst einmal sollte der Bildschirm aussehen wie in Abbildung 2–3, d.h., der Haupt-Editierbereich befindet sich oben links, und unten sind eine Reihe von Tabs aufgeführt.
Abb. 2–3 WingIDE-Layout
Nun wollen wir ein paar Zeilen einfachen Beispielcode eingeben, um einige der nützlichen Funktionen von WingIDE vorzustellen, darunter auch die Tabs »Debug Probe« und »Stack Data«. Geben Sie den folgenden Code im Editor ein:
def sum(number_one,number_two):
number_one_int = convert_integer(number_one)
number_two_int = convert_integer(number_two)
result = number_one_int + number_two_int
return result
def convert_integer(number_string):
converted_integer = int(number_string)
return converted_integer
answer = sum("1","2")
Zugegeben, dieses Beispiel ist doch arg gestellt, doch es zeigt sehr gut, wie man sich mit WingIDE das Leben leichter macht. Sichern Sie den Code unter einem beliebigen Dateinamen, klicken Sie dann auf den Menüpunkt Debug und wählen Sie dann die Option Select Current as Main Debug File, wie in Abbildung 2–4 zu sehen.
Abb. 2–4 Aktuelles Python-Skript zum Debugging auswählen
Nun setzen Sie einen Breakpunkt in der folgenden Zeile:
return converted_integer
Zu diesem Zweck klicken Sie den linken Rand an oder drücken die F9-Taste. Am Rand erscheint daraufhin ein kleiner roter Punkt. Führen Sie das Skript nun aus, indem Sie F5 drücken. Die Ausführung wird am Breakpunkt angehalten. Klicken Sie den Reiter Stack Data an und es erscheint eine Seite wie in Abbildung 2–5.
Im Reiter »Stack Data« finden wir einige nützliche Informationen, etwa den Zustand aller lokalen und globalen Variablen beim Erreichen des Breakpunkts. Das erlaubt das Debugging komplexeren Codes, bei dem die Variablen während der Ausführung untersucht werden müssen, um Fehlern auf die Spur zu kommen. Wenn Sie die Dropdown-Leiste anklicken, sehen Sie auch den aktuellen Aufrufstack (Call-Stack). Dieser sagt Ihnen, welche Funktion die Funktion aufgerufen hat, in der Sie sich gerade befinden. Sehen Sie sich den Stacktrace in Abbildung 2–6 an.
Abb. 2–5 Anzeige der Stackdaten beim Erreichen eines Breakpunkts
Abb. 2–6 Der aktueller Stacktrace
Wir können sehen, dass convert_integer von der sum-Funktion in Zeile 3 unseres Python-Skripts aufgerufen wurde. Das ist sehr praktisch bei rekursiven Funktionen, oder wenn eine Funktion von vielen verschiedenen Stellen aufgerufen wird. Die Nutzung des »Stack Data«-Tabs wird in Ihrer Karriere als Python-Entwickler sehr hilfreich sein!
Das nächste wichtige Feature ist der Tab »Debug Probe«. Dieser Tab ermöglicht es Ihnen, in eine Python-Shell zu wechseln, die innerhalb des aktuellen Kontexts beim Erreichen des Breakpunkts ausgeführt wird. Auf diese Weise können Sie Variablen untersuchen und modifizieren, aber auch Testcode schreiben, um neue Ideen auszuprobieren oder Fehler zu suchen. Abbildung 2–7 zeigt, wie man die Variable converted_integer untersucht und ihren Wert ändert.
Abb. 2–7 Lokale Variablen mit Debug Probe untersuchen und ändern
Nachdem Sie einige Änderungen vorgenommen haben, können Sie die Ausführung des Skripts mit F5 fortsetzen.
Obwohl es ein sehr einfaches Beispiel ist, zeigt es doch die nützlichsten Features von WingIDE beim Entwickeln und Debugging von Python-Skripten.4
Mehr brauchen wir nicht, um mit dem Entwickeln von Code für den Rest des Buches zu beginnen. Vergessen Sie nicht, virtuelle Maschinen als Zielmaschinen für die Windows-spezifischen Kapitel vorzubereiten, aber auch reale Hardware sollte keine Probleme bereiten.
Aber jetzt geht der eigentliche Spaß los!
Das Netzwerk ist und bleibt der attraktivste Schauplatz für einen Hacker. Ein Angreifer kann mit einfachem Netzwerkzugriff so ziemlich alles anstellen: nach Hosts scannen, Pakete einschleusen, Daten abhören, Hosts aus der Ferne entern und vieles mehr. Doch wenn Sie sich als Angreifer in die tiefsten Tiefen eines Ziels vorgearbeitet haben, könnten Sie in der Zwickmühle stecken: Sie besitzen keine Tools, um Netzwerkangriffe durchzuführen. Kein Netcat, kein Wireshark, keinen Compiler und keine Möglichkeit, einen zu installieren. Doch in vielen Fällen findet man überraschenderweise eine Python-Installation und genau da setzen wir an.
Dieses Kapitel vermittelt Grundlagen zum Python-Networking mit dem socket1-Modul. Wir werden Clients, Server und einen TCP-Proxy entwickeln und sie in unser ganz eigenes Netcat verwandeln, inklusive eigener Shell. Dieses Kapitel bildet die Grundlage für die nachfolgenden Kapitel, in denen wir ein Host-Discovery-Tool entwickeln, Cross-Plattform-Sniffer implementieren und ein Framework für entfernte Trojaner aufbauen. Los geht‘s.
Programmierern steht bei Python eine Reihe von Tools von Drittanbietern zur Verfügung, mit denen sich Server und Clients entwickeln lassen, doch das Kern-modul für all diese Tools ist socket. Es stellt alle notwendigen Teile zur Verfügung, um schnell TCP- und UDP-Clients und -Server zu schreiben, Raw Sockets zu nutzen und so weiter. Wenn es darum geht, einzudringen oder den Zugriff auf Zielmaschinen zu erhalten, braucht man nicht mehr als dieses Modul. Wir wollen mit der Entwicklung einfacher Clients und Server beginnen, also den beiden üblichen Netzwerkskripten, die Sie schreiben werden.
Bei Penetrationstest musste ich schon unzählige Male einen TCP-Client laufen lassen, um einen Dienst zu testen, Datenmüll zu senden, Fuzzing durchzuführen oder irgendwelche andere Aufgaben zu erledigen. Wenn Sie sich innerhalb der Grenzen großer Unternehmensumgebungen bewegen, bleibt Ihnen der Luxus von Netzwerktools und Compilern verwehrt und manchmal fehlen sogar die elementarsten Dinge wie Kopieren/Einfügen oder eine Internetverbindung. An diesem Punkt ist es äußerst praktisch, wenn man einen eigenen TCP-Client entwickeln kann. Doch genug geredet, lassen Sie uns programmieren. Hier ein einfacher TCP-Client.
import socket
target_host = "www.google.com"
target_port = 80
# Socket-Objekt erzeugen
➊ client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Clientverbindung herstellen
➋ client.connect((target_host,target_port))
# Einige Daten senden
➌ client.send("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n")
# Einige Daten empfangen
➍ response = client.recv(4096)
print response
Zuerst erzeugen wir ein Socket-Objekt mit den Parametern AF_INET und SOCK_STREAM ➊. Der Parameter AF_INET legt fest, dass wir mit normalen Ipv4-Adressen oder Hostnamen arbeiten, und SOCK_STREAM gibt an, dass dies ein TCP-Client wird. Dann stellen wir die Verbindung mit dem Server her ➋ und senden einige Daten ➌. Im letzten Schritt empfangen wir einige Daten und geben die Antwort (Response) aus ➍. Diese einfachste Form eines TCP-Clients ist diejenige, die Sie am häufigsten schreiben werden.
Im obigen Code nehmen wir einige Dinge über Sockets an, die Sie unbedingt beachten müssen. Unsere erste Annahme ist, dass die Verbindung immer erfolgreich hergestellt werden kann. Als Zweites nehmen wir an, dass der Server immer erwartet, dass wir zuerst Daten senden (im Gegensatz zu Servern, die erst Daten an Sie senden und dann eine Antwort erwarten). Unsere dritte Annahme besteht darin, dass der Server uns Daten immer innerhalb einer gewissen Zeitspanne zurückschickt. Diese Annahmen dienen hauptsächlich der Vereinfachung. Zwar stehen dem Programmierer verschiedene Möglichkeiten zur Verfügung, wie er mit blockierenden Sockets umgeht, Ausnahmen behandelt und Ähnliches, doch es ist bei Pentestern recht selten, solche Nettigkeiten in die schnell entwickelten Tools zu integrieren, die man zum Auskundschaften oder zur Suche nach Sicherheitslücken braucht. Deshalb verzichten wir in diesem Kapitel darauf.
Ein UDP-Client unterscheidet sich in Python nicht wesentlich von einem TCP-Client. Wir müssen nur zwei kleine Änderungen vornehmen, um Pakete in UDP-Form zu senden.
import socket
target_host = "127.0.0.1"
target_port = 80
# Socket-Objekt erzeugen
➊ client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# Einige Daten senden
➋ client.sendto("AAABBBCCC",(target_host,target_port))
# Einige Daten empfangen
➌ data, addr = client.recvfrom(4096)
print data
Wie Sie sehen, ändern wir den Socket-Typ in SOCK_DGRAM ➊, wenn wir das Socket-Objekt erzeugen. Der nächste Schritt ist einfach der Aufruf von sendto() ➋, wobei Sie die Daten übergeben sowie den Server, an den Sie diese Daten senden möchten. Da UDP ein verbindungsfreies Protokoll ist, wird nicht zuerst connect() aufgerufen. Der letzte Schritt besteht im Aufruf von recvfrom() ➌, um UDPDaten zu empfangen. Wie Sie bemerken, werden hier Daten sowie Details über den entfernten Host und Port zurückgegeben.
Auch hier ist es nicht unser Ziel, tolle Netzwerkprogrammierer zu sein. Wir wollen nur schnell, einfach und zuverlässig genug sein, um unsere täglichen Hacking-Aufgaben lösen zu können. Lassen Sie uns nun einige einfache Server entwickeln.
Die Entwicklung eines TCP-Servers ist in Python genauso einfach wie die Entwicklung eines Clients. Sie wollen eventuell eigene TCP-Server verwenden, wenn Sie Kommandozeilen-Shells schreiben oder einen Proxy entwickeln (was wir später beides tun werden). Wir beginnen mit einem normalen Multithread-TCP-Server. Hier der Code:
import socket
import threading
bind_ip = "0.0.0.0"
bind_port = 9999
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
➊ server.bind((bind_ip,bind_port))
➋ server.listen(5)
print "[*] Listening on %s:%d" % (bind_ip,bind_port)
# Das ist der Client-Handler-Thread
➌ def handle_client(client_socket):
# Ausgeben, was der Client sendet
request = client_socket.recv(1024)
print "[*] Received: %s" % request
# Ein Paket zurückschicken
client_socket.send("ACK!")
client_socket.close()
while True:
➍ client,addr = server.accept()
print "[*] Accepted connection from: %s:%d" % (addr[0],addr[1])
# Client-Thread anstoßen, um eingehende Daten zu verarbeiten
client_handler = threading.Thread(target=handle_client,args=(client,))
➎ client_handler.start()
Zu Beginn legen wir die IP-Adresse und den Port fest, an dem unser Server horchen soll ➊. Als Nächstes weisen wir den Server an, mit dem Horchen (»Listening«) zu beginnen ➋, wobei wir maximal 5 Verbindungen gleichzeitig zulassen. Der Server tritt dann in seine Hauptschleife ein, in der er auf eingehende Verbindungen wartet. Stellt ein Client die Verbindung her ➍, empfangen wir den Client-Socket in der Variablen client und die Details der Verbindung in addr. Wir erzeugen dann ein neues Thread-Objekt, das auf unsere handle_client-Funktion verweist, und übergeben das Client-Socket-Objekt als Argument. Dann starten wir den Thread, um die Clientverbindung zu verarbeiten ➎, und unsere Serverschleife ist bereit, andere eingehende Verbindungen zu behandeln. Die Funktion handle_client ➌ übernimmt den recv()-Aufruf und sendet eine einfache Nachricht an den Client zurück.
Wenn wir den vorhin entwickelten TCP-Client nutzen, können wir einige Testpakete an den Server senden und sollten eine Ausgabe wie die folgende erhalten:
[*] Listening on 0.0.0.0:9999
[*] Accepted connection from: 127.0.0.1:62512
[*] Received: ABCDEF
Das war‘s! Wirklich einfach, aber dennoch ein sehr nützliches Stück Code, das wir in den nächsten Abschnitten erweitern werden, wenn wir einen Ersatz für Netcat und einen TCP-Proxy entwickeln.
Netcat ist das Schweizer Messer aller Netzwerker, weshalb es kein Wunder ist, dass clevere Systemadministratoren es von ihren Systemen entfernen. Bei mehr als einer Gelegenheit bin ich auf Server gestoßen, bei denen kein Netcat installiert war, Python aber schon. In diesen Fällen ist es sinnvoll, einfache Netzwerkclients und -server zu entwickeln, mit deren Hilfe Sie Dateien hochladen können oder Zugriff auf die Kommandozeile erhalten. Wenn Sie über eine Webanwendung eingedrungen sind, lohnt sich ein Python-Callback als zusätzlicher Zugang auf jeden Fall, ohne zuerst einen Ihrer Trojaner oder ein Hintertürchen installieren zu müssen. Ein Tool wie dieses zu entwickeln ist auch eine ausgezeichnete Python-Programmierübung, also lassen Sie uns beginnen.
import sys
import socket
import getopt
import threading
import subprocess
# Einige globale Variablen definieren
listen = False
command = False
upload = False
execute = ""
target = ""
upload_destination = ""
port = 0
Hier importieren wir nur die notwendigen Bibliotheken und setzen einige globale Variablen. Nichts wirklich Schwieriges.
Nun wollen wir unsere main-Funktion definieren, die die Kommandozeilenargumente verarbeitet und die restlichen Funktionen aufruft.