| Trees | Indices | Help |
|
|---|
|
|
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 }
143 """A Pretty printing implementation of sids.
144
145 Reference:
146 http://www.sekchek.com/downloads/white-papers/windows-about-sids.pdf
147 """
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
170
173 checks = [('StringCheck', dict(needle="LfLe"))]
174
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
190 """Extract Windows Event Logs (XP/2003 only)"""
191
192 name = "evtlogs"
193 mode = "mode_xp"
194
196 super(EvtLogs, self).__init__(**kwargs)
197 self.profile = EVTObjectTypes(self.profile)
198 self.context = dict(sid_cache={})
199
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
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
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
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
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Oct 9 03:29:44 2017 | http://epydoc.sourceforge.net |