DFIRLABS: Gotham Hustle
by Benshkies
(Image generated by ChatGPT)
The Beginning to Suffering
Volatility has always been one of those tools that was, like, cool, but I never saw true utility out of it other than running basic modules and having the output for the flag given to me. This challenge is definitely not that. It makes you sweat and bleed for the flags. So in the spirit of that, I will give you a rundown of my hardships while learning the ins and outs of basic Volatility.
The Suffering
First things first, let’s get the basic image information so we know what we are dealing with:
python3 vol.py -f "C:\Users\benshkies\Desktop\Cases\gotham\gotham.raw" windows.info.Info | ForEach-Object { $_.Trim() } | Set-Content "$output_dir\mem_info.txt"
By default, Volatility’s output is kind of wack, so I used some PowerShell to trim up the white space. For the rest of the plugins, I’ll use this line and then just set the plugin before I run it. That way, output is consistent:
# set $plugin = "<plugin name>"
python3 vol.py -f "C:\Users\benshkies\Desktop\Cases\gotham\gotham.raw" $plugin | ForEach-Object { $_.Trim() } | Set-Content "$output_dir\$plugin.txt"
Nothing catches my eye with the output of pslist
.
Moving on to the Envars (plugin: windows.envars.Envars
):
- Computername: Bruce-PC
- USERNAME bruce
- USERPROFILE C:\Users\bruce
Not seeing anything else here. Lots of repeating data about a
csilogfile.log
, but don’t think that’s anything.
Not shown here is me trying 13 other modules and finding zilch, nada, zero on anything at all. Then a well-placed question to the DFIRLABS Discord nets me: “$I$ would suggest you to try Volatility 2 for this lab as it’s an older version of Windows and it’s only the challenge to give you experience on using Volatility.”
The Suffering but with Vol2
Volatility2 can be downloaded, but after spending an hour trying to get Python2 installed on my Win11 VM and it failing to read my env variables and install Python2 correctly, I downloaded the SANS SIFT workstation image and did that instead because it has Vol2 included along with all the community modules. SCORE!
So a quick boot of that VM and we are off with Vol2.
Volatility2 is specific in that it needs a specific profile to run the modules on. To do that, we use the imageinfo
module:
vol.py -f gotham.raw imageinfo
Then we get output somewhat like:
Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_24000, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_24000, Win7SP1x64_23418
Since Win7SP1x64_23418
is the latest version, I’ll just stick with that.
Now let’s try some basic commands:
vol.py -f gotham.raw --profile Win7SP1x64_23418 psscan
— Yields… nothing… great.
When in doubt, run strings. Let’s get a string dump of the image and see if we can get some easy wins:
strings gotham.raw >> strings.txt
Now we’ll use the strings command for some analysis with grep
. Is this necessary? Idk, but I did it.
vol.py -f gotham.raw --profile Win7SP1x64_23418 strings -s strings.txt | grep gotham
This outputs a peculiar set of strings
Volatility Foundation Volatility Framework 2.6.1
744406256 [FREE MEMORY:-1] <h2 id="Challenge-Description"><a href="#Challenge-Description" class="headerlink" title="Challenge Description:"></a>Challenge Description:</h2><p>Bruce Wayne was alerted that Joker have escaped from Arkham Asylum, Joker with all the Gotham outlaws crafts a letter for Bruce, He wants to make it go all crazy x_0!,and now Batman gets a message sent to Him with a letter, but apparently as Damain was in the Desktop, he opens it and everything goes crazy, the letter is now distributed to everyone in gotham, if Batman doesn
1085961673 [FREE MEMORY:-1] Jgotham
1098571519 [FREE MEMORY:-1] gotham-chess.com/
BUT the above is actually a clue to Batman 4, so not very helpful.
BUT below, using another basic command, cmdscan
, we can see a command history of our boi Brucey Wayne:
$ vol.py -f gotham.raw --profile Win7SP1x64_23418 cmdscan
...
Cmd #4 @ 0x12d690: Ymkwc2N0Znt3M2xjMG0zXw==
Cmd #5 @ 0x12d6d0: azr43ln1ght.github.io
...
Is that a flag I see? Yes! Is that also Azr43lKn1ght doing some self-promotion in a challenge? Up for debate. Nonetheless, decoding the base64 string gives us:
$ echo "Ymkwc2N0Znt3M2xjMG0zXw==" | base64 -d
bi0sctf{w3lc0m3_
So the flag is in parts, so we are in for a ride with this challenge.
I saw some activity on Bruce’s desktop, so I did the filescan
command with a grep
pipe to look for files specifically in that directory because filescan
is a beast to parse through without any grep.
The -F
means to take the string as a string and not a regular expression.
vol.py -f gotham.raw --profile=Win7SP1x64_23418 filescan | grep -F "bruce\Desktop"
Flag5.rar seems promising. Let’s see if we can extract it:
vol.py -f gotham.raw --profile=Win7SP1x64_23418 dumpfiles --dump-dir=output/ -Q 0x000000011fdaff20
Getting that downloaded and running strings
outputs:
...
The password for the zip file is the computer's password...
Just to see real quick if we could get Bruce’s password, I used the hashdump
module to dump the NTLM hashes.
Bruce’s password gets cracked into batman
using crackstation.net.
Using that password on the zip file yields part 5 of the flag: m0r3_13337431}
So we got the first and last flags first… guess that means we are pretty elite… or that we are really bad at finding basic things.
On another note, I see a lot of Chrome processes and activity in the process list, but when I run the chromehistory
plugin, there are no results.
It looks to be broken. (Did I know that it was broken for the 2 hours I spent trying to find artifacts from Chrome? I certainly did not!)
So after a gracious DFIRLABS admin clued me in that it should return stuff, I copied the chromehistory.py
file here and pasted it over the code in the plugins/community directory and now it works and shows me the Chrome history.
First line shows this:
flag3 = aDBwM190aDE1Xw==
Another flag I see. Base64 decode it and it shall be: h0p3_th15_
Ok, so now we got 1, 3, 5. Only 2 to go. The whole flag so far is:
bi0sctf{w3lc0m3_{FLAG2}h0p3_th15_{FLAG4}m0r3_13337431}
Let’s try seeing what the Paint and Notepad processes were up to.
From pslist
, I got the following:
notepad.exe 2592
mspaint.exe 2516
Let’s try dumping those processes:
volatility -f test.raw --profile=Win7SP1x86_23418 memdump --dump-dir=./ -p 2592
Running strings
on the Notepad data, I was able to find flag 4.
LOL is that flag 3? So if I was smart, I could have found both… great…
flag4 = YjNuM2YxNzVfeTB1Xw==
Is it cheeky to grep for flag? Maybe… but you get desperate when you’ve spent the last 2 hours searching the interwebs on how to parse a Notepad file with Volatility only to find out that you forgot the already quoted quote: “When in doubt, run strings” and could have found it much much earlier.
Flag4 decodes to: b3n3f175_y0u_
Doing the same for MSPaint doesn’t yield any results for flag two. OR does it? Turns out you gotta be simp and use GIMP to have any success here.
This involved a lot of fiddling—oh, did I mention that scrolling to the bottom of the image when changing the options helps a bunch?
I had to do a lot of fiddling with this to find the correct layout.
Micro adjustments will make your life a lot easier as you transform the image. In the end, I used RGB 16-bit and tried a bunch of offsets and finally found some text at the bottom.
Once you have the image set in place, you can flip it 180 and horizontal to reveal an image of a base64-encoded value:
dDBfZGYxcl9sNGl1Xw==
Can you tell what is a capital “I” and what is an “l”? Well, you better start guessing and mixing and matching to find out! Ah, I just love ambiguous fonts.
Finally, decoding this last value and putting it in its place yields:
bi0sctf{w3lc0m3_t0_df1r_l4b5_h0p3_th15_b3n3f175_y0u_m0r3_13337431}
Reflections on Suffering
This challenge was very well written. It gives a broad introduction into Volatility and presents you with unique situations that require some Volatility documentation digging to get the flags. When the challenge says “Easy,” it does not mean easy for anyone. It means easy for those already acquainted with Volatility and memory forensics. This gave me a new appreciation for the tool and showed me just how much I had been missing. There is still so much that I don’t know, but I hope to learn more about the tool as I continue learning in DFIR. Thanks to DFIRLABS for putting this challenge together! Next up is Trinity of Secrets.
tags: dfir - ctf-dfirlabs