Symbolic Link Objects

The concept of symbolic links is widely implemented in file systems. But there is also a symbolic link object for kernel objects. Generally, a symbolic link will make an object accessible under a different and probably much shorter name. But symbolic link objects also provide some forensic value.

Again, WinObj by Mark Russinovich might be a good start to explore symbolic link objects. The following objects links the name "KnownDllPath" to "C:\WINDOWS\system32".


But there's more in the properties of a symbolic link object. As you can see from the following screen shot, Windows stores an object creation time stamp, for whatever reason.

There is a creation time stamp among the object's properties

From the _OBJECT_TYPE structure we learn about the pool tag "Symb" and that its memory gets allocated from the paged pool. Matching allocations are always 0x50 bytes in size (on Windows XP with ServicePack 2). Here is an example of how it looks like in a debugger or hex editor:

kd> db e1347358
e1347358  05 02 0a 0c 53 79 6d e2-88 47 00 e1 86 00 86 00  ....Sym..G......
e1347368  d8 84 39 e1 01 00 00 00-01 00 00 00 00 00 00 00  ..9.............
e1347378  a8 e0 2b 81 10 00 00 32-01 00 00 00 d7 73 00 e1  ..+....2.....s..
e1347388  22 84 97 cc 98 98 c7 01-20 00 22 00 00 d8 34 e1  "....... ."...4.
e1347398  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00  ................
e13473a8  0a 02 01 00 4b 65 79 a0-01 02 02 0c 4f 62 44 69  ....Key.....ObDi

In the first line you will spot the "Symb" pool tag. Note that the most significant bit is set to indicate a system object. In the last line there's already the next allocation (with a "Key" pool tag). The symbolic link object starts at 0xe1347388:

kd> !object e1347388
Object: e1347388  Type: (812be0a8) SymbolicLink
    ObjectHeader: e1347370 (old version)
    HandleCount: 0  PointerCount: 1
    Directory Object: e1004788  Name: ACPI#FixedButton#2&daba3ff&0#{4afa3d53-74a7-11d0-be5e-00a0c9062857}
    Target String is '\Device\00000035'

The object's payload starts with the creation time stamp. You'll have to copy the bytes by hand because the function doesn't take a pointer to the time stamp. The time stamp as usual is in 64bit Windows filetime format.

kd> !filetime 01c79898cc978422
 5/17/2007 16:34:03.828 (local time)

Yes, this is from an old memory image, the time stamp looks plausible. Next is an Unicode string:

kd> !ustr e1347390
String(32,34) at e1347390: \Device\00000035

We now know how to decode the symbolic link object's creation time stamp and target string. For the curious: the name string is stored in an "ObNm" (Object Name) allocation, while the target string is stored in an "Symt" (Symbol Target) allocation. Both are in the paged pool.

Now let's have a look at the _OBJECT_HEADER:

kd> dt _OBJECT_HEADER e1347370
   +0x000 PointerCount     : 1
   +0x004 HandleCount      : 0
   +0x004 NextToFree       : (null) 
   +0x008 Type             : 0x812be0a8 _OBJECT_TYPE
   +0x00c NameInfoOffset   : 0x10 
   +0x00d HandleInfoOffset : 0 ''
   +0x00e QuotaInfoOffset  : 0 ''
   +0x00f Flags            : 0x32 
   +0x010 ObjectCreateInfo : 0x00000001 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : 0x00000001 
   +0x014 SecurityDescriptor : 0xe10073d7 
   +0x018 Body             : _QUAD

The NameInfoOffset member tells us that there is information about the object's name available 0x10 bytes in front of the common object header.

kd> db e1347370-10 L 10
e1347360  88 47 00 e1 86 00 86 00-d8 84 39 e1 01 00 00 00  .G........9.....

Now what does that tell us? The first four bytes (0xe1004788) are a pointer back to the object directory that contains this object. The next eight bytes again are a Unicode string:

kd> !ustr e1347360+4
String(134,134) at e1347364: ACPI#FixedButton#2&daba3ff&0#{4afa3d53-74a7-11d0-be5e-00a0c9062857}

So, this is the last piece of information that was missing, the object's name. With the help of the Volatility memory analysis framework it is not too hard to turn that knowledge into a scanner for symbolic link objects. Please make a backup copy of your installation. Then unzip the archive in your Volatility base directory. If you use the version from the current Volatility SVN, then please copy only the plugin file.

Now issue
python volaltility symlinkobjscan -f filename
to scan your memory image for symbolic link kernel objects. Here are excerpts from two sample images to demonstrate the symbolic link scanner.

The following symbolic links show the mapping between drive letters and devices. The user mapped the "T:" drive to a VMware shared folder a couple of minutes after the system was booted.

Time created              Name -> Target
Fri Apr 10 09:55:17 2009  C: -> \Device\HarddiskVolume1
Fri Apr 10 09:55:35 2009  A: -> \Device\Floppy0
Fri Apr 10 09:55:35 2009  D: -> \Device\CdRom0
Fri Apr 10 08:58:51 2009  T: -> \Device\HGFS

The following example shows the well-known Hacker Defender rootkit. Again the creation time clearly sticks out, but that would not be the case after a reboot.

Time created              Name -> Target
Fri Apr 10 09:55:35 2009  NdisWan -> \Device\NdisWan
Fri Apr 10 08:58:37 2009  HxDefDriver -> \Device\HxDefDriver
Fri Apr 10 09:55:34 2009  RdpDrDvMgr -> \Device\RdpDrDvMgr



This blog is a project of:
Andreas Schuster
Im Äuelchen 45
D-53177 Bonn

Copyright © 2005-2012 by
Andreas Schuster
All rights reserved.