Wednesday 14 December 2011

Using SIFT to Crack a Windows (XP) Password from a Memory Dump

Introduction:

Recently, I was thinking about writing a blog entry on Volatility but then found out that SketchyMoose has done an awesome job of covering it already (in a Windows environment). Thinking of my fellow SIFT-ians / SIFT-ers / SIFT-heads (what?!) - I figured I could still write an entry with a focus on using the SIFT VM to crack a Windows password *evil laugh*.
To give an example of a DFIR scenario, FTK Imager can be used to capture a live Windows memory image and then the SIFT VM can be used to determine the Windows password(s). Or the responder could always nicely ask the owner for the password ;)
For this scenario however, we will be using a Windows XP memory image supplied by NIST. It's not that I don't trust you all with the contents of my memory ... *sarcastic laugh*

Here are the resources I used:

- The SketchyMoose's Blog entry that inspired me (to copy it ;) :
http://sketchymoose.blogspot.com/2011/10/cracking-passwords-with-volatility-and.html
with some further demos:
http://sketchymoose.blogspot.com/2011/11/using-volatility-suspicious-process.html

- For the official Volatility Documentation (eg plugin usage with example outputs) see:
https://code.google.com/p/volatility/wiki/CommandReference
and for some brief notes about Volatility from the SANS Forensics 2009 - Memory Forensics and Registry Analysis Presentation by Brendan Dolan-Gavitt see:
http://www.slideshare.net/mooyix/sans-forensics-2009-memory-forensics-and-registry-analysis

- The official John The Ripper Documentation is available at:
http://www.openwall.com/john/doc/
with usage examples at:
http://www.openwall.com/john/doc/EXAMPLES.shtml

So what I'm now about to cover is specific to using Volatility (2.1a) and John The Ripper as provided on the SANS SIFT Virtual Machine V2.12.

Volatility can be used to analyse a variety of Windows memory images. The general usage syntax is:
vol.py plugin_name memory_image_name
where plugin_name can be things such as pslist (list of running processes), pstree (hierachical view of running processes), connections (live network connections), connscan (live and previous network connection artifacts), hivelist (Windows hive virtual addresses), hashdump (extracts hashes of domain credentials). For more plugins refer to the Volatility Documentation Wiki link mentioned previously.

Method:

Here are the steps I followed:

1. From the command prompt in the SIFT VM, type "sudo mkdir /cases/mem" to create a directory "/cases/mem"

2. Copy/Download "memory-images.rar" (~500 Mb) to "/cases/mem/" from NIST's CFReDS Project at http://www.cfreds.nist.gov/mem/Basic_Memory_Images.html

3. Type "sudo unrar e /cases/mem/memory-images.rar" to extract NIST images to "/cases/mem/"

4. Type "vol.py imageinfo -f /cases/mem/xp-laptop-2005-07-04-1430.img"
This should return an output something like:

Volatile Systems Volatility Framework 2.1_alpha
Determining profile based on KDBG search...

          Suggested Profile(s) : WinXPSP3x86, WinXPSP2x86 (Instantiated with WinXPSP2x86)
                     AS Layer1 : JKIA32PagedMemory (Kernel AS)
                     AS Layer2 : FileAddressSpace (/cases/mem/xp-laptop-2005-07-04-1430.img)
                      PAE type : No PAE
                           DTB : 0x39000
                          KDBG : 0x8054c060L
                          KPCR : 0xffdff000L
             KUSER_SHARED_DATA : 0xffdf0000L
           Image date and time : 2005-07-04 18:30:32
     Image local date and time : 2005-07-04 18:30:32
          Number of Processors : 1
                    Image Type : Service Pack 2

                   
5. We then use the "WINXPSP3x86" profile to search/parse thru the dump. Type "sudo vol.py --profile=WinXPSP3x86 hivelist -f /cases/mem/xp-laptop-2005-07-04-1430.img" so we can obtain the virtual addresses for the SAM and System hives. Note without the "sudo", I was getting some errors so I decided to play it safe. I also tried using it with "--profile=WinXPSP2x86" but got similar errors.
The resulting output will look something like:

Volatile Systems Volatility Framework 2.1_alpha
Virtual     Physical    Name
0xe2610b60  0x14a99b60  \Device\HarddiskVolume1\Documents and Settings\Sarah\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe25f0578  0x17141578  \Device\HarddiskVolume1\Documents and Settings\Sarah\NTUSER.DAT
0xe1d33008  0x0f12c008  \Device\HarddiskVolume1\Documents and Settings\LocalService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1c73888  0x0efc5888  \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT
0xe1c04688  0x0e88e688  \Device\HarddiskVolume1\Documents and Settings\NetworkService\Local Settings\Application Data\Microsoft\Windows\UsrClass.dat
0xe1b70b60  0x0dff5b60  \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT
0xe1658b60  0x0c748b60  \Device\HarddiskVolume1\WINDOWS\system32\config\software
0xe1a5a7e8  0x094bf7e8  \Device\HarddiskVolume1\WINDOWS\system32\config\default
0xe165cb60  0x0c6ecb60  \Device\HarddiskVolume1\WINDOWS\system32\config\SAM
0xe1a4f770  0x0948c770  \Device\HarddiskVolume1\WINDOWS\system32\config\SECURITY
0xe1559b38  0x02d64b38  [no name]
0xe1035b60  0x0283db60  \Device\HarddiskVolume1\WINDOWS\system32\config\system
0xe102e008  0x02837008  [no name]
0x8068d73c  0x0068d73c  [no name]


6. Now we can extract the hashed password list to a file (in the current directory) called "xp-passwd" by typing "vol.py --profile=WinXPSP3x86 hashdump -y 0xe1035b60 -s 0xe165cb60 -f /cases/mem/xp-laptop-2005-07-04-1430.img  > xp-passwd"

Note: 0xe1035b60 = system hive virtual address, 0xe165cb60 = SAM hive virtual address which we obtained previously in step 5.

7. (Optional) If you type "cat xp-passwd" you should get something like:

Administrator:500:08f3a52bdd35f179c81667e9d738c5d9:ed88cccbc08d1c18bcded317112555f4:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
HelpAssistant:1000:ddd4c9c883a8ecb2078f88d729ba2e67:e78d693bc40f92a534197dc1d3a6d34f:::
SUPPORT_388945a0:1002:aad3b435b51404eeaad3b435b51404ee:8bfd47482583168a0ae5ab020e1186a9:::
phoenix:1003:07b8418e83fad948aad3b435b51404ee:53905140b80b6d8cbe1ab5953f7c1c51:::
ASPNET:1004:2b5f618079400df84f9346ce3e830467:aef73a8bb65a0f01d9470fadc55a411c:::
Sarah:1006:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::


8. For clarity, I am assuming that you will be running these commands from "/home/sansforensics". I had some initial problems launching John The Ripper from there - it was complaining that it couldn't open "john.ini" which contains the configuration info/rules. Consequently, I copied/renamed the John configuration file into "/home/sansforensics" using the command "cp /etc/john/john.conf ~/john.ini". This ensures that John's rules will be initialised properly when we proceed with the next step.

9. Type "john xp-passwd" and depending on your CPU, wait a while ... you should get something like this:

Loaded 10 password hashes with no different salts (LM DES [128/128 BS SSE2])
                 (Sarah)
                 (SUPPORT_388945a0)
                 (Guest)
6                (Administrator:2)
NEON96           (phoenix)
guesses: 5  time: 0:00:01:27 (3)  c/s: 33842K  trying: FG#NNJG - FG#NNNI
guesses: 5  time: 0:00:01:32 (3)  c/s: 33771K  trying: SWY1-4C - SWYEGAD
guesses: 5  time: 0:00:01:38 (3)  c/s: 33981K  trying: 0INHM1 - 0INIEK
guesses: 5  time: 0:00:03:35 (3)  c/s: 35750K  trying: KM51319 - KM5135E
NEON199          (Administrator:1)
guesses: 6  time: 0:00:16:35 (3)  c/s: 30877K  trying: 3S35/5# - 3S35/EA
guesses: 6  time: 0:00:17:49 (3)  c/s: 30836K  trying: 06OZJYB - 06OZJ4U
guesses: 6  time: 0:00:20:14 (3)  c/s: 30332K  trying: GM5BOM! - GM5BILI
guesses: 6  time: 0:00:20:19 (3)  c/s: 30341K  trying: HMO-F37 - HMO-FM.
guesses: 6  time: 0:00:40:15 (3)  c/s: 30880K  trying: EYGOMOA - EYGOP5U
guesses: 6  time: 0:00:52:16 (3)  c/s: 30931K  trying: W8W24EI - W8W24N6
JVYMGP1          (HelpAssistant:2)
guesses: 7  time: 0:01:22:17 (3)  c/s: 28872K  trying: V4VBN69 - V4VBN8F
guesses: 7  time: 0:01:23:37 (3)  c/s: 28802K  trying: UCBKWW0 - UCBKWG6
guesses: 7  time: 0:01:28:01 (3)  c/s: 28419K  trying: SGVRGO6 - SGVRGUV
guesses: 7  time: 0:01:38:31 (3)  c/s: 28008K  trying: #04CR3 - #04CM!
guesses: 7  time: 0:01:47:08 (3)  c/s: 27758K  trying: UFE'ACB - UFE'ABN
guesses: 7  time: 0:01:49:04 (3)  c/s: 27620K  trying: FXRG7D  - FXRBOVW
guesses: 7  time: 0:02:02:48 (3)  c/s: 27110K  trying: DYCIAQD - DYCIIHK
guesses: 7  time: 0:06:31:50 (3)  c/s: 24555K  trying: )K6T-. - )K6T_F
guesses: 7  time: 0:06:32:15 (3)  c/s: 24557K  trying: )^Y3G_ - )^Y3TT
Session aborted


You can see where I ran out of patience with my single core Athlon64 CPU and aborted the session after approx 6.5 hours (by pressing CTRL-C).  Your mileage will vary methinks - so feel free to let it run to completion. Whilst John is running, whenever the operator presses a key, a timestamped statistics message is printed to screen.

So from the output above, we now know the "Administrator" password is "NEON1996". John displays passwords in groups of 7 letters so we append the results of Administrator:2 (ie "6") to Administrator:1 (ie "NEON199"). In contrast, "phoenix" has the password "NEON96" - there is no second half to append / there is no numbered index associated. Also, "Sarah" / "SUPPORT_388945a0" / "Guest" do not appear to have a password set.

Also from the output above, we can theorise that "HelpAssistant" and "ASPNET" have passwords greater than 7 characters long (ie they each use 2 password hashes). John reports 10 loaded password hashes = 1 hash each for "Sarah" / "SUPPORT_388945a0" / "Guest "/ "phoenix" + 2 hashes for "Administrator" which implies 4 password hashes left between "HelpAssistant" and "ASPNET".

10. If we type "john -show xp-passwd" we will get a summary of the findings so far:

Administrator:NEON1996:500:ed88cccbc08d1c18bcded317112555f4:::
Guest::501:31d6cfe0d16ae931b73c59d7e0c089c0:::
HelpAssistant:???????JVYMGP1:1000:e78d693bc40f92a534197dc1d3a6d34f:::
SUPPORT_388945a0::1002:8bfd47482583168a0ae5ab020e1186a9:::
phoenix:NEON96:1003:53905140b80b6d8cbe1ab5953f7c1c51:::
Sarah::1006:31d6cfe0d16ae931b73c59d7e0c089c0:::


7 password hashes cracked, 3 left

Note: The second field is the password field eg for "Administrator", the password is "NEON1996". There are no passwords set for "Guest", "SUPPORT_388945a0" and/or "Sarah". I stopped John before it could calculate the passwords for "HelpAssistant" and "ASPNET".

The John results are stored in a file called "john.pot" and events are logged to "john.log". Both of these files are located in the directory where "john" was launched from (eg "/home/sansforensics"). So if we want to restart a cracking attempt from scratch, you can use "rm -f john.pot" before re-launching "john". Should "john" crash/be CTRL-C'd, there will be a "john.rec" recovery file generated so "john" can restart from its last calculation point (as opposed to from the beginning).

So thats about all I have to show you for now ... if you decide to try it out, I'd be interested to hear you comment on how long your processing time took. Go bananas !