Incomplete; Probably won’t finish

Checkpoint 1: “Air-gapped”

Points 10

The FBI infiltrated SHINY SCORPION’s command & control network!

They’ve passed along the victim database related to the campaign that targeted Keep it Simple Security (KiSSec). They’ve also included a Python script that can deobfuscate and parse the ransomware config.

FBI intelligence indicates that it should be possible to undo the ransomware’s encryption using the information stored in these files!

Before we start any decryption, though, they suggest finding our unique victim ID.

We were given a zip containing most files we would need. In the FBI directory was a readme, a config parser, and the database of victims that Shiny Scorpion had exploited, клиенты.db . I opened the binary using https://sqliteviewer.app/ to make the db easier to parse. There were three columns: id, amt, and the key .

id = victim id
amt = money to pay
key = encoded RSA private key

I found a record that looked familiar: the id was the address that our breached company was to send $500,000 worth of bitcoin to as stated in ransom.txt. image Flag: 14hahahaEvMFqrCd2J9vsNjaUhjEdYCsTnG3r

Checkpoint 2: The last easy one for a while

Points: 10

Now that we know our “customer” ID, we should be able to find the ransomware’s decryption key.

Flag

CTFd has some limitations that make it impossible to submit the key directly 😞

Instead, please generate and submit a SHA256 checksum of the key.

Format

SHA256 digest, 64 hexadecimal digits, case-insensitive

When hashing, ensure that you don’t accidentally introduce any leading or trailing whitespace around the key. Any changes, no matter how small, will generate a completely different hash. Be careful copy/pasting!

I took the key from the user db. I noticed that there was a repeating string at the beginning and end of the key: YF0gY . As the malware config used a public key and knowing that a private key started with -----BEGIN RSA PRIVATE KEY-----, I came to the conclusion that it had to be obfuscated. The = hinted towards base64. I tried it with ROT13, and it worked!

From there, I got the sha256 checksum.

cat key.txt | sha256sum

flag: a92bbe46078d2295353bad012292f84ee0564ffb89f7bbe7cb945b8cbf1d1e51

Note: Check the appendix for the encoded decoded private key.

Checkpoint 3: Infinite monkey theorem

Points: 10

Now that we’ve got the key, we should be able to make some headway on those encrypted files.

The README would be a great place to start!

Flag format

cp3:rest_of_the_flag, including the cp3: part, case-sensitive

  • Tried just uploading the file in cyberchef and decrypting with cyberchef, but didn’t work because the message length was invalid.
  • RSA is used to encrypt messages that are shorter than the modulus of the public key.
-----BEGIN RSA PRIVATE KEY-----
RSAPrivateKey ::= SEQUENCE {
  version           Version,
  modulus           INTEGER,  -- n
  publicExponent    INTEGER,  -- e
  privateExponent   INTEGER,  -- d
  prime1            INTEGER,  -- p
  prime2            INTEGER,  -- q
  exponent1         INTEGER,  -- d mod (p-1)
  exponent2         INTEGER,  -- d mod (q-1)
  coefficient       INTEGER,  -- (inverse of q) mod p
  otherPrimeInfos   OtherPrimeInfos OPTIONAL
}
-----END RSA PRIVATE KEY-----

As the private key was 4096, the maximum length that a message could be encrypted is 512 bytes.

  • Decrypted with the first 512 bytes:
L3NmBaEbnKAsp2uiqJkxK2WyK3WuozEioFRuVFRuVFR=
xjgufagfCj+xBeAm5brk4D==

From base64 ROT13: flag: cp3:this_should_be_random!!!!!!!

References

Checkpoint 4: Call for backup

Points: 10

We need to decrypt the rest of the README.

It should contain contact information for the contractors that originally set this backup system up.

What is the phone number for their emergency hotline?

Key : cp3:this_should_be_random!!!!!!! IV: “ a²{l?¤:³s懱á

AES Decrypt CBC/NoPadding

flag: +1 (123) 867-5309

Checkpoint 5: Raise the flag.txt

Points: 10

No luck with the contractors yet; even in this emergency their fees were still deemed too high.

The recovery key’s not in the README, so we need to decrypt the rest of the files for them anyways.

Flag format

cp5:the_rest_the_flag, with or without the cp5 part, case-insensitive

in keyfile bin:

RSA Decrypt the first 512 bytes: cf076bf736b981a70b33e3480127572ea1be1beb97ba2e0 f601f99df6bacac9dd1dd6e7f113cb786

mjqe9mn5tnpYZ+AVNFqKYdT+T+hKhv4XQTrNURq+tb8=
LO+M32hfeW3E3J5/RGl3ut==

base64

Ïk÷6¹§3ãH'W.¡¾뗺.
g€G~‚`™ßk¬¬ÑÝn<·†

Convert from base 64 Kinda stuck on this. Idea so far:

  • Need to decrypt files with RSA key and AES. However, so far, it just isn’t working.
  • What I can do so far: Extract the base64 with the RSA key.
    • Need to make sense of wtf the key is supposed to be
  • Decrypt with AES
  • Get rid of first 512 bytes maybe of the decrypted text.

Python Script:

from Crypto.Cipher import AES

def __unpad(plain_text):
    last_character = plain_text[len(plain_text) - 1:]
    return plain_text[:-ord(last_character)]

for i in range(1, 102):
    with open(f"cyberchef/{i}.txt", "r") as aesFile:
        aesData = aesFile.read()
        aesKey = bytearray.fromhex(aesData[:64])
        aesIV = bytearray.fromhex(aesData[64:])
        cipher = AES.new(aesKey, AES.MODE_CBC, iv=aesIV)
        numString = str(i).rjust(4, "0")
        with open(f"old_desktop/desktop cleanup.7z.{numString}.sting", "rb") as cipherFile:  
            ciphertext = cipherFile.read()
            ciphertext = ciphertext[512:]
            plaintext = cipher.decrypt(ciphertext)
            
            with open(f"decrypted_stuff/desktop cleanup.7z.{numString}", "wb") as plainFile:
                plainFile.write(__unpad(plaintext))
# plaintext = cipher.decrypt(ciphertext)

flag : cp5:i_sure_hope_you_didn't_decrypt_this_manually

Checkpoint 6: Are we there yet?

flag: MFWG233TORPXI2DFOJSSCIJBEE======

Checkpoint 7: El plan