ksanchezcld / volatility

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

breakage in the -o parameter to vadinfo (patch 1195 from win64-support) #216

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Hey guys, 

I found evidence of a bug that's been brewing for a while (since r1195 which 
was carried over from win64-support). I'm posting my findings where so we can 
understand it better. 

In Volatility 2.0, the vadinfo plugin works with -p (specify pid) and -o 
(specify physical offset). The big difference is that when -p is supplied, the 
EPROCESS is instantiated by walking PsActiveProcessHead's LIST_ENTRY and when 
-o is supplied, the EPROCESS is instantiated in 
DllList.virtual_process_from_physical_offset using either 
ethread.ThreadsProcess.dereference() or 
ethread.Tcb.Process.dereference_as("_EPROCESS") depending on the profile 
(Vista/Win7 use the Tcb.Process method). 

$ sudo python vol.py -f mem.dmp vadinfo -o 0x173a208
Volatile Systems Volatility Framework 2.0
************************************************************************
Pid:    708
VAD node @81779208 Start 00190000 End 0019ffff Tag VadS
Flags: PrivateMemory
Commit Charge: 6 Protection: 4
.....

OK, no problem there.  However, starting in r1195, vadinfo still works with -p 
just fine, but breaks with -o:

$ svn update --revision 1195
U    volatility/plugins/overlays/windows/windows.py
U    volatility/plugins/overlays/windows/xp_sp2_x86.py
Updated to revision 1195.

$ sudo python vol.py -f mem.dmp vadinfo -o 0x173a208
Volatile Systems Volatility Framework 2.1_alpha
************************************************************************
Pid:    708
Traceback (most recent call last):
 File "vol.py", line 135, in <module>
   main()
 File "vol.py", line 126, in main
   command.execute()
 File "/home/user/volatility/volatility/commands.py", line 101, in execute
   func(outfd, data)
 File "/home/user/volatility/volatility/plugins/vadinfo.py", line
42, in render_text
   for vad in task.VadRoot.traverse():
 File "/home/user/volatility/volatility/obj.py", line 335, in __getattr__
   return getattr(proxied, attr)
AttributeError: 'long' object has no attribute 'traverse'

I'm pretty sure in this case, the patch for r1195 was first to
introduce the bug. However, starting with r1297, the error output
starts to change:

$ svn update --revision 1297
U    volatility/obj.py
Updated to revision 1297.

$ sudo python vol.py -f mem.dmp vadinfo -o 0x173a208
Volatile Systems Volatility Framework 2.1_alpha
************************************************************************
Pid:    708
Traceback (most recent call last):
 File "vol.py", line 135, in <module>
   main()
 File "vol.py", line 126, in main
   command.execute()
 File "/home/user/volatility/volatility/commands.py", line 101, in execute
   func(outfd, data)
 File "/home/user/volatility/volatility/plugins/vadinfo.py", line
94, in render_text
   for vad in task.VadRoot.traverse():
 File "/home/user/volatility/volatility/obj.py", line 602, in __getattr__
   result = self.dereference()
 File "/home/user/volatility/volatility/obj.py", line 581, in dereference
   name = self.obj_name)
 File "/home/user/volatility/volatility/plugins/overlays/windows/windows.py",
line 502, in __new__
   vm = eprocess.get_process_address_space()
AttributeError: 'NoneType' object has no attribute 'get_process_address_space'

That is the current error displayed in trunk. First of all, what exactly 
changed in r1195: http://code.google.com/p/volatility/source/detail?r=1195 
("Port across the Vad Tag handling from the win64-support branch.")

We replaced this; 

if vm.name.startswith("Kernel"):
    eprocess = obj.Object("_EPROCESS", offset = parent.obj_offset, vm = vm)

With this:

if vm.name.startswith("Kernel"):
    # Find the next _EPROCESS along our parent list
    eprocess = parent
    while eprocess and eprocess.obj_name != "_EPROCESS":
         eprocess = eprocess.obj_parent

To investigate the problem, I printed parent.__dict__. In cases when -p is 
supplied, you see this:

'_vol_parent':  [unsigned long long]: 2153122776, '_vol_theType': '_EPROCESS', 
'_vol_offset': 2171838984L, '_vol_native_vm': 
<volatility.plugins.addrspaces.intel.JKIA32PagedMemory object at 0xad519ec>, 
'_vol_vm': <volatility.plugins.addrspaces.intel.JKIA32PagedMemory object at 
0xad519ec>, '_vol_name': '_EPROCESS'}

In cases when -o is supplied, you see this:

 '_vol_parent': [_ETHREAD _ETHREAD] @ 0x81734020, '_vol_theType': '_EPROCESS', '_vol_offset': 2171838984L, '_vol_native_vm': None, '_vol_vm': <volatility.plugins.addrspaces.intel.JKIA32PagedMemory object at 0xb85eaac>, '_vol_name': 'ThreadsProcess'}

The big difference is _vol_name which is _EPROCESS with -p and ThreadsProcess 
with -o. So the simple fix for this bug is a patch like this:

Index: volatility/plugins/overlays/windows/windows.py
===================================================================
--- volatility/plugins/overlays/windows/windows.py  (revision 1452)
+++ volatility/plugins/overlays/windows/windows.py  (working copy)
@@ -521,7 +521,8 @@
         if vm.name.startswith("Kernel"):
             # Find the next _EPROCESS along our parent list
             eprocess = parent
-            while eprocess and eprocess.obj_name != "_EPROCESS":
+            print parent.__dict__
+            while eprocess and (eprocess.obj_name not in ["_EPROCESS", 
"ThreadsProcess", "Process"]):
                 eprocess = eprocess.obj_parent

That takes care of it regardless of how the EPROCESS is instantiated. I may 
apply this as a temporary patch (or permanent depending on how this discussion 
goes). However for moving forward, it would be cool to understand why we 
deviated from using parent.obj_offset to a while loop looking for _EPROCESS as 
the parent. 

In particular, what cases are there that an _MMVAD's parent would not be 
_EPROCESS but the parent's parent or paren't parent's parent would be 
_EPROCESS? 

Original issue reported on code.google.com by michael.hale@gmail.com on 21 Feb 2012 at 2:24

GoogleCodeExporter commented 9 years ago
I think this same class factory is used for all the _MMVAD structures
and so for deeper structures in the list, the parent will not be an
_EPROCESS but something else. This patch attempts to traverse up the
tree to find the _EPROCESS.

My understanding of the -o option is simply to allow someone to
specify the eprocess in terms of the physical offset. I think we need
to separate these concerns and just have some utility for converting
an _EPROCESS from physical to virtual AS (maybe another module), while
requiring the offset here to be given in the virtual AS.

The correct solution is probably to switch AS to the process AS when
getting the initial MMVAD rather than use the __new__ method, this way
for all members of the tree, they will always use the process AS.

Michael.

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

GoogleCodeExporter commented 9 years ago
Thanks for the explanation Scudette! So I applied the temporary patch in r1457 
and will leave this issue open for discussing a more correct/thorough solution 
like removing __new__. 

Original comment by michael.hale@gmail.com on 21 Feb 2012 at 2:43

GoogleCodeExporter commented 9 years ago
So actually the obj_type for both will be _EPROCESS.  Unfortunately at the 
moment that isn't exposed so we're relying on obj_name (which is the name of 
the element within the struct, rather than the type that element has).  This 
should also answer a question scudette posed, which was what's the difference 
between theType and name, one is the type of the element and the other's the 
name of the element...

So, ideally the patch should add a property to objects called obj_type or 
obj_thetype which then just returns _vol_thetype, and then we use that to 
determine when we hit an EPROCESS, rather than the name of the field.  MHL, 
want to have a crack at that, or should I do it on the weekend?

Original comment by mike.auty@gmail.com on 21 Feb 2012 at 8:31

GoogleCodeExporter commented 9 years ago
This issue was closed by revision r1460.

Original comment by michael.hale@gmail.com on 22 Feb 2012 at 2:40