Find My Pass
The Challenge
I managed to forget my password for my KeePass Database but luckily I had it still open and managed to get a dump of the system’s memory. Can you please help me recover my password?
https://ctfx.hacktm.ro/
I should mention that the actual task was to find password protected files, and not to find the actual password.
Challenge Overview
We receive a zipped HackTM.vmem file. A vmem file, is created by VMWare during a snapshot, and has a complete image of the machines memory. This format can be parsed using Volatility
Solution Walkthrough
When receiving any memory image, the first step should always be to run it through the volatilty imageinfo plugin:
$ python vol.py -f HackTM.vmem imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO : volatility.debug : Determining profile based on KDBG search...
Suggested Profile(s) : Win7SP1x86_23418, Win7SP0x86, Win7SP1x86_24000, Win7SP1x86 (Instantiated with Win7SP1x86)
AS Layer1 : IA32PagedMemoryPae (Kernel AS)
AS Layer2 : FileAddressSpace (/Users/ilyam/Desktop/HackTM/findmypass/HackTM.vmem)
PAE type : PAE
DTB : 0x185000L
KDBG : 0x82b7cb78L
Number of Processors : 2
Image Type (Service Pack) : 1
KPCR for CPU 0 : 0x80b96000L
KPCR for CPU 1 : 0x807ca000L
KUSER_SHARED_DATA : 0xffdf0000L
Image date and time : 2019-11-11 20:50:09 UTC+0000
Image local date and time : 2019-11-11 12:50:09 -0800
For this CTF all we actually need is the profile
Win7SP1x86
According to the challenge we should be looking for information about KeePass, and how it saves files. First things first, lets see what is running in memory:
$ python vol.py --profile=Win7SP1x86 -f HackTM.vmem pslist
Volatility Foundation Volatility Framework 2.6.1
Offset(V) Name PID PPID Thds Hnds Sess Wow64 Start Exit
---------- -------------------- ------ ------ ------ -------- ------ ------ ------------------------------ ------------------------------
0x84a41800 System 4 0 97 410 ------ 0 2019-11-11 20:49:19 UTC+0000
0x8625aa30 smss.exe 280 4 5 30 ------ 0 2019-11-11 20:49:19 UTC+0000
0x863c5d20 csrss.exe 380 360 9 632 0 0 2019-11-11 20:49:22 UTC+0000
[snip]
0x86dccc08 WmiPrvSE.exe 3228 664 14 330 0 0 2019-11-11 20:49:34 UTC+0000
0x86e1b810 KeePass.exe 3620 1988 10 251 1 0 2019-11-11 20:49:46 UTC+0000
0x86e844f0 WmiApSrv.exe 3716 484 7 122 0 0 2019-11-11 20:49:47 UTC+0000
0x85861678 mobsync.exe 2260 664 8 163 1 0 2019-11-11 20:49:55 UTC+0000
0x86a8f030 cmd.exe 3372 1676 0 -------- 0 0 2019-11-11 20:50:09 UTC+0000 2019-11-11 20:50:09 UTC+0000
0x86ec7588 conhost.exe 2520 380 0 30 0 0 2019-11-11 20:50:09 UTC+0000 2019-11-11 20:50:09 UTC+0000
0x86611870 ipconfig.exe 3472 3372 0 -------- 0 0 2019-11-11 20:50:09 UTC+0000 2019-11-11 20:50:09 UTC+0000
As we can see, KeePass is using PID 3620, lets open it using volshell, and traverse the process memory (case sensitive):
$ python vol.py --profile=Win7SP1x86 -f /Users/ilyam/Desktop/HackTM/findmypass/HackTM.vmem -p 3620 volshell
Volatility Foundation Volatility Framework 2.6.1
>>> print '\n'.join([str(obj.Object("String", offset=hit, vm=proc().get_process_address_space(), encoding='utf8', length=7)) for hit in proc().search_process_memory(["keepass"])])
keepass
keepass
keepass
keepass
keepass
keepass
keepass
Alternatively, we can dump the process memory and reverse it using grep:
$ python vol.py --profile=Win7SP1x86 -f HackTM.vmem -p 3620 memdump --dump-dir ./findmypassctf
$ strings ./findmypassctf/3620.dmp | grep -i "keepass"
KeePass
"C:\Program Files\KeePass Password Safe 2\KeePass.exe" "C:\Users\HackTM\Desktop\Database.kdbx"
C:\Program Files\KeePass Password Safe 2\KeePass.exe
C:\Program Files\KeePass Password Safe 2\KeePass.exe
KeePass.exe
keepass.exe
<assemblyIdentity name="KeePass"
KeePass.XmlSerializers.dll
keepass.xmlserializers.dll
[snip]
C:\Program Files\KeePass Password Safe 2\KeePass.exe
C:\Users\HackTM\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\KeePass 2.lnk
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\KeePass 2.lnk
KeePass.exe
KeePass.exe
KeePass.exe
KeePass.exe
KeePass.exe
KeePassPasswordSafe2_is1
KeePass 2 PreLoadz
C:/Program Files/KeePass Password Safe 2/KeePass.exeS
You could also use cat, with the -a flag on grep.
Digging through the process memory dump we stumble upon a familiar format:
$ strings ./findmypassctf/3620.dmp | grep -ia -C 5 "<KeePassFile>"
mUDQ
aB0t
(txYMc
.r+;
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<KeePassFile>
<Meta>
<Generator>KeePass</Generator>
<HeaderHash>jtMppK6LKKkQnA9qVS7rmOgz+OCXof3RS5m9vncRyWs=</HeaderHash>
<DatabaseName>Database</DatabaseName>
<DatabaseNameChanged>2019-10-28T10:27:15Z</DatabaseNameChanged>
So we expand the view, to see the whole structure, and under the
>>> print '\n'.join([str(obj.Object("String", offset=hit, vm=proc().get_process_address_space(), encoding='utf8', length=50000)) for hit in proc().search_process_memory(["<Kee"])])
<KeePassFile>
[snip]
<Binaries>
<Binary ID="0" Compressed="True">H4sIAAAAAAAEADOv2rNeXYaBJVjO5kkAAwRUQelFJyPiO896PZrd7K4j+kfLkvmKmGiMdKpGzb0dU8/Gxd8TEn2udD81bH1VA2emxt0sxy+7KyVrf0d2dp/66vX0TJtxqJtyHNOuG48dP+iJ8QaJrtz38MA/RhY2BkbOAAZ2bkYGJhW2j+yMXMHsPY6Bi3b84C1SVGRkYGTg8fFg4OBi/Gj6uYSBgZVRkpMBBgQVGfIY8hlKGDIYMoGsdCCdylAExHpAsQogZmCQZGJgEOFiZJgb4veqovcqoygbI4MCWDMAJqpejOoAAAA=</Binary>
<Binary ID="1" Compressed="True">H4sIAAAAAAAEADOv2rNeXYaB5WrEgbAABgiogtJBxj41dbf4r309apB3Vdd/3tyLXBXtMw7rTqrUuTZ1q+iZtqKjnyU0vsVrPFnuMe+Ckdr59NkreM5ELHzbm9L8zd/h6tu9fv5NR0ImFHv3vPtScP6Gi93OvYwsbAyMnAEM7NyMDEwqbB/ZGbmC2XMFM+7Pkay7rqjIyMDIwOPjwcDBxfjR9HMJAwMroyQnAwwIKjLkMeQzlDBkMGQCWelAOpWhCIj1gGIVQMzAIMnEwCDCxcgwN8TvVUXvVUZRNkYGBbBmADqAaWnqAAAA</Binary>
</Binaries>
<CustomData />
</Meta>
[snip]
Copying the first string, we decode it:
$ echo "H4sIAAAAAAAEADOv2rNeXYaBJVjO5kkAAwRUQelFJyPiO896PZrd7K4j+kfLkvmKmGiMdKpGzb0dU8/Gxd8TEn2udD81bH1VA2emxt0sxy+7KyVrf0d2dp/66vX0TJtxqJtyHNOuG48dP+iJ8QaJrtz38MA/RhY2BkbOAAZ2b4C1SVGRkYGTg8fFg4OBi/Gj6uYSBgZVRkpMBBgQVGfIY8hlKGDIYMoGsdCCdylAExHpAsQogZmCQZGJgEOFiZJgb4veqovcqoygbI4MCWDMAJqpejOoAAAA=" | base64 -d > flag
$ file flag
flag.gz: gzip compressed data, max speed, from FAT filesystem (MS-DOS, OS/2, NT), original size modulo 2^32 234
$ mv flag flag.gz
Opening it the flag.gz archive, generates another file – “flag”, which we read using a text editor:
$ file flag
flag.7z: 7-zip archive data, version 0.4
$ mv flag flag.7z
opening this file pops a password prompt:
digging around the memory dump for the password proved fruitless, so we started to go through other artifacts in memory. Coming across the clipboard artifact, we found a strange string:
$ python vol.py --profile=Win7SP1x86 -f /Users/ilyam/Desktop/HackTM/findmypass/HackTM.vmem clipboard -v
Volatility Foundation Volatility Framework 2.6.1
Session WindowStation Format Handle Object Data
---------- ------------- ------------------ ---------- ---------- --------------------------------------------------
[snip]
0xffbb46bc 64 00 6d 00 56 00 5a 00 51 00 6d 00 64 00 7a 00 d.m.V.Z.Q.m.d.z.
0xffbb46cc 4f 00 6c 00 55 00 72 00 63 00 45 00 42 00 6c 00 O.l.U.r.c.E.B.l.
0xffbb46dc 52 00 6a 00 38 00 37 00 64 00 48 00 51 00 33 00 R.j.8.7.d.H.Q.3.
0xffbb46ec 55 00 53 00 56 00 42 00 49 00 6e 00 00 00 U.S.V.B.I.n...
[snip]
extracting “dmVZQmdzOlUrcEBlRj87dHQ3USVBIn” and trying it in the password prompt, a file name “nothinghere.txt” containing the flag is extracted:
HackTM{d14c02244b17f4f9dfc0f71ce7ab10e276a5880a05fca64d39a716bab92cda90}
Success!