Contents

FCSC2023 - Ransomémoire

This challenge of the FCSC in the forensic category was divided into 4 parts. Looking back, this was the hardest one I found in this category. Firstly, it was necessary to retrieve fairly basic information about the system from a memory dump. Then, we had to find a deleted file and decrypt it by reversing the code of a malicious executable. Next, we tried to recover information about C2 Meterpreter communications. Finally, we had to find the connection informations of the C2.

SHA256(fcsc.7z) = 754cb093af343356827d650270f9faa56cc4c44f44243ea08590edb1bc270b5e

Ransomémoire 0/3 - Pour commencer

Description

You are about to analyze a memory dump and you note down some information about the machine before diving into the analysis:

  • username,
  • machine name,
  • browser used.

The flag is in the format FCSC{<username>:<machine name>:<browser name>} where :

  • <username> is the name of the user who uses the machine,
  • <machine name> is the name of the analyzed machine, and
  • <browser name> is the name of the browser currently running.

Resolution

Since this is a Windows memory dump, I immediately used Volweb to help me more easily observe the information in the rest of the challenge. While the analysis was running, I performed the actions manually.

/Ransomemoire/d3e9b9d3fa0a39b0db5aa06010dacfdc.png

To discover the name of the browser currently running, we use the windows.pslist module from volatility3, which allows us to find Brave as browser.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ python3 vol.py -f fcsc.dmp windows.pslist
PID     PPID    ImageFileName   Offset(V)       Threads Handles SessionId       Wow64   CreateTime      ExitTime        File output
[...]
4072    3928    brave.exe       0x818688060300  31      -       1       False   2023-04-17 17:21:31.000000      N/A     Disabled
5064    4072    brave.exe       0x8186872b8300  8       -       1       False   2023-04-17 17:21:39.000000      N/A     Disabled
3952    4072    brave.exe       0x818687ff6080  14      -       1       False   2023-04-17 17:21:44.000000      N/A     Disabled
4060    4072    brave.exe       0x818681344080  12      -       1       False   2023-04-17 17:21:44.000000      N/A     Disabled
2844    4072    brave.exe       0x818688773080  7       -       1       False   2023-04-17 17:21:44.000000      N/A     Disabled
5500    4072    brave.exe       0x8186886980c0  15      -       1       False   2023-04-17 17:21:46.000000      N/A     Disabled
[...]

We can retreive the username of the last user logged into the system using HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\LastUsedUsername as registry key or HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\LastLoggedOnUser for the last logged on SAM user. However, neither of these could be retrieved using volatility. We searched the user who have used the system by listing the HKU hives present in C:\Users\<Username>\ntuser.dat. This yields the username Admin

1
2
3
4
5
6
7
8
9
$ python3 vol.py -f fcsc.dmp windows.registry.printkey --key "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\LastUsedUsername"
$ python3 vol.py -f fcsc.dmp windows.registry.printkey --key "SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\LastLoggedOnUser"
$ python3 ~/ctf/forensic/volatility3/vol.py -f fcsc.dmp windows.registry.hivelist

Offset  FileFullPath    File output
[...]
0xe306cd2cd000  \??\C:\Users\Admin\ntuser.dat   Disabled
0xe306cd2ca000  \??\C:\Users\Admin\AppData\Local\Microsoft\Windows\UsrClass.dat Disabled
[...]

Finally, to retrieve the name of the machine, there is the HKLM\SYSTEM\CurrentControlSet\Control\ComputerName key, but once again, this returns nothing. Knowing that computer names by default start with DESKTOP- under Windows, a good old strings/grep works perfectly. A smarter way would have been to grep on COMPUTERNAME.

1
2
3
4
5
6
7
8
$ python3 vol.py -f fcsc.dmp windows.registry.printkey --key "SYSTEM\CurrentControlSet\Control\ComputerName"

$ strings fcsc.dmp| grep "DESKTOP-" | head
3208    728     x64     DESKTOP-PI234GP\Admin   sihost.exe
[...]

$ strings fcsc.dmp| grep "COMPUTERNAME" | head
COMPUTERNAME=DESKTOP-PI234GP

Update : It seems that using ControlSet001\Control\ComputerName\ComputerName you can retrieve the computer name with volatility.

Flag

FCSC{Admin:DESKTOP-PI234GP:Brave}

Ransomémoire 1/3 - Mon précieux

Description

You were looking at your beautiful cat pictures when suddenly, your super secret file on your desktop changed its extension and became unreadable…

You took a memory dump to understand what happened, in order to recover this precious file.

Resolution

Looking at files on the desktop in the memory dump, we don’t have much information except only th (9).webp which contains nothing when dumped.

/Ransomemoire/fb1876b78339e15e15d32d8a8faf8d3b.png

Analyzing the files present on the disk, it is impossible to find a trace of the $USNJrnl file, which contains NTFS transactions and therefore probably the name of the encrypted file. We turn to the $MFT with the windows.mftscan module of volatility, unfortunately it does not display the path of the files. It is therefore impossible to sort by hand.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$ python3 ~/ctf/forensic/volatility3/vol.py -f fcsc.dmp windows.mftscan

Offset  Record Type     Record Number   Link Count      MFT Type        Permissions     Attribute Type  Created Modified        Updated Accessed        Filename

0x81867fcb8450  FILE    242429  65535   File    Archive FILE_NAME       2023-04-04 18:11:47.000000      2023-04-04 18:11:47.000000      2023-04-04 18:11:47.000000      2023-04-04 18:11:47.000000      SPACED~1.SYS
* 0x81867fcb84c8        FILE    242429  65535   File    Archive FILE_NAME       2023-04-04 18:11:47.000000      2023-04-04 18:11:47.000000      2023-04-04 18:11:47.000000      2023-04-04 18:11:47.000000      spacedump.sys
0x81867fcb8850  FILE    242430  2       File    N/A     STANDARD_INFORMATION    2023-04-04 18:03:39.000000      2023-04-04 18:03:29.000000      2023-04-04 18:03:33.000000      2023-04-04 18:03:39.000000      N/A
* 0x81867fcb88b0        FILE    242430  2       File    Archive FILE_NAME       2023-04-04 18:03:39.000000      2023-04-04 18:03:39.000000      2023-04-04 18:03:39.000000      2023-04-04 18:03:39.000000      MSFT_M~1.WPR
* 0x81867fcb8928        FILE    242430  2       File    Archive FILE_NAME       2023-04-04 18:03:39.000000      2023-04-04 18:03:39.000000      2023-04-04 18:03:39.000000      2023-04-04 18:03:39.000000      MSFT_MpPerformanceRecording.wprp
* 0x81867fcb8c50        FILE    242431  0       File    Archive FILE_NAME       2023-04-04 17:48:08.000000      2023-04-04 17:48:08.000000      2023-04-04 17:48:08.000000      2023-04-04 17:48:08.000000      spacedump.sys

We try to dump the tree $MFT files still in the memory dump to analyze them. Once again, a failure because the extraction must not be perfect with volatility, indeed it is impossible to open the file in MFT Explorer and parsing with MFTECmd does not work too.

/Ransomemoire/126c859be372c8c08c989f16c3af8428.png

We can try to see if it is possible to recover information with Brave history about the user activity.

/Ransomemoire/960603e9231131eb2d1e66a0e2a0a996.png

After dumping the file, we open the sqlite3 database with SQLiteBrowser. The downloads table indicates that there were 10 downloaded images.

/Ransomemoire/04349f7bbb29885f591cdcdee5154b8d.png

Going into the downloads_url_chains table, we find the download URLs, which confirms that they are indeed pictures of cats.

/Ransomemoire/2dd65d5368e1d6da426dbab48eb542ef.png

In the downloads table, the start_time column is not in the classic Unix epoch format. To convert this time, we will use a customized SQL query based on a question asked on community.brave.com.

1
2
3
SELECT  d.current_path, du.url , datetime(d.start_time / 1000000 + (strftime('%s', '1601-01-01')), 'unixepoch', 'localtime') AS start_time
FROM downloads d
LEFT JOIN downloads_url_chains du on d.id = du.id

/Ransomemoire/16b1c9d74261882559ce58414a2110a7.png

We see that the 10 images were downloaded between 5:22 pm and 5:24 pm, but this does not help us any further in finding the encrypted file. So, we go back to the forensic basic strings/grep.

1
2
3
4
5
6
7
8
9
$ strings fcsc.dmp | grep -i 'Users\\Admin\\Desktop -C 5
[...]
3stdapi_fs_file
C:\Users\Admin\Desktop\chats.odt
47356039989504321872891306727343
61376899975370051322534324446423
3stdapi_fs_file
C:\Users\Admin\Desktop\flag.fcsc
[...]

We observe two files chats.odt and flag.fcsc, as well as two lines stdapi_fs_file.

Searching for this character string on Internet, we find that it is a class implemented by Meterpreter.

By analyzing the $MFT again, searching for these 2 files, we understand that the file flag.fcsc has been encrypted into flag.fcsc.enc.

1
2
3
4
5
6
7
Offset  Record Type     Record Number   Link Count      MFT Type        Permissions     Attribute Type  Created Modified        Updated Accessed        Filename

0xcc04be15b450  FILE    102253  1       File    N/A     STANDARD_INFORMATION    2023-04-17 17:23:45.000000      2023-04-17 17:23:46.000000      2023-04-17 17:23:46.000000      2023-04-17 17:23:48.000000      N/A
* 0xcc04be15b4b0        FILE    102253  1       File    Archive FILE_NAME       2023-04-17 17:23:45.000000      2023-04-17 17:23:45.000000      2023-04-17 17:23:45.000000      2023-04-17 17:23:45.000000      chats.odt
0xcc04cd429450  FILE    96165   2       File    N/A     STANDARD_INFORMATION    2023-04-17 17:23:45.000000      2023-04-17 17:23:50.000000      2023-04-17 17:23:50.000000      2023-04-17 17:23:50.000000      N/A
* 0xcc04cd4294b0        FILE    96165   2       File    Archive FILE_NAME       2023-04-17 17:23:45.000000      2023-04-17 17:23:50.000000      2023-04-17 17:23:50.000000      2023-04-17 17:23:50.000000      FLAGFC~1.ENC
* 0xcc04cd429528        FILE    96165   2       File    Archive FILE_NAME       2023-04-17 17:23:45.000000      2023-04-17 17:23:50.000000      2023-04-17 17:23:50.000000      2023-04-17 17:23:50.000000      flag.fcsc.enc

We create a yara rule to find in which process we can find traces of these files or Meterpreter.

1
2
3
4
5
6
7
8
9
rule flag_plz
{
    strings:
        $chats = "chats" ascii wide
        $fcsc = "fcsc" ascii wide
        $meterpreter = "stdapi_" ascii wide
    condition:
        any of them
}

The windows.vadyarascan module is used to scan processes in the memory dump looking for our strings.

 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
$ python3 vol.py -f fcsc.dmp windows.vadyarascan --yara-file ransomemoire.yara
Volatility 3 Framework 2.4.2
Progress:  100.00               PDB scanning finished
Offset  PID     Rule    Component       Value

0x24d2df4d026   108     flag_plz        $chats  63 00 68 00 61 00 74 00 73 00
0x24d2df4d42e   108     flag_plz        $fcsc   66 00 63 00 73 0 63 00
0x24d2fbf911c   108     flag_plz        $chats  63 68 61 74 73
0x255ad8dce08   1484    flag_plz        $chats  63 68 61 74 73
0xdf57e2        3928    flag_plz        $fcsc   66 00 63 00 73 00 63 00
0x91b6ec6       3928    flag_plz        $fcsc   66 63 73 63
0x91b7f52       3928    flag_plz        $chats  63 00 68 00 61 00 74 00 73 00
0xc4a189e       3928    flag_plz        $chats  63 68 61 74 73
0xb7335f0ac8    4568    flag_plz        $chats  63 00 68 00 61 00 74 00 73 00
0x1bdaa63eac2   4568    flag_plz        $fcsc   66 00 63 00 73 00 63 00
0x20dc71cf428   5720    flag_plz        $chats  63 00 68 00 61 00 74 00 73 00
0x22d80f4ca9c   6424    flag_plz        $fcsc   66 63 73 63
0x22d80f4d007   6424    flag_plz        $chats  63 68 61 74 73
0x22d828ff990   6424    flag_plz        $meterpreter    73 74 64 61 70 69 5f
0x2171ff5fc26   7704    flag_plz        $chats  63 00 68 00 61 00 74 00 73 00
0x217358900f1   7704    flag_plz        $meterpreter    73 74 64 61 70 69 5f
0x2174c7df08d   7704    flag_plz        $chats  63 68 61 74 73
0x1929bb175f8   620     flag_plz        $chats  63 00 68 00 61 00 74 00 73 00
0x1929dfa1e98   620     flag_plz        $chats  63 68 61 74 73
0x25c0c8f5fb7   6936    flag_plz        $fcsc   66 63 73 63
0x402054        5540    flag_plz        $fcsc   66 00 63 00 73 00 63 00
0x1c7940e0036   4072    flag_plz        $chats  63 68 61 74 73
0x5d50008d8364  4072    flag_plz        $chats  63 00 68 00 61 00 74 00 73 00
0x169835c12c6   4160    flag_plz        $chats  63 00 68 00 61 00 74 00 73 00
0x2610010dfc5   4160    flag_plz        $chats  63 68 61 74 73
0xe1eb1faec6    7684    flag_plz        $chats  63 00 68 00 61 00 74 00 73 00
0x258f06d6c66   7684    flag_plz        $fcsc   66 63 73 63
0x258f06d6ca3   7684    flag_plz        $fcsc   66 00 63 00 73 00 63 00
0x258f06fe0b1   7684    flag_plz        $chats  63 68 61 74 73
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ cat ransomemoire_result | awk '{print $2" "$4}' | sort -n | uniq -c
[...]
      5 108 $chats
      2 108 $fcsc
     18 620 $chats
      3 1484 $chats
     14 3928 $chats
     29 3928 $fcsc
      6 4072 $chats
    869 4160 $chats
     14 4568 $chats
     12 4568 $fcsc
      2 5124 $chats
     14 5540 $fcsc
     32 5720 $chats
      5 6424 $chats
      2 6424 $fcsc
      6 6424 $meterpreter
      2 6936 $fcsc
      6 7684 $chats
     54 7684 $fcsc
      3 7704 $chats
      1 7704 $meterpreter

Analyzing the number of occurrences of each string per process, we notice that the stdapi_ is the most present one in the process VBoxService.exe (6424). Moreover, with the windows.malfind module, this same process comes up as an alert because it has a memory region in RWX. We see that the beginning starts with fc 48 89, which is typical for Meterpreter shellcode. If you have done malware development, you can also recognize the instruction mov rdx, qword ptr gs:[rdx + 0x60] with the gs segment register which is used to access the TEB on Windows. Then, the TEB pointer is dereferences to get the pointer to the PEB, etc. The VBoxTray process appears to be infected by a Meterpreter shellcode.

/Ransomemoire/211c15a1f514b089b465508890b02900.png

Furthermore, we can observe that chats string is present 869 times in process 4160, which is normal since it is the Brave process, the same one that was probably used to search for cat images.

For fcsc string, we can see that there are 54 occurrences in process 7684 and 29 in 3928. These processes are actually SearchProtocolHost.exe and explorer.exe, respectively, which seems logical since the former is related to file indexing and the latter to file navigation. However, the 14 occurrences for process 5540 is suspicious because they come from svchost.exe. Upon inspecting the command line of this process, we see that the file is being executed from C:\Windows\Temp instead of C:\Windows\System32, and with no arguments as it should.

/Ransomemoire/4cc99f8bd17a3a0ff2ff30338a32e70b.png

The mistake here was forgetting to check the command line of all processes with windows.cmdline at the beginning, which would have allowed us to reach this step more quickly

We could also identify the fact that this was not the same executable as the other svchost processes because the base address is different.

/Ransomemoire/f1a7a6687a31fe5f80d14bd81639e69a.png

/Ransomemoire/5a1e0c0f9abc0dea837616169ae1af6d.png

Then, we dump the process and analyze it in IDA.

1
2
3
$ python3 vol.py -o svchost  -f fcsc.dmp windows.dumpfiles --pid 5540
$ file svchost/file.0x818687285610.0x818688495050.ImageSectionObject.svchost.exe.img
[...] PE32+ executable (GUI) x86-64 (stripped to external PDB), for MS Windows, 5 sections

The problem is that upon opening this executable, it doesn’t seem to be complete, as we can’t find anything at byte_405125.

/Ransomemoire/1f6a332bfe7a57b45b5d8f4b3060b8d1.png

There are 2 options available to you at this point.

The first is to use volatility2, but since we don’t want to search for a profile, we’ll go directly to the second solution MemProcFS.

We run the command MemProcFS.exe -device fcsc.dmp -forensic 1, which will simulate a file system from the memory image. We can easily retrieve the executable associated with the svchost process.

/Ransomemoire/d8766b1471ab459b9c75db4a1905d928.png

When opening this executable, we have a complete PE this time.

/Ransomemoire/ce69a7af3af18f81bba60dd004b854fe.png

In the main function, we will generate a key for each file on the desktop. Then encrypt those ending with .fcsc.

/Ransomemoire/d54d8f765b81c024564b31ae9ba08a75.png

The key generation function will write a random 100 bytes key to a file C:\Windows\Temp\MsCmdRun%d.log (%d being incremented for each file present on the desktop).

/Ransomemoire/988569230a953bef051494eae22e40f5.png

The encryption function will read the first 100 bytes of the file, then XOR the initial text, the key, and the key ID. The result will be rewritten to the file, which will then be moved to <filename>.enc.

/Ransomemoire/d3ccfc3761dd8ac6835ca5476edd4e5a.png

Since, the file fcsc.flag.enc is small enough (inferior to 1024 bytes), his content must be in the resident data of the $MFT. Although the file extracted with volatility3 seems corrupted, it is possible to open it in 010 Editor which has a plugin to parse the $MFT. By searching for fcsc.flag.enc, we recover the 71 bytes of the file in the resident data.

/Ransomemoire/7d807b62bea049d9e2189ac3e897a7b8.png

fcsc.flag.enc : 3b6517196403719fdd1a30ec37ba83c91bb044c98d054588ff4140d632e561095ff23207446a8d05c7fe822f22769a0832287aadff90c84d96ca99541c2c58f77a8be5c55d515a

In the memory dump, volatility only finds 2 files, whose keys do not seem to work.

  • C:\Windows\Temp\MsCmdRun19.log
  • C:\Windows\Temp\MsCmdRun20.log

We can continue to use the $MFT to recover the other files (but some are missing 0, 1, and 5). Alternatively, with MemProcFS, it is possible to navigate as a file system to find them.

/Ransomemoire/21de56302e537829c36d2e276b1abb08.png

We can test each key one by one in CyberChef as there are few keys. We find that the correct key corresponds to the file MsCmdRun14.log.

We could guess it because there were 14 files on the desktop.

/Ransomemoire/7658058a59e8f6f291c06ca8c14eca7d.png

Flag

FCSC{776f25d811bf9ac262143d0f1fa97c382f7b5972121b37d0361c7d7ad1b27079}

Ransomémoire 2/3 - Début d’investigation

Description

You were able to recover your precious file. You are now investigating the origin of this encryption.

The flag is in the format FCSC{<pid>:<protocol>:<port>} where :

  • <pid> is the ID of the process that deposited and executed the encryptor, and
  • <protocol> and <port> are the parameters of the connection with the C2.

Resolution

In this part, we are trying to first find the PID of the process that executed svchost.exe (5540), which is 6424 (VBoxTray.exe) that we have already seen earlier as it contains a Meterpreter shellcode.

/Ransomemoire/dc12d0251ca34dbf250c2e206df9533a.png

We will dump the memory section that contains the shellcode using the windows.malfind module.

1
$ python3 vol.py -f fcsc.dmp windows.malfind --pid 6424 --dump

By searching for the constants in the shellcode, we can think that it is the assembly code of migrate.asm.

/Ransomemoire/d2fd3ee3f0eacd218753446f61e7da25.png

However, upon closer inspection, we can see that in our code, the line mov rdi, rax is actually an xchg rax, rdi.

/Ransomemoire/27537de869e66a2043ece5ce0ebb7570.png

This means that it corresponds to the assembly code present in migrate_tcp_x64.rb.

All that’s left is to find the port, for which we will use string/grep.

1
2
3
$ strings -el ransomemoire/shellcode_ransomemoire.bin | grep "tcp" -C 2
[...]
tcp://:8080

Flag

FCSC{6424:tcp:8080}

Ransomémoire 3/3 - Doppelgänger

Description

You don’t understand how the agent you found in Ransomémoire 2/3 - Début d'investigation ended up on the machine. You suspect the presence of a sleeping agent, hiding in memory…

The flag is in the format FCSC{<pid>:<ip>:<port>} where :

  • <pid> is the ID of the malicious process and
  • <ip> and <port> are the parameters of the connection with the C2.

Resolution

First, we look into the process doppelgänging technique, which is a process injection technique. We learn from MITRE that this technique involves launching a legitimate executable and then replacing it with a malicious one.

/Ransomemoire/a0252b8e79141675c936249da28d9bc3.png

The base address of the process will therefore be different from other processes coming from the same executable. Looking at the NetGraph of VolWeb, we see that there are very few connections, and most public IPs can quickly be excluded as legitimate in sandbox reports.

/Ransomemoire/41fc9cbadef180abfdf2d1cc59208ed4.png

We will focus on the Brave processes because that would be the best place to hide a C2 stream.

Checking the base addresses, we discover that the Brave 6808 process is the only process with a base address at 15335424 instead of 140695088398336 for all other processes.

We will use strings to see if we can get more information.

1
2
3
4
5
6
$ strings fcsc.dmp | grep "192.168.1.106" -C 2
build   -ldflags="-s -w -X \"main.build=4d0e944d6b52f2715a2d75e5373a60f045921488\" -X
-X \"main.protocol=https\" -X
\"main.url=https://192.168.1.106:443/\"
-X \"main.host=mal.server.notlocal\" -X \"main.psk=WyGRb98LKLQfZiO32\" -X \"main.sleep=30s\" -X \"main.proxy=\" -X \"main.useragent=Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.85 Safari/537.36\" -X \"main.headers=\" -X \"main.skew=3000\" -X \"main.padding=4096\" -X \"main.killdate=0\" -X \"main.maxretry=7\" -X \"main.parrot=\" -H=windowsgui -buildid="
build   CGO_ENABLED=0

These parameters look like a C2 configuration. Searching for main.psk in grep.app, we find that it is the agent for the C2 Merlin.

/Ransomemoire/766fe062765dc305fb0c912d871b28d8.png

Flag

FCSC{6808:192.168.1.106:443}