Memlabs Memory Forensics Challenges – Lab 6 Write-up

Memlabs is a set of six CTF-style memory forensics challenges released in January 2020 by @_abhiramkumar and Team bi0s. I have been working on the Magnet Weekly CTF recently so the other write-ups I had in progress have been sitting partially finished for a while now. This write-up covers the final challenge – Lab 6 – The Reckoning. You can find the rest of my Memlabs write-ups here.

MD5: 405985dc8ab7651c65cdbc04cb22961c
SHA1: 344ed78742197c70070e5bdcfeeabf29c0785298

Lab 6. The final challenge in the Memlabs series. This one moves a little bit outside of memory analysis and was a lot of fun. Let’s go!

As usual, the first thing we do is determine which profile Volatility should use for the rest of the analysis.

vol.py -f MemoryDump_Lab6.raw imageinfo

Again, as usual, imageinfo suggests a few suitable profiles; we will use Win7SP1x64 for the rest of the challenge. Checking the running processes with pstree shows that there was quite a lot going on when the memory dump was captured.

vol.py -f MemoryDump_Lab6.raw --profile=Win7SP1x64 pstree

There’s a lot going here. The Chrome and Firefox processes seem like a pretty good starting point, but after picking up a trick in Lab 5, I decided to run the screenshot plugin to get an idea of what was displayed on screen before digging deeper.

vol.py -f MemoryDump_Lab6.raw --profile=Win7SP1x64 screenshot -D screenshot-output/

Examining the output we find one screenshot (session_1.WinSta0.Default.png) showing a Firefox window titled:

Mega Drive Key - davidbenjamin939@gmail.com - Gmail - Mozilla Firefox

That’s interesting, but not immediately helpful. I used the filescan and dumpfiles plugins to extract the Firefox browser history, but found nothing interesting so repeated the process to extract the Chrome history.

vol.py -f MemoryDump_Lab6.raw --profile=Win7SP1x64 filescan > filescan.txt
grep 'Google\\Chrome\\User Data\\Default\\History' filescan.txt
vol.py -f MemoryDump_Lab6.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000005da5a610 -D . -n

Chrome stores its browsing history as a SQLite database. Loading the extracted file into a GUI SQLite viewer, we find the following Pastebin link in the urls table:

https://pastebin.com/RSGSi1hk

The Pastebin post contains a Google Documents link and a reference to a key. Maybe the same key we saw referenced in the screenshots output earlier?

https://www.google.com/url?q=https://docs.google.com/document/d/1lptcksPt1l_w7Y29V4o6vkEnHToAPqiCkgNNZfS9rCk/edit?usp%3Dsharing&sa=D&source=hangouts&ust=1566208765722000&usg=AFQjCNHXd6Ck6F22MNQEsxdZo21JayPKug

Follow the Google Documents link and we find some pages of stock text, but look a little closer and there is a link to the MEGA file sharing service…

https://mega.nz/#!SrxQxYTQ

As expected, we need a key to access the MEGA drive:

We can make an educated guess that the key will be in the memory assigned to one of the Firefox processes, but rather than dumping each process individually, I simply grepped the whole memory image for the “Mega Drive Key” string in the Firefox window title. My strings command below uses the -n flag to limit the output to strings of 300 characters or longer; this is simply to make the resulting screenshot look a bit clearer!

strings -n 300 MemoryDump_Lab6.raw | grep 'Mega Drive Key'

Our grep search returns a line that looks somewhat like the source code of a web page, and includes the text we are looking for:

THE KEY IS zyWxCjCYYSEMA-hZe552qWVXiPwa5TecODbjnsscMIU

Now we can access the MEGA drive:

The filename flag_.png is promising but it seems that the file is somehow corrupted:

The viewer provides a hint that the IHDR chunk is missing. Let’s open it up in a hex editor and take a closer look. After checking the PNG specification (the PNG Wikipedia article has a nice illustration of how the header should look) I spotted the problem:

Changing the lower-case i (0x69) to an upper-case I (0x49)…

…was all that was needed to open the PNG file correctly and give us the first part of the flag.

inctf{thi5_cH4LL3Ng3_!s_g0nn4_b3_?_

Now to find the second part of the flag. As well as the Firefox and Chrome browser processes, pstree showed us a WinRAR process (PID: 3716). The cmdline plugin can help identify the file that WinRAR was using, then we grep our saved filescan output to find the offset, before finally extracting the archive – flag.rar – using the dumpfiles plugin:

vol.py -f MemoryDump_Lab6.raw --profile=Win7SP1x64 cmdline -p 3716
grep 'Users\\Jaffa\\Desktop\\pr0t3ct3d\\flag.rar' filescan.txt
vol.py -f MemoryDump_Lab6.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000005fcfc4b0 -D . -n

We’re not done yet though! We still need to find another password to open the RAR archive.

Thinking back to Lab 2 I used the envars plugin to list all of the environment variables in use, and one immediately stood out. Using grep for highlighting, we can see that it was not so subtly hidden!

vol.py -f MemoryDump_Lab6.raw --profile=Win7SP1x64 envars | grep 'RAR password'

There we go. An environment variable named “RAR password” with a value “easypeasyvirus“. Now we can open the archive…

And read the second part of our flag:

aN_Am4zINg_!_i_gU3Ss???}

Put the two parts together and we have completed the final Memlabs challenge!

inctf{thi5_cH4LL3Ng3_!s_g0nn4_b3_?_aN_Am4zINg_!_i_gU3Ss???}

Memlabs Memory Forensics Challenges – Lab 5 Write-up

Memlabs is a set of six CTF-style memory forensics challenges released in January 2020 by @_abhiramkumar and Team bi0s. I have been working on the Magnet Weekly CTF recently so the other write-ups I had in progress have been sitting partially finished for a while now. This write-up covers Lab 5 – Black Tuesday, which I worked on back in July! You can find the rest of my Memlabs write-up here.

MD5: 9dd6cb1134c9b018020bad44f27394db
SHA1: 289ec571ca6000b6234dee20c28d4cdba13e4ab7

After downloading the memory image and calculating the hashes, the first thing to do is determine which profile Volatility should use for the rest of the analysis.

vol.py -f MemoryDump_Lab5.raw imageinfo

The imageinfo plugin suggests a few profiles we can use; let’s go with Win7SP1x64 for now, and check the running processes with pstree.

vol.py -f MemoryDump_Lab5.raw --profile=Win7SP1x64 pstree

There are a few user processes that warrant investigation but no immediately obvious starting point. The cmdline plugin will display any command-line arguments that were passed when the process was started. Initially I ran the cmdline plugin with no additional arguments, but I have truncated the output to focus on two of the more interesting processes – WinRAR.exe and NOTEPAD.EXE.

vol.py -f MemoryDump_Lab5.raw --profile=Win7SP1x64 cmdline -p 2924,2724

We can see that the WinRAR process has a file associated with it; using the filescan and dumpfiles plugins we can extract this file from the memory image.

vol.py -f MemoryDump_Lab5.raw --profile=Win7SP1x64 filescan > filescan.txt
grep -E 'SW1wb3J0YW50.rar

Now we have the RAR file…

unrar e SW1wb3J0YW50.rar

…but we don’t have the password to open it. The RAR file contains Stage2.png, let’s go find the Stage 1 password.

After going down a few dead ends, I tried the screenshot plugin which, as the name suggests, allows us to see what was displayed on the desktop at the time the memory dump was taken. The screenshots are actually wire-frame drawings showing the positions and titles of the displayed windows. It won’t show us the full window content, but it is often enough to get an idea of what was displayed on the desktop.

vol.py -f MemoryDump_Lab5.raw --profile=Win7SP1x64 screenshot -D screenshot-output/

The screenshot plugin outputs a number of images; most are empty but one (session_1.WinSta0.Default.png) shows us that the Windows Photo Viewer was displaying a file with what looks to be a base64 filename:

ZmxhZ3shIV93M0xMX2QwbjNfU3Q0ZzMtMV8wZl9MNEJfM19EMG4zXyEhfQ

We can decode the base64 with CyberChef

…and there’s our Stage 1 flag:

flag{!!_w3LL_d0n3_St4g3-1_0f_L4B_5_D0n3_!!}

Now, we can go back to the RAR file and extract the Stage2.png:

Success!

flag{W1th_th1s_$taGe_2_1s_c0mPL3T3_!!}

Between “completing” this lab in the middle of July 2020 and finding time to write it up (in November!), the challenge description has been updated with the following note:

This challenge is composed of 3 flags. If you think 2nd flag is the end, it isn’t!! 😛

What?

This kind of thing was exactly what put me off the Memlabs challenges in the first place. Maybe the NOTEPAD.EXE process (PID: 2724) is worth examining, but I’m moving on.

Memlabs Memory Forensics Challenges – Lab 4 Write-up

Memlabs is a set of six CTF-style memory forensics challenges released in January 2020 by @_abhiramkumar and Team bi0s. This write-up covers Lab 4 – Obsession. You can find the rest of my Memlabs write-ups here.

As usual I started by calculating hashes for the image…

MD5: d2bc2f671bcc9281de5f73993de04df3
SHA1: bf96e3f55a9d645cb50a0ccf3eed6c02ed37c4df

…and running the Volatility imageinfo plugin to determine which profile to use for the rest of the analysis.

vol.py -f MemoryDump_Lab4.raw imageinfo

Having chosen Win7SP1x64 from the suggested profiles, I next checked the running processes with the pstree plugin.

vol.py -f MemoryDump_Lab4.raw --profile=Win7SP1x64 pstree

I briefly investigated the StikyNot.exe process but found nothing of interest. Let’s try the filescan plugin instead. I directed the output to a file, and used grep to filter the files in user profile directories, guessing that anything “very important” to the user would be stored there.

vol.py -f MemoryDump_Lab4.raw --profile=Win7SP1x64 filescan > filescan.txt
grep '\\Users\\' filescan.txt

Indeed, examining the filtered list we see a reference to Important.txt in a Desktop directory. My first approach was simply to run the dumpfiles plugin to recover the file from the memory image…

vol.py -f MemoryDump_Lab4.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000003fc398d0 -D . -n

… but in this case no output was created.

We can’t extract the file directly but there is another place the data might be stored. On an NTFS partition, small files (up to a few hundred bytes) may be stored as resident in the $DATA attribute in the Master File Table (MFT). We can use the mftparser plugin to, well, parse the MFT, and use grep again to filter the relevant entry. The -C 20 argument in my grep command instructs grep to return the 20 lines above and below the matching line.

Looking at the $DATA attribute, we can see something that looks like the flag but broken up with whitespace characters; with CyberChef we can easily convert the raw bytes to text then remove these…

… leaving us with our flag to complete the challenge.

inctf{1_is_n0t_EQu4l_7o_2_bUt_th1s_d0s3nt_m4ke_s3ns3}

Memlabs Memory Forensics Challenges – Lab 3 Write-up

Memlabs is a set of six CTF-style memory forensics challenges released in January 2020 by @_abhiramkumar and Team bi0s. This write-up covers Lab 3 – The Evil’s Den. You can find the rest of my Memlabs write-ups here.

Before starting with the analysis I calculated the MD5 and SHA1 hashes of the memory dump

MD5: ce4e7adc4efbf719888d2c87256d1da3
SHA1: b70966fa50a5c5a9dc00c26c33a9096aee20f624

And determined the correct profile for Volatility:

vol.py -f MemoryDump_Lab3.raw imageinfo

The imageinfo plugin suggests a few profiles; I used Win7SP1x86_23418 to complete the analysis. To begin with, let’s check the running processes with pstree:

vol.py -f MemoryDump_Lab3.raw --profile=Win7SP1x86_23418 pstree

There are two notepad.exe processes running (Pid: 3736 & 3432) but nothing else that immediately jumps out. Using the cmdlines plugin we may be able to see which files were opened.

vol.py -f MemoryDump_Lab3.raw --profile=Win7SP1x86_23418 cmdline -p 3736,3432

That’s a bit more interesting now! Notepad was used to open two files – evilscript.py and vip.txt – let’s try to extract them:

vol.py -f MemoryDump_Lab3.raw --profile=Win7SP1x86_23418 filescan > filescan.txt
grep -E '\\Desktop\\evilscript.py|\\Desktop\\vip.txt' filescan.txt
vol.py -f MemoryDump_Lab3.raw --profile=Win7SP1x86_23418 dumpfiles -Q 0x000000003de1b5f0 -D . -n
vol.py -f MemoryDump_Lab3.raw --profile=Win7SP1x86_23418 dumpfiles -Q 0x000000003e727e50 -D . -n

I used the filescan plugin to list all of the file objects (and their offsets) within the memory image, and redirected the output to a file. Using grep we get the offsets for the files (and also notice that evilscript.py is actually evilscript.py.py), then the dumpfiles plugin will extract the files to disk for analysis.

evilscript.py

import sys
import string

def xor(s):
  a = ''.join(chr(ord(i)^3) for i in s)
  return a

def encoder(x):
  return x.encode("base64")

if __name__ == "__main__":
  f = open("C:\\Users\\hello\\Desktop\\vip.txt", "w")
  arr = sys.argv[1]
  arr = encoder(xor(arr))
  f.write(arr)
  f.close()

vip.txt

am1gd2V4M20wXGs3b2U=

So, we have a Python script that works as follows:

  1. Take a string as a command-line argument
  2. Break that string down to its individual characters, and XOR each character with 3
  3. Encode the XOR’d string as Base64
  4. Write the Base64 encoded string to the file vip.txt

We could write another Python script to reverse these steps, but CyberChef is much easier!

Reversing the steps from evilscript.py, CyberChef spits out the first part of our flag:

inctf{0n3_h4lf

Now we have the first part of the flag, but we still need to find the second. None of the other running processes look particularly interesting, but the challenge description specifically mentions that steghide is required.

Steghide is a steganography program that is able to hide data in various kinds of image and audio files.

Using grep and my saved filescan output I filtered for common image file extensions, and spotted the following after searching for JPEG files:

grep -E '.jpg$|.jpeg

After extracting suspision1.jpeg:

We can feed it into steghide to check for any hidden data. Presumably the first part of the flag is the password…

steghide extract -sf suspision1.jpeg
cat secret\ text

And there we go, the second part of our flag.

_1s_n0t_3n0ugh}

Put them together, and we have completed the challenge!

inctf{0n3_h4lf_1s_n0t_3n0ugh}

Memlabs Memory Forensics Challenges – Lab 2 Write-up

Memlabs is a set of six CTF-style memory forensics challenges released in January 2020 by @_abhiramkumar and Team bi0s. I completed and published my write-up of Lab 1 in February 2020, but skipped the rest of the challenges due to the general wild-goose-chase approach of simply running Volatility plugins and searching the output for interesting strings.

That was until I saw Jessica Hyde mention the Memlabs challenges on Twitter during the SANS DFIR Summit, and noticed that they had been updated to include some context about why the analysis was needed. With my main complaint from Lab 1 taken care of I jumped back in, starting with Lab 2 – A New World.

As usual, I started by confirming the MD5 and SHA1 hashes of the memory image…

MD5: ddb337936a75153822baed718851716b
SHA1: 3ee71b2507e6b5b15bb2e5f97bf809ef7c85d810

And by determining the correct profile for Volatility using the imageinfo plugin:

vol.py -f MemoryDump_Lab2.raw imageinfo

The output gives us a number of suggestions; Win7SP1x64 will do for now.

The challenge contains three flags, but the order is not important. I am presenting this write-up in the order that I found the flags – Stage 3, Stage 2, then Stage 1.

Stage 3

The challenge description mentions that web browsers and password managers. Checking the running processes with the pstree plugin shows that Chrome and the KeePass password manager were running when the dump was made. Let’s start with Chrome.

vol.py -f MemoryDump_Lab2.raw --profile=Win7SP1x64 pstree

The filescan plugin will produce a list of all of the file objects within the memory dump; it can take some time to run so I redirected the output to a file to speed up grep searches later on.

vol.py -f MemoryDump_Lab2.raw --profile=Win7SP1x64 filescan > filescan.txt
head filescan.txt

Using grep to search for the location of the Chrome History file we can find and extract the database for analysis using the dumpfiles plugin.

grep '\\Chrome\\User Data\\Default\\History' filescan.txt
vol.py -f MemoryDump_Lab2.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000003fcfb1d0 -D .

The History file is a SQLite database which we can explore with the sqlite3 command-line tool, or with a GUI application such as DB Browser for SQLite.

Browsing the database we see that the MEGA file-sharing website was visited; let’s check that out.

The directory title – MemLab_Lab2_Stage3 – is promising but the ZIP file is password protected.

Fortunately we already know the flags from Lab 1, and CyberChef can easily calculate the SHA1 hash:

6045dd90029719a039fd2d2ebcca718439dd100a

The password is accepted and Important.png is extracted, giving us our first flag (actually for Stage 3, but nevermind).

flag{oK_So_Now_St4g3_3_is_DoNE!!}

Stage 2

We have investigated the browser history, now let’s take a look at KeePass. We know the KeePass Process ID (3008) from the pstree output earlier. By checking the command-line associated with the KeePass process using the cmdline plugin we can find the location of the KeePass database file, then extract it from the memory dump in the same way as the Chrome History file.

vol.py -f MemoryDump_Lab2.raw --profile=Win7SP1x64 cmdline -p 3008
grep '\\Users\\SmartNet\\Secrets\\Hidden.kdbx' filescan.txt
vol.py -f MemoryDump_Lab2.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000003fb112a0 -D .

After installing KeePassX on my SIFT VM, I can open the file but require a password before I can actually view any of the contents.

I got lucky with grep searches over the saved filescan output from earlier and was able to extract a file named Password.png

grep -i 'password' filescan.txt
vol.py -f MemoryDump_Lab2.raw --profile=Win7SP1x64 dumpfiles -Q 0x000000003fce1c70 -D .

Opening the extracted PNG file, we see the following:

The lower right-hand corner of the image contains the following text:

Psst!! password is P4SSw0rd_123

After entering the newly acquired password into KeePassX, we can browse the stored credentials and find the flag for Stage 2.

flag{w0w_th1s_1s_Th3_SeC0nD_ST4g3_!!}

Stage 1

While working on Stage 2 I ran the cmdscan plugin along with cmdline. The cmdscan plugin didn’t return anything related to KeePass, but it did show some unusual output from a cmd.exe shell.

vol.py -f MemoryDump_Lab2.raw --profile=Win7SP1x64 cmdscan

The challenge description emphasises that the owner of the system is an environmental activist; pulling out the environment variables for this process (2068) with the envvars plugin gives us the following:

vol.py -f MemoryDump_Lab2.raw --profile=Win7SP1x64 envars -p 2068

The environment variable NEW_TMP contains what appears to be a base64 string:

ZmxhZ3t3M2xjMG0zX1QwXyRUNGczXyFfT2ZfTDRCXzJ9

Going back to CyberChef, we can decode this with ease and return our final flag for Lab 2.

flag{w3lc0m3_T0_$T4g3_!_Of_L4B_2}

Memlabs Memory Forensics Challenges – Lab 1 Write-up

In an effort to improve my forensics skills I have been working through publicly available forensics CTFs when I have some free time.

Memlabs is a set of six CTF-style memory forensics challenges released in January 2020 by @_abhiramkumar and Team bi0s. This write-up covers the first memory image which has three flags to uncover.

Unlike most CTFs I have encountered, Memlabs does not actually ask any questions or give hints regarding the flags, only that the flags have the following format:

flag{stage1_is_n0w_d0n3}

No hashes were provided to check against but I calculated the following:

MD5: b9fec1a443907d870cb32b048bda9380
SHA1: 02a58ccf572e6b369934268842551722c4411a60

Let’s go!

Flag 1

First let’s determine what kind of memory image we are working with. As usual for memory forensics, I’m going to work with Volatility.

vol.py -f MemoryDump_Lab1.raw imageinfo

The first suggestion is Win7SP1x64; this seems like a sensible starting point.

We have no clues as to what we are supposed to be looking for. Let’s check the running processes using the pstree module and see if anything stands out.

vol.py -f MemoryDump_Lab1.raw --profile Win7SP1x64 pstree

The only processes that stand out are WinRAR.exe (PID: 1512), cmd.exe (PID: 1984), and mspaint.exe (PID: 2424). DumpIt.exe is likely the tool used to capture the memory dump so I am ignoring it for now. We can use the cmdline and consoles modules to show the command that launched these processes, and any console output associated with them.

vol.py -f MemoryDump_Lab1.raw --profile Win7SP1x64 cmdline -p 1512,1984,2424
vol.py -f MemoryDump_Lab1.raw --profile Win7SP1x64 consoles

The output from cmdline tells us that WinRAR.exe was launched with a file called Important.exe which seems, well, important but the consoles plugin shows a command St4Ge$1 being run and the following output:

ZmxhZ3t0aDFzXzFzX3RoM18xc3Rfc3Q0ZzMhIX0=

Decoding this from base64 gives us our first flag:

echo "ZmxhZ3t0aDFzXzFzX3RoM18xc3Rfc3Q0ZzMhIX0=" | base64 -d

flag{th1s_1s_th3_1st_st4g3!!}

Flag 2

I actually found Flag 3 before Flag 2 as I spotted the reference to Important.rar in the cmdline output, but for ease of reading I’ll keep this order. As I had examined the cmd.exe and WinRAR.exe processes already I guessed that Flag 2 was hidden in the mspaint.exe process, so began by dumping the process memory.

vol.py -f MemoryDump_Lab1.raw --profile Win7SP1x64 memdump -p 2424 -D .

After some Googling I found a blogpost detailing how to extract RAW images from memory dumps. I renamed the dump from 2424.dmp to 2424.data and opened it up with the GIMP image editing suite, setting the Image Type to RGB Alpha, and fiddling with the Offset, Width, and Height values through trial and error until I got something that looked intelligible.

That’s definitely text but not very easy to read. I’m better with Volatility than with GIMP so I took a screenshot of the image preview and flipped it vertically, revealing the flag.

flag{G00d_BoY_good_girL}

Flag 3

The output from the cmdline module showed that WinRAR.exe had been launched with a file called Important.rar. Lets extract that from the memory image and take a look.

vol.py -f MemoryDump_Lab1.raw --profile Win7SP1x64 filescan | grep -i "important.rar"
vol.py -f MemoryDump_Lab1.raw --profile Win7SP1x64 dumpfiles -Q 0x000000003fa3ebc0 -D .
file file.None.0xfffffa8001034450.dat

I renamed the file to Important.rar and tried extracting the contents.

unrar x Important.rar

Unfortunately we need a password. Fortunately the password hint tells us where to find it. We can use the hashdump module to dump the NTLM hashes.

vol.py -f MemoryDump_Lab1.raw --profile Win7SP1x64 hashdump

We only need the second part of the hash, but we do need to convert it to upper-case first. Rather than doing it manually I used CyberChef to do it for me.

Now we have the password we can extract the archive and view its contents – a PNG image containing our flag.

 

flag{w3ll_3rd_stage_was_easy}

Despite completing the first challenge I found the lack of direction or motivation incredibly frustrating. The whole point of forensic investigation is to follow a trail, building on what has been found already to come to a specified conclusion. Real investigations have a purpose. Why was this memory dump captured in the first place? Why are you asking me to take the time to do some analysis? I did learn a new technique in finding Flag 2, but for now I am skipping the rest of Memlabs to work on something more representative of real-world DFIR.