Hi Mike,
On Sun, Sep 20, 2009 at 11:30 AM, Mike Auty <mike.auty(a)gmail.com> wrote:
Hi guys,
Here's another pylint patch, much of it the same as the last one, but
this one applies to the new_object branch (it's probably a bit better
than the last one).
Thanks for that - the patch didnt seem to make it for me (it ended up
being a 14 byte bz2 file - maybe gmail stole it?).
new_object requires utils.py[1] and linked_lists.py[2]
to work, and the
patch requires their presence. Please be aware, I don't have a complete
Not exactly - the new object scheme itself doesnt need these as these
functions were merged into the new object code. However, since I still
had the old object code lying around there might have been some
references left over. I dont think they are used though. (linked lists
are now handled automatically by overlaying a
class _LIST_ENTRY(CType) definitions on top of the struct member -
defined in memory_objects/Windows/xp_sp2.py). utils.py is in the svn
tree (or it should be).
library of images to test this stuff against, so
whilst none of the
changes should break anything, if they do, please let me know and I'll
be happy to fix them up (particularly if you've got an image I can test
them against!). 5:)
I think the load_as function from utils.py (which makes use of the new
address_space voting scheme that scudette wrote) will make a huge
difference to the duplication going on in all the plugins, so my next
step is going to be converting vmodules.py into individual plugin files,
and then converting each one to use the new address_space system. Once
Some of that work is already done - please have a look at the new
plugins which are doing much the same things - I just left vmodules
there as a guide as to whats left to do. For example get_pslist() is
now powered by a rewritten pslist() in ./forensics/win32/tasks.py and
is used in the module memory_plugins/pstree.py for example.
I get good at that, I can start taking on externally
written plugins, if
it'll help? I think maintaining backwards compatibility will clutter an
already complicated layout, so I'd sooner offer my time to convert other
people's plugins, than try and maintain two mechanisms side-by-side and
I dont think backwards compatibility is a realistic goal we can have
when we change the underlying framework. I am more happy with a linux
style development model where everyone is free to have their own
modules, but committing them to the main tree will ensure they get
maintained as the code evolves.
hope people don't get confused about which one
they should be using.
With the namespace cleanup happening anyway, this seems like an ideal
time to drop any deprecated code, unless people think otherwise?
After that, I'm going to have a go at converting them from Object to
NewObject calls. Does anyone know whether NewObject is a drop in
replacement for Object, or if there are specific changes required (such
as, does NewObject require Profiles, or will it still work with normal
types arrays)?
It is not a drop in replacement at all - Hopefully its easier to use
than the old Object code. The new object code implements the
__getitem__ protocol so you can just do something like:
task_info['image_file_name'] = task.ImageFileName or
'UNKNOWN'
task_info['process_id'] = task.UniqueProcessId.v() or -1
task_info['active_threads'] = task.ActiveThreads or -1
task_info['inherited_from'] =
task.InheritedFromUniqueProcessId.v() or -1
task_info['handle_count'] = task.ObjectTable.HandleCount or -1
task_info['create_time'] = task.CreateTime
If the pointer is NULL it returns a NoneObject which can be used as
the LHS of or to continue assignment (giving defaults).
Also, I wondered what people's thoughts were (as a
long term goal) on
integrating the Object2/NewObject code with the object code, so that all
the familiars like read_string and so on, would be done through the one
single object model?
read_string and friends should be deprecated since the act of reading
from struct members is now fully implemented by the struct members
themselves - not by an external function. As an example here is
moyix's registry code:
class _CM_KEY_NODE(Object):
"""Class representing a _CM_KEY_NODE
Adds the following behavior:
* Name is read as a string.
"""
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
return obj
# Custom Attributes
def getName(self):
return read_string(self.vm, types, ['_CM_KEY_NODE', 'Name'],
self.offset, self.NameLength)
Name = property(fget=getName)
implementing getName. This is now replaced by the new object
definition (from ./forensics/win32/overlay.py):
'_CM_KEY_NODE' : [ None, {
'Signature' : [ None, ['String', dict(length=2)]],
'LastWriteTime' : [ None, ['WinTimeStamp', {}]],
'Name' : [ None, ['String', dict(length=lambda x: x.NameLength)]],
}],
So you dont need read_string() at all - the object itself knows how to
do it. If x is a _CM_KEY_NODE then x.Name will return the string via
instantiating the String() object on the right AS.
BTW. The stuff defined in overlay.py can be thought of basically as
"fixups" to the vtypes (which are autogenerated from .h files). Where
we have None we dont override the vtypes definition, and if we have
something we do. So the overlay can be read in conjunction with the
vtypes definition:
'_CM_KEY_NODE' : [ 0x50, {
'Signature' : [ 0x0, ['String', dict(length=2)]],
'Flags' : [ 0x2, ['unsigned short']],
....
In this case I put the String definition into vtypes, but if it comes
from an autogenerated header file parser it might have crap in there
(like void* ) for example. In this case the overlay can fix it up.
Note the lambda in the args for the String class - it gets evaluated
at construction time and has access to the new struct, so it can
easily return a String with length x.NameLength. Therefore we dont
need a special class override for _CM_KEY_NODE to call a read_string
function.
So, once all the modules are in their own individual
files, and the
imports are all explicit, it should become much easier to move things
around, and get volatility into it's own namespace. Once that's been
done, I'll probably do a sweep over the code changing all the direct
imports (from blah.mumble import foo) to slightly more explicit ones
(import blah.mumble) or similar. The reason I'd do this is because the
imports were all over the place (as evidenced by the fact that not one
internal plugin imported forensics.commands!), and the namespaces were
getting messed up (so most of the plugins were importing gmtime from
other volatility modules, rather than from time itself). The main
question becomes, would it be tedious/ugly to have such long names (like
"volatility.forensics.win32.tasks.process_handle(blah)") or are they not
called often enough to make coding cumbersome? What do people think?
i dont like using the "from xxx import *" form because its messy and
pollutes the namespaces. We should use something like "import x.y.z as
z" to make things explicit and also keep module reference short.
That should cover the first three items on the todo
list[3], and four
and five I've got existing code[4] that should get everything sorted
with the installation system, and allow volatility.exe binaries to be
created (there'll need to be some code modifications to allow plugins to
be dropped into directories external to the executable, but that's all
doable)...
The plugin architecture (which came from PyFlag originally) is used to
make management of the code much easier for large project - not so
much to allow other people to maintain their own plugins seperate from
the codebase. I think long term compatibility will be a huge issue and
a maintenance nightmare - we really need to bring all modules to the
same tree. In PF we can add new plugin directories via the --plugins
directive (I think this is already in the volatiltiy version of the
registry code).
Then it's just merging the linux stuff in (where
does that come from?)
and lots and lots and lots of documentation!!! Anyone want to help out
with that? It'd really help to have some words about how scudette's
NewObject system works from anyone who understands it... 5:)
Yeah I should probably start documenting it a bit more .... Its
probably stopping people from adopting it right now :-)
Thanks,
Michael.