Package rekall :: Package plugins :: Package windows :: Package registry :: Module evtlogs
[frames] | no frames]

Source Code for Module rekall.plugins.windows.registry.evtlogs

  1  # Rekall Memory Forensics 
  2  # Copyright (C) 2008-2011 Volatile Systems 
  3  # Copyright (C) 2011 Jamie Levy (Gleeda) <jamie.levy@gmail.com> 
  4  # Copyright 2013 Google Inc. All Rights Reserved. 
  5  # 
  6  # Additional Authors: 
  7  # Michael Cohen <scudette@gmail.com> 
  8  # 
  9  # This program is free software; you can redistribute it and/or modify 
 10  # it under the terms of the GNU General Public License as published by 
 11  # the Free Software Foundation; either version 2 of the License, or (at 
 12  # your option) any later version. 
 13  # 
 14  # This program is distributed in the hope that it will be useful, but 
 15  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 17  # General Public License for more details. 
 18  # 
 19  # You should have received a copy of the GNU General Public License 
 20  # along with this program; if not, write to the Free Software 
 21  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 22  # 
 23   
 24  """ 
 25  @author:       Jamie Levy (gleeda) 
 26  @license:      GNU General Public License 2.0 or later 
 27  @contact:      jamie.levy@gmail.com 
 28  @organization: Volatile Systems 
 29  """ 
 30  import ntpath 
 31   
 32  from rekall import obj 
 33  from rekall import scan 
 34  from rekall.plugins.windows.registry import registry 
 35  from rekall.plugins.windows.registry import getsids 
 36  from rekall_lib import utils 
 37   
 38  # for more information on Event Log structures see WFA 2E pg 260-263 by Harlan 
 39  # Carvey 
 40  evt_log_types = { 
 41      'EVTLogHeader' : [0x30, { 
 42          'HeaderSize' : [0x0, ['unsigned int']], 
 43          'Magic' : [0x4, ['String', dict(length=4)]],  # LfLe 
 44   
 45          # Offset of oldest record. 
 46          'OffsetOldest' : [0x10, ['int']], 
 47   
 48          # Offset of next record to be written. 
 49          'OffsetNextToWrite' : [0x14, ['int']], 
 50          'NextID' : [0x18, ['int']],  # Next event record ID. 
 51          'OldestID' : [0x1c, ['int']], # Oldest event record ID. 
 52   
 53          # Maximum size of event record (from registry). 
 54          'MaxSize' : [0x20, ['int']], 
 55   
 56          # Retention time of records (from registry). 
 57          'RetentionTime' : [0x28, ['int']], 
 58   
 59          # Size of the record (repeat of DWORD at offset 0). 
 60          'RecordSize' : [0x2c, ['int']], 
 61          }], 
 62   
 63      'EVTRecordStruct' : [0x38, { 
 64          'RecordLength' : [0x0, ['int']], 
 65          'Magic' : [0x4, ['String', dict(length=4)]],  # LfLe 
 66          'RecordNumber' : [0x8, ['int']], 
 67   
 68          'TimeGenerated' : [0xc, ['UnixTimeStamp']], 
 69          'TimeWritten' : [0x10, ['UnixTimeStamp']], 
 70   
 71          # Specific to event source and uniquely identifies the event. 
 72          'EventID' : [0x14, ['unsigned short']], 
 73          'EventType' : [0x18, ['Enumeration', dict( 
 74              target='unsigned short', 
 75              choices={0x01: "Error", 
 76                       0x02: "Warning", 
 77                       0x04: "Info", 
 78                       0x08: "Success", 
 79                       0x10: "Failure"})]], 
 80   
 81          # Number of description strings in event message. 
 82          'NumStrings' : [0x1a, ['unsigned short']], 
 83          'EventCategory' : [0x1c, ['unsigned short']], 
 84          'ReservedFlags' : [0x1e, ['unsigned short']], 
 85          'ClosingRecordNum' : [0x20, ['int']], 
 86   
 87          # Offset w/in record of description strings. 
 88          'StringOffset' : [0x24, ['int']], 
 89   
 90          # Length of SID: if 0 no SID is present. 
 91          'SidLength' : [0x28, ['int']], 
 92   
 93          # Offset w/in record to start of SID (if present). 
 94          'SidOffset' : [0x2c, ['int']], 
 95   
 96          # Length of binary data of record. 
 97          'DataLength' : [0x30, ['int']], 
 98   
 99          # Offset of data w/in record. 
100          'DataOffset' : [0x34, ['int']], 
101   
102          'Source': [0x38, ['UnicodeString', dict( 
103              length=lambda x: x.RecordLength)]], 
104   
105          # The computer name is right after the Source. 
106          'Computer': [lambda x: x.Source.obj_offset + x.Source.obj_size, 
107                       ['UnicodeString', dict( 
108                           length=lambda x: x.RecordLength)]], 
109   
110          'Sid': [lambda x: x.obj_offset + x.SidOffset.v(), ['_SID']], 
111   
112          'Data':[lambda x: x.obj_offset + x.StringOffset.v(), [ 
113              "ListArray", dict( 
114                  target="UnicodeString", 
115                  target_args=dict(encoding="utf16"), 
116                  maximum_size=lambda x: x.RecordLength, 
117                  count=lambda x: x.NumStrings)]], 
118          }], 
119   
120      "_SID": [None, { 
121          "IdentifierAuthority": [None, ["Enumeration", dict( 
122              choices={ 
123                  "\x00\x00\x00\x00\x00\x00": "Null Authority", 
124                  "\x00\x00\x00\x00\x00\x01": "World Authority", 
125                  "\x00\x00\x00\x00\x00\x02": "Local Authority", 
126                  "\x00\x00\x00\x00\x00\x03": "Creator Authority", 
127                  "\x00\x00\x00\x00\x00\x04": "NonUnique Authority", 
128                  "\x00\x00\x00\x00\x00\x05": "NT Authority", 
129                  }, 
130              target="String", 
131              target_args=dict(length=6, term=None) 
132              )]], 
133          "NumericIdentifier": [0x4, ["unsigned be int"]], 
134          "SubAuthority": [None, ["Array", dict( 
135              target="unsigned long", 
136              count=lambda x: x.SubAuthorityCount)]], 
137          }], 
138      } 
139 140 141 142 -class _SID(obj.Struct):
143 """A Pretty printing implementation of sids. 144 145 Reference: 146 http://www.sekchek.com/downloads/white-papers/windows-about-sids.pdf 147 """
148 - def __unicode__(self):
149 """Format the Sid using SDDL Notation.""" 150 components = [self.Revision, self.NumericIdentifier] 151 components.extend(self.SubAuthority) 152 153 result = u"S-" + u"-".join([str(x) for x in components]) 154 155 # Try to resolve a friendly name from the cache in the context. 156 friendly_name = self.obj_context.get("sid_cache", {}).get(result) 157 if friendly_name: 158 result = u"%s (%s)" % (result, friendly_name) 159 160 return result
161
162 163 -class EVTObjectTypes(obj.ProfileModification):
164 """An implementation for parsing event logs.""" 165 166 @classmethod
167 - def modify(cls, profile):
170
171 172 -class EVTScanner(scan.BaseScanner):
173 checks = [('StringCheck', dict(needle="LfLe"))] 174
175 - def scan(self, offset, maxlen=None, context=None):
176 for hit in super(EVTScanner, self).scan(offset, maxlen=maxlen): 177 event_offset = hit - self.profile.get_obj_offset( 178 "EVTRecordStruct", "Magic") 179 180 event = self.profile.EVTRecordStruct( 181 offset=event_offset, vm=self.address_space, context=context) 182 183 # Eliminate crazy events (between 2001 and 2017): 184 if (1500000000 > event.TimeGenerated > 1000000000 and 185 1500000000 > event.TimeWritten > 1000000000): 186 yield event
187
188 189 -class EvtLogs(registry.RegistryPlugin):
190 """Extract Windows Event Logs (XP/2003 only)""" 191 192 name = "evtlogs" 193 mode = "mode_xp" 194
195 - def __init__(self, **kwargs):
196 super(EvtLogs, self).__init__(**kwargs) 197 self.profile = EVTObjectTypes(self.profile) 198 self.context = dict(sid_cache={})
199
200 - def FindEVTFiles(self):
201 """Search for event log files in memory. 202 203 We search for processes called 'services.exe' with a vad to and open 204 file ending with '.evt'. 205 """ 206 ps_plugin = self.get_plugin("pslist", proc_regex="services.exe") 207 208 for task in ps_plugin.filter_processes(): 209 for vad in task.RealVadRoot.traverse(): 210 try: 211 filename = vad.ControlArea.FilePointer.FileName 212 if utils.SmartUnicode(filename).lower().endswith(".evt"): 213 yield task, vad 214 except AttributeError: 215 pass
216
217 - def ScanEvents(self, vad, address_space):
218 scanner = EVTScanner(profile=self.profile, address_space=address_space, 219 session=self.session) 220 for event in scanner.scan(offset=vad.Start, maxlen=vad.Length, 221 context=self.context): 222 yield event
223
224 - def PrecacheSids(self):
225 """Search for known sids that we can cache.""" 226 sid_cache = self.context["sid_cache"] 227 sid_cache.update(getsids.well_known_sids) 228 229 # Search for all known user sids. 230 for hive_offset in self.hive_offsets: 231 hive_address_space = registry.HiveAddressSpace( 232 base=self.kernel_address_space, 233 hive_addr=hive_offset, profile=self.profile) 234 235 reg = registry.Registry( 236 profile=self.profile, address_space=hive_address_space) 237 238 # We get the user names according to the name of the diretory where 239 # their profile is. This is not very accurate - should we check the 240 # SAM instead? 241 profiles = reg.open_key( 242 'Microsoft\\Windows NT\\CurrentVersion\\ProfileList') 243 244 for profile in profiles.subkeys(): 245 path = profile.open_value("ProfileImagePath").DecodedData 246 if path: 247 sid_cache[utils.SmartUnicode(profile.Name)] = ( 248 utils.SmartUnicode(ntpath.basename(path))) 249 250 # Search for all service sids. 251 getservicesids = self.get_plugin("getservicesids") 252 for sid, service_name in getservicesids.get_service_sids(): 253 sid_cache[sid] = "(Service: %s)" % service_name
254
255 - def render(self, renderer):
256 if self.plugin_args.verbosity > 5: 257 self.PrecacheSids() 258 259 renderer.table_header([("TimeWritten", "timestamp", ""), 260 ("Filename", "filename", ""), 261 ("Computer", "computer", ""), 262 ("Sid", "sid", ""), 263 ("Source", "source", ""), 264 ("Event Id", "event_id", ""), 265 ("Event Type", "event_type", ""), 266 ("Message", "message", "")]) 267 268 for task, vad in self.FindEVTFiles(): 269 filename = ntpath.basename( 270 utils.SmartUnicode(vad.ControlArea.FilePointer.FileName)) 271 272 for event in self.ScanEvents(vad, task.get_process_address_space()): 273 args = ";".join( 274 repr(utils.SmartStr(x)) for x in event.Data) 275 276 renderer.table_row( 277 event.TimeWritten, 278 filename, 279 event.Computer, 280 event.Sid, 281 event.Source, 282 event.EventID, 283 event.EventType, 284 args)
285