Hiya guys,
I'm pretty new here, so forgive me for bursting in and asking lots of
questions, but I'm trying to get used to the codebase (I've had some fun
running pylint across this, which helped a *lot* with trying to figure
out what went where).
I'd really like to add a layer that allows the existing volatility tools
to be run against a live system, directly via firewire (ie, without
having to completely image the system first). I should probably mention
now that I'm from a penetration testing background, rather than a
forensics background, but that I've been investigating the firewire
technique metlstorm developed for a while now. My hope is that some of
the hash dumping tools and similar might be much quicker when run
directly, rather than having to image the entire system first, and that
it might also help the volatility suite be used as a live debugging aide
for people trying to learn about memory and how it works.
It seemed as though everything was laid out nicely, so I'd just need to
implement a FirewireAddressSpace object (which I've done, and attached,
although I have yet to test it). The problem I found was that all
forensics.commands.command subclasses appear to accept an optparse
parser result, and then manually open their own image based on the
filename. Since most of the functions seem to operate on an
AddressSpace rather than on a filename string, it seemed as though it
should be possible to pass that into the plugins/commands. So that
leads me to a few questions:
* Would it be worthwhile reworking the module system to allow modules to
specify their requirements more abstractly (I need a memory image, I
need a set of registry keys, etc)?
* Would it need to be that abstract, or do pretty much all modules
always act on an AddressSpace?
* How are you guys intending to deal with upgrading plugins after a
major enhancement (I noticed plugins are already getting a bit out of
hand, since Andreas' plugins require overwriting bits of volatility with
his own versions)?
* Would it be a major version number bump with an API break, and if so
are there any other changes that would be worthwhile addressing at the
same time?
* Should I investigate allowing multiple plugin versions to co-exist?
In implementing a new AddressSpace, I also spotted this fast variable,
that appears simply to open a new handle, and I can't figure out how
that helps or makes it faster? Was this a place holder for a possible
address space enhancement, or is there really some kind of speed-up
which I'm missing?
Sorry to kind of drop all this here, but it seemed the most appropriate
place for it. I've joined the IRC channel as well, so if you want to
poke me for not doing things sensibly, you'll find me on there as
ikelos... 5:)
Thanks,
Mike 5:)
diff --git a/Volatility/forensics/addrspace.py b/Volatility/forensics/addrspace.py
index d0c0dee..8697f71 100755
--- a/Volatility/forensics/addrspace.py
+++ b/Volatility/forensics/addrspace.py
@@ -30,6 +30,7 @@
""" Alias for all address spaces """
import os
+import sys
import struct
try:
@@ -73,7 +74,7 @@ class FileAddressSpace:
return False
return addr < self.fsize - 1
- def close():
+ def close(self):
self.fhandle.close()
class BufferAddressSpace(FileAddressSpace):
@@ -85,3 +86,103 @@ class BufferAddressSpace(FileAddressSpace):
if fast == True:
self.fast_fhandle = StringIO(buf)
+
+try:
+ import firewire
+except:
+ pass
+
+if 'firewire' in sys.modules:
+
+ def intervals(exclusions, start, end):
+ """Returns a list of intervals, from start to end, that do not
include the exclusions"""
+ return _intervals(sorted(exclusions), start, end, [])
+
+ def _intervals(exclusions, start, end, accumulator):
+ """Accepts a sorted list of intervals and a start and end
+
+ This will return a list of intervals between start and length
+ that does not contain any of the intervals in the list of exclusions.
+ """
+ if not len(exclusions):
+ # We're done
+ return accumulator + [(start, end)]
+
+ e = exclusions[0]
+ estart = e[0]
+ eend = e[1]
+
+ # e and range overlap
+ if not (eend < start or estart > end):
+ # Ignore this exclusions
+ return intervals(exclusions[1:], start, end, accumulator)
+ if estart < start:
+ if eend < end:
+ # Covers the start of the remaining length
+ return intervals(exclusions[1:], eend, end, accumulator)
+ else:
+ # Covers the entire remaining area
+ return accumulator
+ else:
+ if eend < end:
+ # Covers a section of the remaining length
+ return intervals(exclusions[1:], eend, end, accumulator + [(start,
estart)])
+ else:
+ # Covers the end of the remaining length
+ return accumulator + [(start, estart)]
+
+ class FirewireIO(object):
+ """File-like interface for Firewire devices"""
+ def __init__(self, bus, node):
+ self.offset = 0
+ self.fsize = 4 * 1024 * 1024 * 1024
+ self.closed = False
+ self._exclusions = [(0xa0000, 0xfffff, "Upper Memory Area")]
+ try:
+ h = firewire.Host()
+ self._node = h[bus][node]
+ except IndexError:
+ raise IOError, "Firewire node " + str(node) + " on bus
" + str(bus) + " was not accessible"
+
+ def close(self):
+ """Close function for file-like interface"""
+ self.closed = True
+
+ def flush(self):
+ """Flush function for file-like interface"""
+ pass
+
+ def read(self, size = -1):
+ if size < 0:
+ size = self.fsize
+ ints = intervals(self._exclusions, self.offset, self.offset + size)
+ output = "\x00" * size
+ for i in ints:
+ output = output[: i[0] - self.offset] + self._node.read(i[1] - i[0],
i[0]) + output[i[1] - self.offset:]
+ return output
+
+ def seek(self, offset, whence = os.SEEK_SET):
+ """Seek function for file-like interface"""
+ self.offset = offset
+ if (whence == os.SEEK_CUR):
+ self.offset += offset
+ elif (whence == os.SEEK_END):
+ self.offset = self.fsize - offset
+
+ def tell(self):
+ """Tell function for file-like interface"""
+ return self.offset
+
+ def write(self, string):
+ pass
+
+ class FirewireAddressSpace(FileAddressSpace):
+ def __init__(self, bus, node, fast=False):
+ self.fname = "Firewire on bus " + bus + " node " + node
+ self.name = self.fname
+ self.fhandle = FirewireIO(bus, node)
+ # Theoretical limit
+ self.fsize = self.fhandle.fsize
+
+ if fast == True:
+ raise RuntimeError("Fast mode for firewire not implemented")
\ No newline at end of file