Skip to content

Commit

Permalink
Coverted getservicesids and evtlogs to the new framework. Improved us…
Browse files Browse the repository at this point in the history
…er interface so output is clipped when a pager is defined to avoid hammering the terminal. Added a --recursive option to printkey.

git-svn-id: https://volatility.googlecode.com/svn/branches/scudette@2566 8d5d6628-2090-11de-9909-f37ff7dbbc12
  • Loading branch information
scudette@gmail.com committed Sep 20, 2012
1 parent 562a22c commit 3e35f66
Show file tree
Hide file tree
Showing 23 changed files with 683 additions and 151 deletions.
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@
"volatility.plugins.linux",
"volatility.plugins.overlays",
"volatility.plugins.overlays.linux",
"volatility.plugins.overlays.mac",
"volatility.plugins.overlays.windows",
"volatility.plugins.windows",
"volatility.plugins.windows.gui",
"volatility.plugins.windows.malware",
"volatility.plugins.windows.registry",
"volatility.ui",
Expand Down
10 changes: 8 additions & 2 deletions vol.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,11 @@ def UpdateSessionFromArgv(user_session, FLAGS):

return result

if __name__ == '__main__':
FLAGS = args.parse_args()

def main(argv=None):
global FLAGS

FLAGS = args.parse_args(argv=argv)

logging.basicConfig(level=logging.INFO)

Expand All @@ -138,3 +141,6 @@ def UpdateSessionFromArgv(user_session, FLAGS):
(IPython011Support(user_session) or
IPython012Support(user_session) or
NativePythonSupport(user_session))

if __name__ == '__main__':
main()
13 changes: 13 additions & 0 deletions volatility/ipython_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ def Shell(user_session):
cfg = Config()
cfg.InteractiveShellEmbed.autocall = 2

cfg.PromptManager.in_template = (
r'{color.LightCyan}'
'{session.profile.__class__.__name__}:{session.base_filename}'
'{color.LightBlue}{color.Green} \T> ')

cfg.PromptManager.in2_template = (
r'{color.Green}|{color.LightGreen}\D{color.Green}> ')

cfg.PromptManager.out_template = r'Out<\#> '
cfg.InteractiveShell.separate_in = ''
cfg.InteractiveShell.separate_out = ''
cfg.InteractiveShell.separate_out2 = ''

shell = InteractiveShellEmbed(config=cfg, user_ns=user_session._locals,
banner2=constants.BANNER)

Expand Down
5 changes: 4 additions & 1 deletion volatility/obj.py
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,7 @@ def copy(self):
result = self.__class__(session=self.session)
result.vtypes = copy.deepcopy(self.vtypes)
result.overlays = copy.deepcopy(self.overlays)
result.applied_modifications = self.applied_modifications[:]

# Object classes are shallow dicts.
result.object_classes = self.object_classes.copy()
Expand Down Expand Up @@ -1485,7 +1486,9 @@ def __new__(cls, profile):
except KeyError:
# Return a copy of the profile.
result = profile.copy()
cls.modify(result)
res = cls.modify(result)
result = res or result

result.applied_modifications.append(cls.__name__)

PROFILE_CACHE.Put(key, result)
Expand Down
17 changes: 15 additions & 2 deletions volatility/plugins/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class Info(plugin.Command):

__name = "info"


standard_options = [("output", " Save output to this file."),
("overwrite", " Must be set to overwrite an output "
"file. You can also set this in the session as a "
Expand All @@ -64,6 +63,11 @@ def plugins(self):
if name:
yield name, cls.name, cls.__doc__.splitlines()[0]

def profiles(self):
for name, cls in obj.Profile.classes.items():
if name:
yield name, cls.__doc__.splitlines()[0].strip()

def address_spaces(self):
for name, cls in addrspaces.BaseAddressSpace.classes.items():
yield dict(name=name, function=cls.name, definition=cls.__module__)
Expand Down Expand Up @@ -207,14 +211,23 @@ def _clean_up_doc(self, doc, dedent=0):

def render_general_info(self, renderer):
renderer.write(constants.BANNER)
renderer.section()
renderer.table_header([('Plugin', 'function', "20"),
('Provider Class', 'provider', '20'),
('Docs', 'docs', '[wrap:50]'),
])

for cls, name, doc in self.plugins():
for cls, name, doc in sorted(self.plugins()):
renderer.table_row(name, cls, doc)

renderer.section()
renderer.table_header([('Profile', 'profile', "20"),
('Docs', 'docs', '[wrap:70]'),
])

for name, doc in sorted(self.profiles()):
renderer.table_row(name, doc)



class LoadAddressSpace(plugin.ProfileCommand):
Expand Down
12 changes: 9 additions & 3 deletions volatility/plugins/overlays/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ def __str__(self):
return super(UnicodeString, self).__str__().encode("utf8")

def size(self):
return len(self.v()) * 2
# This will only work if the encoding and decoding are equivalent.
return len(self.v().encode(self.encoding, 'ignore'))

Expand Down Expand Up @@ -191,8 +192,8 @@ def __getattr__(self, attr):
class Enumeration(obj.NativeType):
"""Enumeration class for handling multiple possible meanings for a single value"""

def __init__(self, choices = None, target = "unsigned long", value=None,
default = None, **kwargs):
def __init__(self, choices = None, target="unsigned long", value=None,
default=None, target_args={}, **kwargs):
super(Enumeration, self).__init__(**kwargs)
self.choices = choices or {}
self.default = default
Expand All @@ -203,7 +204,8 @@ def __init__(self, choices = None, target = "unsigned long", value=None,
if value is None:
self.target = target
self.target_obj = self.obj_profile.Object(
target, offset=self.obj_offset, vm=self.obj_vm, context=self.obj_context)
target, offset=self.obj_offset, vm=self.obj_vm, context=self.obj_context,
**target_args)

def v(self, vm=None):
if self.value is None:
Expand Down Expand Up @@ -369,6 +371,10 @@ def __str__(self):

return "-"

def __repr__(self):
return "%s (%s)" % (super(UnixTimeStamp, self).__repr__(),
str(self))

def as_datetime(self):
try:
dt = datetime.datetime.utcfromtimestamp(self.v())
Expand Down
1 change: 1 addition & 0 deletions volatility/plugins/overlays/native_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
'unsigned short int' : obj.Curry(obj.NativeType, theType='unsigned short int', format_string='<H'),
'unsigned short' : obj.Curry(obj.NativeType, theType='unsigned short', format_string='<H'),
'unsigned be short' : obj.Curry(obj.NativeType, theType='unsigned be short', format_string='>H'),
'unsigned be int' : obj.Curry(obj.NativeType, theType='unsigned be int', format_string='>I'),
'short' : obj.Curry(obj.NativeType, theType='short', format_string='<h'),
'long long' : obj.Curry(obj.NativeType, theType='long long', format_string='<q'),
'unsigned long long' : obj.Curry(obj.NativeType, theType='unsigned long long', format_string='<Q'),
Expand Down
4 changes: 2 additions & 2 deletions volatility/plugins/overlays/windows/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ def _make_handle_array(self, offset, level, depth = 0):
# The size of a handle table entry.
handle_entry_size = self.obj_profile.get_obj_size("_HANDLE_TABLE_ENTRY")
# Finally, compute the handle value for this object.
handle_value = ((entry.obj_offset - offset) /
handle_value = ((entry.obj_offset - table[0].obj_offset) /
(handle_entry_size / handle_multiplier)) + handle_level_base

## OK We got to the bottom table, we just resolve
Expand Down Expand Up @@ -879,7 +879,7 @@ def traverse(self, visited = None, depth=0):
We try to be tolerant of cycles by storing all offsets visited.
"""
if depth > 100:
import pdb; pdb.set_trace()
raise RuntimeError("Vad tree too deep - something went wrong!")

if visited == None:
visited = set()
Expand Down
1 change: 1 addition & 0 deletions volatility/plugins/windows/gui/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from volatility.plugins.windows.gui import atoms
from volatility.plugins.windows.gui import clipboard
from volatility.plugins.windows.gui import windowstations
from volatility.plugins.windows.gui import sessions
137 changes: 77 additions & 60 deletions volatility/plugins/windows/gui/clipboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,133 +10,150 @@
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import logging

import volatility.obj as obj
import volatility.debug as debug
import volatility.utils as utils
import volatility.commands as commands
import volatility.plugins.gui.sessions as sessions
import volatility.plugins.gui.windowstations as windowstations
import volatility.plugins.gui.constants as consts
from volatility import obj
from volatility.plugins.windows import common
from volatility.plugins.windows.gui import sessions
from volatility.plugins.windows.gui import windowstations
from volatility.plugins.windows.gui import win32k_core
from volatility.plugins.windows.gui import constants

class Clipboard(commands.Command, sessions.SessionsMixin):


class Clipboard(common.WinProcessFilter):
"""Extract the contents of the windows clipboard"""

__name = "clipboard"

@classmethod
def args(cls, parser):
parser.add_argument("-v", "--verbose", default=False,
action="store_true",
help="Dump more information")

def __init__(self, verbose=False, **kwargs):
super(Clipboard, self).__init__(**kwargs)
self.verbose = verbose
self.profile = win32k_core.Win32GUIProfile(self.profile)

def calculate(self):
kernel_space = utils.load_as(self._config)
session_plugin = self.session.plugins.sessions()

# Dictionary of MM_SESSION_SPACEs by ID
sesses = dict((int(session.SessionId), session)
for session in self.session_spaces(kernel_space)
)
sessions = dict((int(session.SessionId), session)
for session in session_plugin.session_spaces())

# Dictionary of session USER objects by handle
session_handles = {}

# If various objects cannot be found or associated,
# If various objects cannot be found or associated,
# we'll return none objects
e0 = obj.NoneObject("Unknown tagCLIPDATA")
e1 = obj.NoneObject("Unknown tagWINDOWSTATION")
e2 = obj.NoneObject("Unknown tagCLIP")

# Handle type filter
# Handle type filter
filters = [lambda x : str(x.bType) == "TYPE_CLIPDATA"]

# Load tagCLIPDATA handles from all sessions
for sid, session in sesses.items():
# Load tagCLIPDATA handles from all sessions
import pdb; pdb.set_trace()
for sid, session in sessions.items():
handles = {}
shared_info = session.find_shared_info()
if not shared_info:
debug.debug("No shared info for session {0}".format(sid))
logging.debug("No shared info for session {0}".format(sid))

continue
for handle in shared_info.handles(filters):
handles[int(handle.phead.h)] = handle

session_handles[sid] = handles

# Each WindowStation
for wndsta in windowstations.WndScan(self._config).calculate():
session = sesses.get(int(wndsta.dwSessionId), None)
# The session is unknown
# Scan for Each WindowStation
windowstations_plugin = self.session.plugins.wndscan()

for wndsta, station_as in windowstations_plugin.generate_hits():
session = sessions.get(int(wndsta.dwSessionId), None)
# The session is unknown
if not session:
continue

handles = session_handles.get(int(session.SessionId), None)
# No handles in the session
# No handles in the session
if not handles:
continue
clip_array = wndsta.pClipBase.dereference()
# The tagCLIP array is empty or the pointer is invalid

clip_array = wndsta.pClipBase.dereference(vm=station_as)
# The tagCLIP array is empty or the pointer is invalid
if not clip_array:
continue
# Resolve tagCLIPDATA from tagCLIP.hData

# Resolve tagCLIPDATA from tagCLIP.hData
for clip in clip_array:
handle = handles.get(int(clip.hData), e0)
# Remove this handle from the list
# Remove this handle from the list
if handle:
handles.pop(int(clip.hData))

yield session, wndsta, clip, handle

# Any remaining tagCLIPDATA not matched. This allows us
# to still find clipboard data if a window station is not
# found or if pClipData or cNumClipFormats were corrupt
for sid in sesses.keys():
for sid in sessions.keys():
handles = session_handles.get(sid, None)
# No handles in the session
# No handles in the session
if not handles:
continue
for handle in handles.values():
yield sesses[sid], e1, e2, handle

def render_text(self, outfd, data):

self.table_header(outfd,
[("Session", "10"),
("WindowStation", "12"),
("Format", "18"),
("Handle", "[addr]"),
("Object", "[addrpad]"),
("Data", "50"),
])

for session, wndsta, clip, handle in data:

for handle in handles.values():
yield sessions[sid], e1, e2, handle

def render(self, renderer):
renderer.table_header([("Session", "session", "10"),
("WindowStation", "window_station", "12"),
("Format", "format", "18"),
("Handle", "handle", "[addr]"),
("Object", "object", "[addrpad]"),
("Data", "data", "50"),
])

for session, wndsta, clip, handle in self.calculate():
# If no tagCLIP is provided, we do not know the format
if not clip:
fmt = obj.NoneObject("Format unknown")
else:
# Try to get the format name, but failing that, print
# the format number in hex instead.
if clip.fmt.v() in consts.CLIPBOARD_FORMAT_ENUM:
# Try to get the format name, but failing that, print
# the format number in hex instead.
if clip.fmt.v() in constants.CLIPBOARD_FORMAT_ENUM:
fmt = str(clip.fmt)
else:
fmt = hex(clip.fmt.v())

# Try to get the handle from tagCLIP first, but
# fall back to using _HANDLEENTRY.phead. Note: this can
# be a value like DUMMY_TEXT_HANDLE (1) etc.
if clip:
handle_value = clip.hData
else:
handle_value = handle.phead.h
handle_value = clip.hData or handle.phead.h

clip_data = ""
if handle and "TEXT" in fmt:
clip_data = handle.reference_object().as_string(fmt)

self.table_row(outfd,
session.SessionId,
wndsta.Name,
fmt,
handle_value,
handle.phead.v(),
clip_data)
renderer.table_row(session.SessionId,
wndsta.Name,
fmt,
handle_value,
handle.phead.v(),
clip_data)

# Print an additional hexdump if --verbose is specified
if self._config.VERBOSE and handle:
if self.verbose and handle:
hex_dump = handle.reference_object().as_hex()
outfd.write("{0}".format(hex_dump))
Loading

0 comments on commit 3e35f66

Please sign in to comment.