
DNS-Covert-Channel-Implantat für Red Teams.
WEASEL ist ein kleiner In-Memory-Implant, der Python 3 ohne Abhängigkeiten nutzt. Der Beacon-Client sendet eine kleine Menge identifizierender Informationen über seinen Host an eine DNS-Zone, die Sie kontrollieren. Der WEASEL-Server kann Clients beauftragen, vorgefertigte oder beliebige Befehle auszuführen.
WEASEL ist ein Stage-1-Payload, das schwer zu erkennen sein soll und nützlich ist, um wieder Zugriff zu erlangen, wenn Ihre lauten, vollwertigen Stages entdeckt wurden.
Status
Siehe die Nutzung im Client-README und Server-README für spezifische Anweisungen.
Um den Server oder Client zu starten, führen Sie die Skripte direkt aus oder übergeben Sie sie dem Python-Interpreter.
Stellen Sie sicher, dass die C2-Domänen jeweils einen NS-Eintrag mit der IP-Adresse des Hosts haben, auf dem server.py ausgeführt wird.
WEASEL benötigt Python 3.6+.
Der Client ist eigenständig und verwendet nur Standardbibliotheken, daher kann er auf macOS, Linux usw. ausgeführt werden.
Der Server hat einige Abhängigkeiten von pip, die in server/requirements.txt enthalten sind. Der Server sollte unter Linux ausgeführt werden, aber es spricht nichts dagegen, ihn unter macOS oder anderen *nix-Systemen zu betreiben.
Es ist in diesem Fall nicht nötig, den Beacon zu obfuskatieren und zu minimieren. Print-Anweisungen bleiben erhalten. Wie unter „Verwendung“ oben, stellen Sie sicher, dass NS-Einträge für die Domäne(n) in servers in beacon.py auf die IP-Adresse von server.py zeigen.
Auf dem Server-Host:
sudo python3 server.py
Auf dem Opfer-Host (kann derselbe wie der Server sein):
python3 beacon.py
Sie müssen nichts davon verstehen, um WEASEL zu nutzen.
Beacon kommuniziert über DNS mit AAAA-Anfragen und -Antworten. Es verwendet keine TXT-Einträge, da diese dafür bekannt sind, von DNS-Malware und -Tunnel genutzt zu werden. Blue Teams haben oft DNS-Tunnel-Erkennungen, die bei großen TXT-Anfragen alarmieren.
Die Client-Seite benötigt keine Root-Rechte, verwendet keine Raw-Sockets und erstellt keine fehlerhaften DNS-Pakete. Es werden reguläre, vom System und der Sprache bereitgestellte Schnittstellen für DNS-Anfragen verwendet. Die Informationen sind in den Einträgen selbst kodiert + verschlüsselt.
Dieser Beacon ist als langsam und leise mit geringer Bandbreite konzipiert. Er soll uns mitteilen, auf welchen Hosts er sich befindet, und uns eine Möglichkeit geben, bei Bedarf weitere Stages zu starten – und nicht mehr. Obwohl er beliebige Befehle unterstützt, ist er nicht als reguläre interaktive Shell oder Kommunikationskanal gedacht.
WEASEL ist eine Stage 1, die Sie laufen lassen, um dauerhaften Zugriff zu gewährleisten, während Ihre vollwertigen (und daher lauteren) Stages entdeckt werden.
WEASEL war ursprünglich für Server mit hoher Betriebszeit gedacht, bei denen wir einen zuverlässigen Fußpunkt/Ausnutzungsvektor hatten. Die Umgehung forensischer Untersuchungen hatte hohe Priorität. Daher verfügt es über keine nativen Persistenzfunktionen.
Sie können es persistent machen, indem Sie seine Ausführung zu Ihrer bevorzugten Persistenztechnik hinzufügen – dies bleibt dem Leser als Übung überlassen :)
Eine Anfrage (vom Client) ist eine einzelne AAAA-Abfrage für einen Namen, der wie folgt formatiert ist:
<Präambel><Daten>.<Stream>.<Sitzung>.domain.tld
Die Präambel ist 2 Byte lang. Präambel[0] ist die Sequenznummer dieses Pakets. Präambel[1] ist die Gesamtanzahl der Pakete in diesem Stream.
Daten sind auf 50 Byte (konfigurierbar) begrenzt und enthalten die Nutzlast. Die Nutzlast ist mit einem benutzerdefinierten Alphabet base32-kodiert.
Zuerst werden alle 'w'-Zeichen durch '-' ersetzt.
Als nächstes wird das Padding-Zeichen von '=' zu 'w' geändert, um dem DNS-Zeichensatz [a-z0-9] und [-] zu entsprechen.
Wir ersetzen '=' nicht direkt durch '-', da das Padding immer am Ende der Zeichenkette steht und ein Hostname, der auf '---' endet, sowohl verdächtig als auch nicht RFC-konform ist. Auf diese Weise endet eine Zeichenkette mit Padding auf 'www', was weniger verdächtig und RFC-konform ist.
Eine Antwort (vom Server) besteht aus einem oder mehreren AAAA-Antworten.
Jede AAAA-Antwort ist eine 16 Byte lange verschlüsselte Nutzlast, die als IPv6-Adresse mit socket.inet_ntop dargestellt wird. Antworten in einer DNS-Antwort behalten ihre Reihenfolge während der Übertragung nicht bei, daher werden sie wie die Client-Anfragen sequenziert und wieder zusammengesetzt.
Die Transportnutzlast ist eine Zeichenkette von Datenelementen, die durch ein ^-Zeichen getrennt sind.
Anfragen und Antworten folgen diesem Format:
<Typ>|<Daten>
| Typ | Bedeutung (Absender) | AKA | Daten |
|---|---|---|---|
| 0 | Bestätigt | ACK | Zufälliges Hex |
| 1 | Checkt ein (Client) | PING | Zufälliges Hex |
| 2 | Beende dich selbst (Server), Beende mich selbst (Client) | FIN | |
| 3 | Initialisierungsnachricht (Client) | SYN | Version|Hostname|Kernel |
| 4 | Wieder verbinden (Server) | RST | |
| 5 | Callback-Intervall setzen (Server) | Sekunden | |
| 6 | Netzwerkschnittstellendaten abrufen | eth0 1.2.3.4/24\neth1 fe80:::/64\n... | |
| 8 | Beliebigen Python3-Code bis 666 Byte ausführen (Server), die ersten 400 Byte der Ausgabe zurückgeben (Client) | EVAL | Python3-One-Liner-Skript |
| 9 | Beliebigen Befehl bis 666 Byte ausführen (Server), die ersten 400 Byte der Ausgabe zurückgeben (Client) | EXEC | Bash-Befehl |
Sitzungen sind langlebig: Ein Client initiiert eine Sitzung, wenn der Beacon zum ersten Mal ausgeführt wird, und diese Sitzung sollte für die gesamte Zeit bestehen bleiben, in der der Beacon auf diesem Client aktiv ist. Beachten Sie, dass die Sitzungsdaten, da der Beacon im Speicher und nicht persistent ist, im Speicher des Python-Prozesses gespeichert werden. Jeder neue Aufruf des Beacons initiiert eine neue Sitzung.