cs24 / volatility

Automatically exported from code.google.com/p/volatility
0 stars 0 forks source link

Error parsing Win2k3Sp1 VAD #164

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
$ python vol.py -f Win2K3SP1x86-Snapshot1.vmem --profile=Win2K3SP1x86 vadinfo

[snip] 

VAD node @81dba048 Start 7ffaf000 End 7ffaffff Tag Vadl
Flags: PhysicalMapping, PrivateMemory, WriteWatch
Commit Charge: 1 Protection: 4
First prototype PTE: 81e0d038 Last contiguous PTE: 00000000
Flags2: LongVad, OneSecured
File offset: 00000000

VAD node @81df20b8 Start 7ffda000 End 7ffdafff Tag Vadl
Flags: PhysicalMapping, PrivateMemory, WriteWatch
Commit Charge: 1 Protection: 4
ControlArea @81df20a0 Segment 00000000
Dereference list: Flink 000012f0, Blink 0000136f
NumberOfSectionReferences: 2214592513 NumberOfPfnReferences:   168296452
NumberOfMappedViews:       1818517846 NumberOfUserReferences: 2178840712
WaitingForDeletion Event:  0007ffda
Flags: CollidedFlush, Commit, DebugSymbolsLoaded, DeleteOnClose, 
FilePointerNull, GlobalMemory, HadUserReference, Image, Networked, NoChange, 
PhysicalMemory, UserReference
Invalid Address 0x0008000A, instantiating FileName

<-- stops here but its only done 4-5 processes

As you can see, many of the VAD fields look irregular (the Flink, Blink, 
NumberOfSectionReferences, etc). There is no stack dump, just stops after the 
Invalid Address message. 

I can share the memory dump with people willing to look into it...just drop me 
a note. 

Original issue reported on code.google.com by michael.hale@gmail.com on 29 Oct 2011 at 12:15

GoogleCodeExporter commented 8 years ago
We'll compare with windbg and investigate in particular the ControlArea 
structure. 

Original comment by michael.hale@gmail.com on 13 Dec 2011 at 3:13

GoogleCodeExporter commented 8 years ago
Turns out I still have access to the live machine from which this memory dump 
was taken. I started up windbg and checked a few things. From the above 
comment, note the important factors:

VAD node @81df20b8 Start 7ffda000 End 7ffdafff Tag Vadl 
ControlArea @81df20a0 Segment 00000000
Invalid Address 0x0008000A, instantiating FileName

So the MMVAD_LONG is at 81df20b8 for starting address 7ffda000, the 
CONTROL_AREA is allegedly 81df20a0, and from there the 
CONTROL_AREA.FilePointer.FileName is invalid. The process we're dealing with is 
winlogon.exe: 

kd> !process 0 0 
PROCESS 81dff6a8  SessionId: 0  Cid: 01dc    Peb: 7ffdf000  ParentCid: 017c
    DirBase: 168ae060  ObjectTable: e12b80d0  HandleCount: 520.
    Image: winlogon.exe

kd> !vad 81dff6a8 + 250 
81df20b8 ( 4)      7ffda    7ffda         1 Private      READWRITE   

kd> dt _MMVAD_LONG 81df20b8
nt!_MMVAD_LONG
   +0x000 u1               : __unnamed
   +0x004 LeftChild        : 0x81de7888 _MMVAD
   +0x008 RightChild       : 0x81df2520 _MMVAD
   +0x00c StartingVpn      : 0x7ffda
   +0x010 EndingVpn        : 0x7ffda
   +0x014 u                : __unnamed
   +0x018 ControlArea      : 0x81df20a0 _CONTROL_AREA
   +0x01c FirstPrototypePte : (null) 
   +0x020 LastContiguousPte : 0x81df2e70 _MMPTE
   +0x024 u2               : __unnamed
   +0x028 u3               : __unnamed
   +0x030 u4               : __unnamed

So there really is an MMVAD_LONG at the address printed by vadinfo, and its 
CONTROL_AREA really is at 0x81df20a0. No issues with Volatility's VAD parsing 
yet per se. Now let's check out the CA:

kd> dt _CONTROL_AREA 0x81df20a0 
nt!_CONTROL_AREA
   +0x000 Segment          : (null) 
   +0x004 DereferenceList  : _LIST_ENTRY [ 0x12f0 - 0x136f ]
   +0x00c NumberOfSectionReferences : 0x84000001
   +0x010 NumberOfPfnReferences : 0xa080004
   +0x014 NumberOfMappedViews : 0x6c646156
   +0x018 NumberOfSystemCacheViews : 0x81e05e18
   +0x01c NumberOfUserReferences : 0x81de7888
   +0x020 u                : __unnamed
   +0x024 FilePointer      : 0x0007ffda _FILE_OBJECT
   +0x028 WaitingForDeletion : 0x0007ffda _EVENT_COUNTER
   +0x02c ModifiedWriteCount : 1
   +0x02e FlushInProgressCount : 0x8488
   +0x030 WritableUserReferences : 0x81df20a0
   +0x034 QuadwordPad      : 0

All the crazy values printed by vadinfo are correct, just as they appear in the 
windbg output. The specific member causing the vadinfo command to abort is 
FilePointer = 0x0007ffda. See the line: 

http://code.google.com/p/volatility/source/browse/trunk/volatility/plugins/vadin
fo.py#84

....format(FO.obj_offset, FO.FileName.Buffer, FO.FileName))

When accessing FO.FileName, it causes obj.BaseObject to raise 
InvalidOffsetError. This call is made from VADInfo.write_vad_control() and 
there is a try/except block around it, but only for catching AttributeError:

try:
    self.write_vad_control(outfd, vad)
except AttributeError:
    pass

So a possible fix, that allows vadinfo to continue printing the other vads 
instead of aborting:

try:
    self.write_vad_control(outfd, vad)
except (AttributeError, obj.InvalidOffsetError):
    pass

I'd like to discuss if this placement of the fix is good, or if you want to 
place it elsewhere or do something else entirely. As long as vadinfo doesn't 
come to a complete halt when parsing these invalid fields. 

By the way, you might notice that ControlArea.FilePointer (0x0007ffda) is 
followed by ControlArea.WaitingForDeletion which is also 0x0007ffda. That 
sounds ironically similar to the StartingVpn and EndingVpn values of the 
MMVAD_LONG itself:

  +0x00c StartingVpn      : 0x7ffda
   +0x010 EndingVpn        : 0x7ffda

If the MMVAD_LONG is at 81df20b8 and the ControlArea pointer is 0x81df20a0, 
that means the ControlArea points to -0x18 bytes behind the actual MMVAD_LONG. 
What is the significance of 0x18? Its the offset of MMVAD_LONG.ControlArea:

+0x018 ControlArea 

What the fuzz?

Original comment by michael.hale@gmail.com on 14 Dec 2011 at 7:16

GoogleCodeExporter commented 8 years ago
Attaching some supporting data for LabarumXP

Original comment by michael.hale@gmail.com on 14 Dec 2011 at 7:32

Attachments:

GoogleCodeExporter commented 8 years ago
At first I just thought this was something crazy and isolated to the current 
state of my w2k3sp1 system. But after rebooting, there are still similar issues 
(and not just with the winlogon process). Also going back to some XP and Win7 
systems, the ControlArea is often not even in kernel mode. For example:

VAD node @821d69c8 Start 7ffde000 End 7ffdefff Tag Vadl
Flags: MemCommit, NoChange, PrivateMemory
Commit Charge: 1 Protection: 4
ControlArea @00010100 Segment 0057005c
Dereference list: Flink 004e0049, Blink 004f0044
NumberOfSectionReferences:    5439575 NumberOfPfnReferences:     7536732
NumberOfMappedViews:          7536761 NumberOfUserReferences:    3342445
WaitingForDeletion Event:  002e0064
Flags: BeingCreated, CollidedFlush, DebugSymbolsLoaded, DeleteOnClose, 
FailAllIo, FilePointerNull, Image
FileObject: none
First prototype PTE: 82293bd8 Last contiguous PTE: 823cd638
Flags2: LongVad, OneSecured
File offset: 00000000

Is there a flag somewhere that says if the ControlArea is used/unused and the 
OS just sets that flag rather than NULL-ing out the ControlArea pointer when 
its not in use? 

In some cases I've even seen ControlArea be 00000000. We should not be printing 
the ControlArea fields if the pointer is NULL. For example:

VAD node @81a59770 Start 00160000 End 0025ffff Tag Vadl
Flags: PrivateMemory
Commit Charge: 63 Protection: 4
ControlArea @00000000 Segment 30000000
Dereference list: Flink f000ff53, Blink f000e2c3
NumberOfSectionReferences: 4026597203 NumberOfPfnReferences:  4026597203
NumberOfMappedViews:       4026597204 NumberOfUserReferences: 4026597203
WaitingForDeletion Event:  f0000b01
Flags: BeingDeleted, BeingPurged, Commit, CopyOnWrite, File, FloppyMedia, 
GlobalOnlyPerSession, Image, NoCache, PhysicalMemory, Reserve, Rom, WasPurged
FileObject: none
First prototype PTE: 00000000 Last contiguous PTE: 00000000
Flags2: LongVad, ReadOnly
File offset: 00000000

How does that pass the check in vadinfo anyway?

CA = vad.get_control_area()

if not CA:
     #debug.b()
     return

We end up having to do this:

if not CA or CA == 0:

But that still doesn't prevent us from printing the fields of a ControlArea if 
the pointer is 1 instead of 0. Also note due to 
http://code.google.com/p/volatility/issues/detail?id=144 most of the vad flags 
are being printed incorrectly bc of overlay issues. 

Original comment by michael.hale@gmail.com on 14 Dec 2011 at 8:21

GoogleCodeExporter commented 8 years ago
A friend chimed in that VADs with the PrivateMemory flag set never have a valid 
ControlArea (even if ControlArea is not NULL). We can use this as an indicator 
of when to print the ControlArea members or not. However, in order to test if 
the PrivateMemory bit is set, we'll need to first address issues 143 and 144. 

Original comment by michael.hale@gmail.com on 14 Dec 2011 at 10:33

GoogleCodeExporter commented 8 years ago
This issue was closed by revision r1161.

Original comment by michael.hale@gmail.com on 15 Dec 2011 at 9:53