FCSC 2023 - Ransomémoire - Forensics

11 minute read

Here is the write-up of “Ransomémoire” series of forensic challenges of the FCSC 2023 which involves investigation of a Windows 10 memory dump. The series is divided in four parts.

Ransomémoire 0/4 - Pour commencer | Description

You prepare to analyze a memory capture and note some information about the machine before diving into the analysis:
    username,
    machine name,
    browser used.

The flag is in FCSC{<username>:<machine name>:<browser name>} format where:
    <username> is the name of the user using the machine,
    <machine name> is the name of the machine being analyzed, and
    <browser name> is the name of the running browser.

For example: FCSC{toto:Computer-of-jojo:Firefox}.

Author : haxom

This is the warm-up phase, we just need to use volatility with classic commands on the provided memory dump to extract the three information.

Note : I used volatility2 (vol.py) and 3(vol3.py) to resolve the challenge, the profile for volatility2 is Win10x64_19041, obtained with imageinfo plugin.

Username

Just a quick filescan and a grep to see the Users.

$ vol.py -f ./fcsc.dmp  --profile=Win10x64_19041 filescan > out/vol2/filescan.txt
$ cat out/vol2/filescan.txt| grep Desktop
0x0000818684ee8160     12      0 R--r-d \Device\HarddiskVolume2\Windows\System32\NPSMDesktopProvider.dll
0x0000818686c595a0      3      0 R--r-d \Device\HarddiskVolume2\Windows\System32\DispBroker.Desktop.dll
0x0000818687ecd680      9      0 R--r-d \Device\HarddiskVolume2\Windows\System32\DdcComImplementationsDesktop.dll
0x0000818687ed5ce0     14      0 R--r-d \Device\HarddiskVolume2\Windows\System32\SettingsEnvironment.Desktop.dll
0x0000818687ee9ec0     11      0 R--r-d \Device\HarddiskVolume2\Windows\System32\Windows.Cortana.Desktop.dll
0x0000818689b077d0     18      0 RW-rwd \Device\HarddiskVolume2\Users\Admin\Desktop\th (9).webp
0x0000818689b0d270     16      0 R--rwd \Device\HarddiskVolume2\Users\Public\Desktop\desktop.ini
0x0000818689b87700     16      0 R--rw- \Device\HarddiskVolume2\Users\Admin\Desktop\Microsoft Edge.lnk
0x0000818689b8b260     16      0 R--rwd \Device\HarddiskVolume2\Users\Admin\Desktop\desktop.ini
0x0000818689b8f590  32768      1 R--rwd \Device\HarddiskVolume2\Users\Admin\Desktop
0x0000818689b9cba0  32768      1 R--rwd \Device\HarddiskVolume2\Users\Public\Desktop
0x0000818689b9d1e0  32766      1 R--rwd \Device\HarddiskVolume2\Users\Admin\Desktop
0x0000818689b9e4a0  32768      1 R--rwd \Device\HarddiskVolume2\Users\Admin\Desktop
0x0000818689b9fda0  32768      1 R--rwd \Device\HarddiskVolume2\Users\Public\Desktop

So the username is Admin.

Computer name

With the printkey plugin, we can print the value of the registry key ComputerName.

$ vol3.py -f ./fcsc.dmp windows.registry.printkey.PrintKey --key "ControlSet001\Control\ComputerName\ComputerName"
Volatility 3 Framework 2.4.0
Progress:  100.00               PDB scanning finished
Last Write Time Hive Offset     Type    Key     Name    Data    Volatile

-       0xe306c7864000  Key     ?\ControlSet001\Control\ComputerName\ComputerName       -               -
2023-04-04 17:24:39.000000      0xe306c7889000  REG_SZ  \REGISTRY\MACHINE\SYSTEM\ControlSet001\Control\ComputerName\ComputerName        (Default)       "mnmsrvc"       False
2023-04-04 17:24:39.000000      0xe306c7889000  REG_SZ  \REGISTRY\MACHINE\SYSTEM\ControlSet001\Control\ComputerName\ComputerName        ComputerName    "DESKTOP-PI234GP"       False

The computer name is DESKTOP-PI234GP.

Browser

We list the processes and brave browser is running :

$ vol.py -f fcsc.dmp --profile=Win10x64_19041 pslist > out/vol2/pslist.txt
$ cat out/vol2/pslist.txt
➜  dump-analysis cat out/vol2/pslist.txt
         Name                    PID   PPID   Thds     Hnds   Sess  Wow64 Start                          Exit
-------------------- ------ ------ ------ -------- ------ ------ ------------------------------ ------------------------------
[...]
brave.exe              4072   3928     31        0      1      0 2023-04-17 17:21:31 UTC+0000
brave.exe              5064   4072      8        0      1      0 2023-04-17 17:21:39 UTC+0000
brave.exe              3952   4072     14        0      1      0 2023-04-17 17:21:44 UTC+0000
brave.exe              4060   4072     12        0      1      0 2023-04-17 17:21:44 UTC+0000
brave.exe              2844   4072      7        0      1      0 2023-04-17 17:21:44 UTC+0000
brave.exe              5500   4072     15        0      1      0 2023-04-17 17:21:46 UTC+0000
[...]

The browser is brave.

We have the flag for the part 0 : FCSC{Admin:DESKTOP-PI234GP:Brave}

Ransomémoire 3/3 - Doppelgänger | Description

You don't understand how the agent you found in Ransomemory 2/3 - Beginning of Investigation could be on the machine (Note: it is not necessary to have solved this challenge to solve Ransomemory 3/3 - Doppelgänger). You suspect the presence of a sleeping agent, which hides in memory...

The flag is in FCSC{<pid>:<ip>:<port>} format where:
    <pid> is the ID of the malicious process and
    <ip> and <port> are the parameters of the connection with the C2.

Author : haxom

I don’t write the 1/3 and 2/3 solutions now because they are more complex and during the competition I solved the 3/3 before the two remaining (1/3 and 2/3).

First, the title of the challenge : “Doppelgänger”, puts us on the track that we need to find a process which looks similar to another but which isn’t the same. If we link this information with the part 0/3, we could think about the browser, brave, which can be backdoored, but we are not sure.

I started to use the common volatility plugins related to processes and network, because we need to find an IP/port and a PID :

  • psscan
  • pstree
  • psxview
  • netscan
  • netstat

With the netstat plugin of vol3, I found this :

0x8186882a7a20  TCPv4   10.0.2.15       49836   192.168.1.106   443     CLOSE_WAIT      6808    brave.exe       2023-04-17 17:16:51.000000

A brave process communicates with an IP which seems to be related to a local network of the machine. (192.168.1.106 and port 443)

I also used a tool called bulkextractor on the memory dump to extract many information about it.

$ ./bulk_extractor ./fcsc.dmp -o out_bulk
$ ls out_bulk
aes_keys.txt              domain.txt                  ether.txt           httplogs.txt         ntfslogfile_carved.txt  rar.txt            tcp.txt                   url_microsoft-live.txt  windirs.txt       zip.txt
alerts.txt                elf.txt                     evtx_carved.txt     ip_histogram.txt     ntfsmft_carved.txt      report.xml         telephone_histogram.txt   url_searches.txt        winlnk.txt
ccn_histogram.txt         email_domain_histogram.txt  exif.txt            ip.txt               ntfsusn_carved          rfc822.txt         telephone.txt             url_services.txt        winpe_carved
ccn_track2_histogram.txt  email_histogram.txt         facebook.txt        jpeg_carved.txt      ntfsusn_carved.txt      sin.txt            unrar_carved.txt          url.txt                 winpe_carved.txt
ccn_track2.txt            email.txt                   find_histogram.txt  json.txt             packets.pcap            sqlite_carved      url_facebook-address.txt  utmp_carved             winpe.txt
ccn.txt                   ether_histogram_1.txt       find.txt            kml_carved.txt       pii_teamviewer.txt      sqlite_carved.txt  url_facebook-id.txt       utmp_carved.txt         winprefetch.txt
domain_histogram.txt      ether_histogram.txt         gps.txt             ntfsindx_carved.txt  pii.txt                 tcp_histogram.txt  url_histogram.txt         vcard.txt               zip

In the rfc822.txt file, I found this information:

So there are requests on the mal.server.notlocal domain, looks really suspicous.

Lets strings / strings -el the dump and grump for it.

strings -el is to extact UTF-16 strings

strings fcsc.dmp > strings.txt
strings -el fcsc.dmp > -el strings.txt

And grep it :

-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/5
37.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="

This line looks like a Golang compilation command and we find the previous IP that we found before : 192.168.1.106 in the main.url field. There is also a sleep field, that’s obviously a C2 beacon !

Let’s use procdump with the PID to dump the brave executable and analyze it.

$ vol.py -f fcsc.dmp --profile=Win10x64_19041 procdump --pid=6808 --dump-dir=./proc_dump_6808

Quick upload on virus total confirms it : https://www.virustotal.com/gui/file/9be810fedb8378987a9170ed8a261ef714120b4a3f50772d906d5928a715e9fc

That’s the malware which fake brave with his name.

Flag : FCSC{6808:192.168.1.106:443}

Ransomémoire 1/3 - Mon précieux | Description

You were looking at your beautiful cat pictures when, lo and behold, your super secret file on your desktop changes extension and becomes unreadable...

You do a memory capture to understand what happened, in order to recover this precious file.

Author : haxom

So now we need to recover an encrypted file which we don’t know the name, we only know that this file was on the user Desktop.

The filescan plugin didn’t find anything, so the file was removed. A quick grep on strings with Desktop keyword allows us to find the two files.

$ cat strings.txt | grep -i '\\Desktop'
[...]
C:\Users\Admin\Desktop\chats.odt
C:\Users\Admin\Desktop\flag.fcsc
[...]

The file which contains the cats pictures is chats.odt, and the file that we need to recover is flag.fcsc.

Right after, I used the mftparser plugin of volatility which dump the MFT to see if the flag.fcsc content was not there.

$ vol.py -f ./fcsc.dmp  --profile=Win10x64_19041 mftparser > out/vol2/mftparser
$  cat out/vol2/mftparser| grep -A 10 "flag.fcsc"
2023-04-17 17:23:45 UTC+0000 2023-04-17 17:23:50 UTC+0000   2023-04-17 17:23:50 UTC+0000   2023-04-17 17:23:50 UTC+0000   Users\Admin\Desktop\flag.fcsc.enc

$DATA
0000000000: 3b 65 17 19 64 03 71 9f dd 1a 30 ec 37 ba 83 c9   ;e..d.q...0.7...
0000000010: 1b b0 44 c9 8d 05 45 88 ff 41 40 d6 32 e5 61 09   ..D...E..A@.2.a.
0000000020: 5f f2 32 07 44 6a 8d 05 c7 fe 82 2f 22 76 9a 08   _.2.Dj...../"v..
0000000030: 32 28 7a ad ff 90 c8 4d 96 ca 99 54 1c 2c 58 f7   2(z....M...T.,X.
0000000040: 7a 8b e5 c5 5d 51 5a                              z...]QZ

***************************************************************************

Here it is, but it seems to be encrypted, now our goal is to find where it can come from.

The challenging step starts. My first thought when reading the challenge description was that the encryption of the flag.fcsc file was linked to the cats document. We found that this is an ODT file, so It’s possible that there is a malicious Macro into it which encrypted the flag.

I tried many things to dump the chats.odt content, binwalk, foremost, strings to retrieve the content. I even retrieved the text content with strings and grep :

Album photo de chats
(aucun flag ici, juste des photos de chats trop mignons)

So I moved away from this idea. I started to try to recover the file not encrypted directly.

I used the plugin memdump to dump the memory of specific processes. There were some interesting processes name like “Process Hacker” but gives nothing fascinating.

I made a timeline with this little trick which uses volatility and mactime:

$ vol.py -f fcsc.dmp --profile=Win10x64_19041 timeliner --output=body > time.txt
$ vol.py -f fcsc.dmp --profile=Win10x64_19041 shellbags --output=body >> time.txt
$ vol.py -f fcsc.dmp --profile=Win10x64_19041 mftparser --output=body >> time.txt
$ mactime -b time.txt -d > timeline.csv

Now we have a cool csv which made my libreoffice laggy x).

This was cool, but didn’t help me to find where the encryption come from.

My last try was to use a yara, I didn’t know that, but the power of yara with volatility is that the process PID where the found content is found is written.

So I make two rules, one in UTF-8 and one in UTF-16. The UTF-16 was the good one.

$ vol.py -f fcsc.dmp --profile=Win10x64_19041 yarascan --yara-rules="{66 00 6c 00 61 00 67 00 2e 00 66 00 63 00 73 00 63}"

The string was found on explorer.exe process, not important, but especially on a svchost process !

We could try to dump the process :

$ vol.py -f fcsc.dmp --profile=Win10x64_19041 procdump --pid=5540 --dump-dir=./procdump_5540

Open it on IDA aaaaand :

Bingo we found it :)

Note: With string and grep I had already found a suspicous PATH : C:\Windows\Temp\svchost.exe, it was the malicious svchost.

Here are the two other functions of the binary :

The first function write random data in a file C:\\Windows\\Temp\\MsCmdRun%d.log, %d is changing.

The second function is just xoring the content of all .fcsc files with the random data generated and an index which is the number of time passed in the loop. (There’s a sleep between each iteration).

Now our goal is to recover the good MsCmdRun file to xor it with our flag.fcsc.enc. For the index, we are going to brute force to gain time.

We retrieve the MsCmdRun files with mftparser, but there are many. We need to find the good one. (During the challenge I decided to dump all of them, but It was not a good option).

The timestamp was the way, the MsCmdRun14.log file was created just before the content was modified, as you can see in the screenshot of the csv timeline.

So It was obviously the good one.

We just need to brute force the index and it was 0xe.

Here is the script to decrypt flag.fcsc.enc :

encrypted = open('./flag.fcsc.enc','rb').read()
key = open('./logs_file/MsCmdRun14.log','rb').read()

res = b""
for i in range(len(encrypted)):
    res += chr(encrypted[i] ^ key[i] ^ 0xe).encode() 

print(res)
$ python3 decrypt.py
b'FCSC{776f25d811bf9ac262143d0f1fa97c382f7b5972121b37d0361c7d7ad1b27079}\n'

We got it, flag : FCSC{776f25d811bf9ac262143d0f1fa97c382f7b5972121b37d0361c7d7ad1b27079}

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

Phew, you were able to recover your precious file. Now you investigate the origin of this encryption.

The flag is in FCSC{<pid>:<protocol>:<port>} format where:
    <pid> is the ID of the process that dropped and executed the encryptor and
    <protocol> and <port> are the parameters of the connection with C2.
Author : haxom

Last part of the challenge, we need to find the process which executed the malicious svchost executable.

With the pstree plugin we can see this :

... 0xffff81868852e080:VBoxTray.exe                  6424   3928     13      0 2023-04-16 21:47:34 UTC+0000
.... 0xffff818687754080:svchost.exe                  5540   6424      1      0 2023-04-17 17:21:18 UTC+0000

The parent PID of svchost.exe is VBoxTray.exe. If we’re referring to his name, It’s a process link to VirtualBox Guest Additions. We could think that’s not what we search, but we’re going to check in case it’s a malicious process.

Let’s dump it.

$ vol.py -f fcsc.dmp --profile=Win10x64_19041 procdump --pid=6424 --dump-dir=./procdump_6424

Quick check on VT : https://www.virustotal.com/gui/file/58c73998bcd720a9694bb136f3c53fc9dcd1e4b653dcc796364a76b52f23de57

Seems to be legit, but the file has no signature. Let’s use IDA to reverse it quickly.

We can find many GetProcAddress call, really suspicious.

The TEB strcture is retrieved, a common move in malwares to bypass Antivirus and EDRs.

I tried to run it on my VM but It crashes, :/ I tried one or two Sandbox online but get nothing interesting except one or two signatures.

Note: It was a legit VBoxTray, but a shellcode was injected into his memory

So I came back to the memory dump and use the malfind plugin (I had already run it but a result in VBoxTray.exe made me go through other things)

$ cat out/vol2/malfind.txt
Process: VBoxTray.exe Pid: 6424 Address: 0x22d82840000
Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITE
Flags: PrivateMemory: 1, Protection: 6

0x0000022d82840000  fc 48 89 ce 48 81 ec 00 20 00 00 48 83 e4 f0 e8   .H..H......H....
0x0000022d82840010  cc 00 00 00 41 51 41 50 52 48 31 d2 51 56 65 48   ....AQAPRH1.QVeH
0x0000022d82840020  8b 52 60 48 8b 52 18 48 8b 52 20 48 0f b7 4a 4a   .R`H.R.H.R.H..JJ
0x0000022d82840030  48 8b 72 50 4d 31 c9 48 31 c0 ac 3c 61 7c 02 2c   H.rPM1.H1..<a|.,

0x0000000082840000 fc               CLD
0x0000000082840001 48               DEC EAX
0x0000000082840002 89ce             MOV ESI, ECX
0x0000000082840004 48               DEC EAX
0x0000000082840005 81ec00200000     SUB ESP, 0x2000
0x000000008284000b 48               DEC EAX
0x000000008284000c 83e4f0           AND ESP, -0x10
0x000000008284000f e8cc000000       CALL 0x828400e0
0x0000000082840014 41               INC ECX
0x0000000082840015 51               PUSH ECX
0x0000000082840016 41               INC ECX
0x0000000082840017 50               PUSH EAX
0x0000000082840018 52               PUSH EDX
0x0000000082840019 48               DEC EAX
0x000000008284001a 31d2             XOR EDX, EDX
0x000000008284001c 51               PUSH ECX
0x000000008284001d 56               PUSH ESI
0x000000008284001e 6548             DEC EAX
0x0000000082840020 8b5260           MOV EDX, [EDX+0x60]
0x0000000082840023 48               DEC EAX
0x0000000082840024 8b5218           MOV EDX, [EDX+0x18]
0x0000000082840027 48               DEC EAX
0x0000000082840028 8b5220           MOV EDX, [EDX+0x20]
0x000000008284002b 48               DEC EAX
0x000000008284002c 0fb74a4a         MOVZX ECX, WORD [EDX+0x4a]
0x0000000082840030 48               DEC EAX
0x0000000082840031 8b7250           MOV ESI, [EDX+0x50]
0x0000000082840034 4d               DEC EBP
0x0000000082840035 31c9             XOR ECX, ECX
0x0000000082840037 48               DEC EAX
0x0000000082840038 31c0             XOR EAX, EAX
0x000000008284003a ac               LODSB
0x000000008284003b 3c61             CMP AL, 0x61
0x000000008284003d 7c02             JL 0x82840041
0x000000008284003f 2c               DB 0x2c

There is an RWX section in the VBoxTray.exe process memory. It is probably a shellcode.

Let’s dump it with the plugin.

$ vol3.py -f ./fcsc.dmp windows.malfind.Malfind --pid 6424 --dump

The shellcode seems to be hard to reverse when seeing it in IDA. Let’s just use string / strings -el to find the port and the protocol.

$ strings -el pid.6424.vad.0x22d82840000-0x22d82871fff.dmp | tail
zh-chs
zh-cht
zh-cn
zh-hk
zh-mo
zh-sg
zh-tw
zu-za
CONOUT$
tcp://:8080

Here it is :) the protocol is tcp and port 8080 ! We have all the information to flag.

Flag : FCSC{6424:tcp:8080}

Conclusion

This challenge was really cool, It allows playing with many different volatility plugins to find what we need. The confusion in process names for brave / svchost and VBoxTray was interesting because it reminds us that even if a process name seems legit, it is not necessarily.