Closed GoogleCodeExporter closed 9 years ago
Original comment by jamie.l...@gmail.com
on 1 Feb 2012 at 7:45
Fixed by r1337 (heh that commit is so leet!)
Original comment by scude...@gmail.com
on 2 Feb 2012 at 1:38
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
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
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
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
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
Original comment by mike.auty@gmail.com
on 10 Mar 2012 at 11:39
Original comment by michael.hale@gmail.com
on 1 Feb 2013 at 4:41
Original comment by jamie.l...@gmail.com
on 6 Jan 2014 at 7:10
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
Original issue reported on code.google.com by
scude...@gmail.com
on 1 Feb 2012 at 7:41