ksanchezcld / volatility

Automatically exported from code.google.com/p/volatility
GNU General Public License v2.0
1 stars 0 forks source link

pslist does not handle smeared images #198

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
The pslist module works by iterating over the _EPROCESS.ActiveProcessLinks 
linked list.

However this list is only traversed in the forward direction. I have several 
images which exhibit smear in that for some _EPROCESS instances the Flink is 
invalid (while the Blink may be valid). This causes pslist right now to stop 
and therefore not display all the process.

List traversal should be fixed so that we follow Flink and Blink for each iterm 
in the list.

Original issue reported on code.google.com by scude...@gmail.com on 1 Feb 2012 at 7:41

GoogleCodeExporter commented 9 years ago

Original comment by jamie.l...@gmail.com on 1 Feb 2012 at 7:45

GoogleCodeExporter commented 9 years ago
Fixed by r1337  (heh that commit is so leet!)

Original comment by scude...@gmail.com on 2 Feb 2012 at 1:38

GoogleCodeExporter commented 9 years ago
Any idea what causes the Flink to be invalid? Is it invalid because it points 
to paged memory or invalid because its been overwritten either maliciously or 
accidentally (wow that's bad for whoever wrote the responsible driver). 

Do other linked lists in those images also have invalid Flinks? Like modules, 
dlls, etc? 

Original comment by michael.hale@gmail.com on 2 Feb 2012 at 8:14

GoogleCodeExporter commented 9 years ago
I can only assume this is happening because the EPROCESS for a linked in 
process has been freed by the time this region was imaged - this seems 
reasonable to me, especially if the imaging is slow (e.g. over network). I 
added some print statements around the place and I can see:

PsActiveList = PsActiveProcessHead.dereference_as("_LIST_ENTRY")

print PsActiveList.d()

[_LIST_ENTRY _LIST_ENTRY] @ 0x8278AB98
 Flink - <NoneObject Flink pointer to [0x838CEDC0]>
 Blink - <_LIST_ENTRY Blink pointer to [0x85B536C0]>

And also:

0x83efe020 smss.exe                208      4      2     29 2012-01-30 12:06:18 

[_LIST_ENTRY ActiveProcessLinks] @ 0x83EFE0D8
 Flink - <_LIST_ENTRY Flink pointer to [0x839C4360]>
 Blink - <NoneObject Blink pointer to [0x838CEDC0]>

On this particular image, trunk returns no pslist because the very first Flink 
is invalid. In the trunk code, as soon as we hit the first invalid entry we 
quit which makes it very fragile. In the new code we can handle a variety of 
races (like Flink valid but Blink not yet) and can resort to using the Blink to 
traverse the list.

Original comment by scude...@gmail.com on 2 Feb 2012 at 9:39

GoogleCodeExporter commented 9 years ago
Hmm... Ok I have dug more into this and the plot thickens :-)

So I was using win32dd to take this image. I traced through the 
Flink.is_valid() call above to learn that the Virtual Address 0x838CEDC0 is 
mapped just outside the image (Thats why its invalid) so it seems that the 
image is too short!

I went back to the win32dd source code and it calculates the image size using:

MiGetTotalPhysicalPages() {
  ZwQuerySystemInformation()
  ...

  return SystemBasicInfo.NumberOfPhysicalPages;
};

However, the image size is calculated 

IoWriteRawDump_Level0() {
...
TotalPhysicalPages = MiGetTotalPhysicalPages();
...
  for (PageIndex = 0; PageIndex < TotalPhysicalPages; PageIndex++) {
...
  };
};

So as you can see this is a bug because the operating system does not use all 
the physcial ram. So while the total number of pages is correct, it does not 
start at zero. Memory is used in ranges (Runs) and you can get the start and 
length of each range:

PPHYSICAL_MEMORY_RANGE  MmPhysicalMemoryRange = MmGetPhysicalMemoryRanges();

while ((MmPhysicalMemoryRange[NumberOfRuns].BaseAddress.QuadPart != 0) &&
           (MmPhysicalMemoryRange[NumberOfRuns].NumberOfBytes.QuadPart != 0)) {
      NumberOfRuns++;
      DbgPrint("Run %llX to %llX\n", 
               MmPhysicalMemoryRange[NumberOfRuns].BaseAddress,
               MmPhysicalMemoryRange[NumberOfRuns].NumberOfBytes);
    };

And we can see that the range actually starts at address 0x100000 (with the 
same number of pages). This is why the original image is a little too short.

I have it working right now and will commit the fix later today.

Original comment by scude...@gmail.com on 2 Feb 2012 at 11:06

GoogleCodeExporter commented 9 years ago
Nice detective work Scudette! Do you guys we should still alter the behavior of 
_LIST_ENTRY now that the problem can be attributed to a fault in the 
acquisition? 

Original comment by michael.hale@gmail.com on 4 Feb 2012 at 4:14

GoogleCodeExporter commented 9 years ago
Definitely. I think the list_entry function should be as robust as
possible because there is a chance that lists might be broken for
whatever reason. Admittedly this was not the case here so I am not
sure how likely it is, but it is possible.

Original comment by scude...@gmail.com on 4 Feb 2012 at 6:40

GoogleCodeExporter commented 9 years ago

Original comment by mike.auty@gmail.com on 10 Mar 2012 at 11:39

GoogleCodeExporter commented 9 years ago

Original comment by michael.hale@gmail.com on 1 Feb 2013 at 4:41

GoogleCodeExporter commented 9 years ago

Original comment by jamie.l...@gmail.com on 6 Jan 2014 at 7:10

GoogleCodeExporter commented 9 years ago
In the cases we've seen, smeared images are result of bad acquisitions. There 
is some value in knowing when you're dealing with a corrupt image, so leaving 
pslist as-is will be fine. If the LIST_ENTRY pointers are smeared/invalid, you 
can always find them using psscan. 

Original comment by michael.hale@gmail.com on 7 Mar 2014 at 6:42