Identifying Memory Images

Identifying Memory Images

Have you ever been given a memory image to examine and not known what OS it was? Or maybe you were told it was X when it was really Y? Or perhaps you have a collection of images that may not be labeled correctly?

So how do you figure out the OS of an unknown Windows image?


You could use strings to look for clues of the OS type. For example looking for the version numbers [1]. You can often find this in close proximity to a DLL name. Two examples (XP and Windows 7) are below:

Windows XP: 5.1.2600

2546060:5.1.2600.0 (xpclient.010817-1148)2546134:InternalName2546160:HCAppRes.dll2546194:LegalCopyright2546226: Microsoft Corporation. All rights reserved.2546322:OriginalFilename2546356:HCAppRes.dll

Windows 7: 6.1.7600.16385 (win7_rtm.090713-1255)

1335896:6.1.7600.16385 (win7_rtm.090713-1255)1335978:InternalName1336004:BlbEvents.dll1336038:LegalCopyright1336070: Microsoft Corporation. All rights reserved.

How do you determine if the memory image is from a x86 or x64 machine? Well, here you can look for environmental variables like PROCESSOR_ARCHITECTURE and PROCESSOR_ARCHITEW6432 (used for WOW64) [2]. An example from x86 and x64 machines:

=x86PROCESSOR_IDENTIFIER=x86 Family 6 Model 37 Stepping 5, GenuineIntel



More details about these variables can be found here.

Still, this is more labor intensive than it need be.


Remembering a blogpost Moyix wrote about finding kernel global variables in Windows I figured each OS would have a different size after the OwnerTag defined in wdbgext.h:


Moyix gives us the pattern to search for regarding x86 OSes since the end of LIST_ENTRY64 will be 0 for x86 machines [3]:


First let's try to find the sizes for each OS:

$ xxd xpsp3x86.dd |less[skip]0000b70: 6780 0000 0000 0000 0000 4b44 4247 9002 g.........KDBG..[skip]
$ xxd win7x86.dd |less[skip]0000bf0: ffff ffec 6fbb 83ec 6fbb 8300 0000 0000 ....o...o.......0000c00: 0000 004b 4442 4740 0300 0000 8084 8300 ...KDBG@........[skip]

After examining XP, W2K3, Vista, W2K8 and Windows 7 machines (and different service packs), this is what we get (Windows 2000 value not done personally, but taken from Moyix's blog [3]):

OS Size
Windows 2000 \x08\x02 XP \x90\x02 W2K3 \x18\x03 Vista \x28\x03 W2K8 \x30\x03 Windows 7 \x40\x03

Now we need to find the pattern for x64 systems as well. We could do this with a hexdump of memory images to find the KDBG pattern:

$ xxd win7x64.dd |less[skip]0000080: f8ff ff10 44a1 0200 f8ff ff4b 4442 4740 ....D......KDBG@0000090: 0300 0000 f080 0200 f8ff ff60 8f87 0200 ...........`....[skip]
$ xxd w2k8x64.dd |less[skip]0000f10: f8ff ff40 f878 0100 f8ff ff4b 4442 4730 ...@.x.....KDBG00000f20: 0300 0000 c060 0100 f8ff ff60 b865 0100 .....`.....`.e..[skip]

After examining several x64 dumps, the pattern that seemed universal to them was:


The header sizes also appear to remain the same for x64 and x86 machines. So there it is. You can search for a unique pattern in the memory image in order to figure out what OS it is. Some examples:

Windows 7x86: '\x00\x00\x00\x00\x00\x00\x00\x00KDBG\x40\x03'
W2K3 x86: '\x00\x00\x00\x00\x00\x00\x00\x00KDBG\x18\x03'
W2K8 x64: '\x00\xf8\xff\xffKDBG\x30\x03'

You could very easily write a Python script to identify Windows memory images using this technique, but you don't have to: This has already been incorporated into the Volatility 1.4 framework in the plugin. Thanks to Mike Auty (ikelos) for doing the honors :-)


[1] List of Windows Versions

[2] HOWTO: Detect Process Bitness

[3] Finding Kernel Global Variables in Windows


0 意見: