Package rekall :: Package plugins :: Package windows :: Package gui :: Module atoms
[frames] | no frames]

Source Code for Module rekall.plugins.windows.gui.atoms

  1  # Rekall Memory Forensics 
  2  # Copyright (C) 2007,2008 Volatile Systems 
  3  # Copyright (C) 2010,2011,2012 Michael Hale Ligh <michael.ligh@mnin.org> 
  4  # Copyright 2013 Google Inc. All Rights Reserved. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or (at 
  9  # your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, but 
 12  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 14  # General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the Free Software 
 18  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 19  # 
 20  # pylint: disable=protected-access 
 21   
 22  from rekall import obj 
 23   
 24  from rekall.plugins.windows import common 
 25  from rekall.plugins.windows.gui import win32k_core 
 26   
 27   
28 -class PoolScanAtom(common.PoolScanner):
29 """Pool scanner for atom tables""" 30
31 - def __init__(self, **kwargs):
32 super(PoolScanAtom, self).__init__(**kwargs) 33 34 self.checks = [ 35 ('PoolTagCheck', dict(tag=self.profile.get_constant( 36 "PoolTag_Atom"))), 37 38 ('CheckPoolSize', dict( 39 min_size=self.profile.get_obj_size("_RTL_ATOM_TABLE"))), 40 41 ('CheckPoolType', dict(paged=True, non_paged=True, free=True)), 42 ]
43 44
45 -class AtomScan(win32k_core.Win32kPluginMixin, common.PoolScannerPlugin):
46 """Pool scanner for _RTL_ATOM_TABLE""" 47 48 __name = "atomscan" 49 50 __args = [ 51 dict(name="sort_by", choices=["atom", "refcount", "offset"], 52 default="offset", help="Sort by [offset | atom | refcount]") 53 ] 54 55 table_header = [ 56 dict(name="offset_p", style="address"), 57 dict(name="offset_v", style="address"), 58 dict(name="atom", style="address"), 59 dict(name="refs", width=6), 60 dict(name="pinned", width=6), 61 dict(name="name"), 62 ] 63 64 scanner_defaults = dict( 65 scan_physical=True 66 ) 67
68 - def collect(self):
69 for run in self.generate_memory_ranges(): 70 scanner = PoolScanAtom( 71 profile=self.win32k_profile, session=self.session, 72 address_space=run.address_space) 73 74 for pool_header in scanner.scan(run.start, run.length): 75 # Note: all OS after XP, there are an extra 8 bytes (for 32-bit) 76 # or 16 bytes (for 64-bit) between the _POOL_HEADER and 77 # _RTL_ATOM_TABLE. This is variable length structure, so we 78 # can't use the bottom-up approach as we do with other object 79 # scanners - because the size of an _RTL_ATOM_TABLE differs 80 # depending on the number of hash buckets. 81 82 version = self.profile.metadata('version') 83 fixup = 0 84 85 if self.profile.metadata('arch') == 'I386': 86 if version > 5.1: 87 fixup = 8 88 else: 89 if version > 5.1: 90 fixup = 16 91 92 atom_table = self.win32k_profile._RTL_ATOM_TABLE( 93 offset=pool_header.obj_end + fixup, 94 vm=pool_header.obj_vm) 95 96 # There's no way to tell which session or window station 97 # owns an atom table by *just* looking at the atom table, 98 # so we have to instantiate it from the default kernel AS. 99 if not atom_table.is_valid(): 100 continue 101 102 # This defeats the purpose of having a generator, but 103 # its required if we want to be able to sort. We also 104 # filter string atoms here. 105 atoms = [] 106 for atom in atom_table.atoms(vm=self.kernel_address_space): 107 if atom.is_string_atom(): 108 atoms.append(atom) 109 110 if self.plugin_args.sort_by == "atom": 111 attr = "Atom" 112 elif self.plugin_args.sort_by == "refcount": 113 attr = "ReferenceCount" 114 else: 115 attr = "obj_offset" 116 117 for atom in sorted(atoms, key=lambda x: getattr(x, attr)): 118 yield dict(offset_p=atom_table.obj_offset, 119 offset_v=atom.obj_offset, 120 atom=atom.Atom, 121 refs=atom.ReferenceCount, 122 pinned=atom.Pinned, 123 name=atom.Name)
124 125
126 -class Atoms(win32k_core.Win32kPluginMixin, 127 common.WindowsCommandPlugin):
128 """Print session and window station atom tables. 129 130 From: 131 http://msdn.microsoft.com/en-us/library/windows/desktop/ms649053.aspx 132 133 An atom table is a system-defined table that stores strings and 134 corresponding identifiers. An application places a string in an atom table 135 and receives a 16-bit integer, called an atom, that can be used to access 136 the string. A string that has been placed in an atom table is called an atom 137 name. 138 139 The global atom table is available to all applications. When an application 140 places a string in the global atom table, the system generates an atom that 141 is unique throughout the system. Any application that has the atom can 142 obtain the string it identifies by querying the global atom table. 143 144 (The global atom tables are only global within each session). 145 """ 146 147 __name = "atoms" 148 149 150 table_header = [ 151 dict(name="offset_p", style="address"), 152 dict(name="session", width=10), 153 dict(name="windows_station", width=18), 154 dict(name="atom", style="address"), 155 dict(name="ref_count", width=10), 156 dict(name="hindex", width=10), 157 dict(name="pinned", width=10), 158 dict(name="name"), 159 ] 160
161 - def station_atoms(self, station):
162 """Generate all the atoms in the windows station atom table.""" 163 table = station.pGlobalAtomTable 164 165 # In Windows 8 this pointer is not valid or points to something else 166 # since there are no more global atom tables. Ref: 167 # http://mista.nu/research/smashing_the_atom.pdf 168 if table.Signature != 0x6D6F7441: 169 return 170 171 for atom in sorted(table.atoms(), key=lambda x: x.Atom): 172 ## Filter string atoms 173 if not atom.is_string_atom(): 174 continue 175 176 yield table, atom
177
178 - def session_atoms(self, session):
179 """Generate all (Session) Global User Atoms.""" 180 # Now find all the atoms in the User handle table. 181 table = self.win32k_profile.get_constant_object( 182 "UserAtomTableHandle", 183 target="Pointer", 184 target_args=dict( 185 target="_RTL_ATOM_TABLE", 186 ), 187 vm=session.obj_vm, 188 ) 189 190 for atom in sorted(table.atoms(), key=lambda x: x.Atom): 191 ## Filter string atoms 192 if not atom.is_string_atom(): 193 continue 194 195 yield table, atom
196
197 - def find_atoms(self):
198 windows_stations = self.session.plugins.windows_stations() 199 # List the atom tables that belong to each window station. 200 for station in windows_stations.stations(): 201 for table, atom in self.station_atoms(station): 202 yield table, atom, station, station.dwSessionId 203 204 # List the global user atom tables. 205 for session in self.session.plugins.sessions().session_spaces(): 206 for table, atom in self.session_atoms(session): 207 yield table, atom, obj.NoneObject(), session.SessionId
208
209 - def collect(self):
210 for table, atom, window_station, session_id in self.find_atoms(): 211 yield dict(offset_p=table, 212 session=session_id, 213 windows_station=window_station.Name, 214 atom=atom.Atom, 215 ref_count=atom.ReferenceCount, 216 hindex=atom.HandleIndex, 217 pinned=atom.Pinned, 218 name=atom.Name)
219