1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 """
22 @author: Michael Cohen <scudette@gmail.com>
23 @author: AAron Walters and Brendan Dolan-Gavitt
24 @license: GNU General Public License 2.0 or later
25 @contact: awalters@volatilesystems.com,bdolangavitt@wesleyan.edu
26 @organization: Volatile Systems
27 """
28 import re
29
30 from rekall import addrspace
31 from rekall.plugins import core
32 from rekall.plugins.windows.registry import registry
33 from rekall.plugins.overlays import basic
34 from rekall_lib import utils
35
36
37 -class PrintKey(registry.RegistryPlugin):
38 """Print a registry key, and its subkeys and values"""
39 __name = "printkey"
40
41 @classmethod
42 - def args(cls, parser):
43 """Declare the command line args we need."""
44 super(PrintKey, cls).args(parser)
45
46 parser.add_argument("-k", "--key", default="",
47 help="Registry key to print.")
48
49 parser.add_argument("-r", "--recursive", default=False,
50 type="Boolean",
51 help='If set print the entire subtree.')
52
53
54 - def __init__(self, key="", recursive=False, **kwargs):
55 """Print all keys and values contained by a registry key.
56
57 Args:
58 key: The key name to list. If not provided we list the root key in the
59 hive.
60
61 recursive: If set print the entire subtree.
62 """
63 super(PrintKey, self).__init__(**kwargs)
64 self.key = key
65 self.recursive = recursive
66
68 yield key
69
70 if self.recursive:
71 for subkey in key.subkeys():
72 for subkey in self._list_keys(subkey):
73 yield subkey
74
76 """Return the keys that match."""
77 seen = set()
78 for hive_offset in self.hive_offsets:
79 reg = registry.RegistryHive(
80 profile=self.profile, session=self.session,
81 kernel_address_space=self.kernel_address_space,
82 hive_offset=hive_offset)
83
84 key = reg.open_key(self.key)
85 for subkey in self._list_keys(key):
86 if subkey in seen:
87 break
88
89 seen.add(subkey)
90
91 yield reg, subkey
92
93 - def voltext(self, key):
94 """Returns a string representing (S)table or (V)olatile keys."""
95 return "(V)" if key.obj_offset & 0x80000000 else "(S)"
96
98 renderer.format("Legend: (S) = Stable (V) = Volatile\n\n")
99 for reg, key in self.list_keys():
100 self.session.report_progress(
101 "Printing %s", lambda key=key: key.Path)
102
103 if key:
104 renderer.format("----------------------------\n")
105 renderer.format("Registry: {0}\n", reg.Name)
106 renderer.format("Key name: {0} {1} @ {2:addrpad}\n", key.Name,
107 self.voltext(key), key.obj_vm.vtop(int(key)))
108
109 renderer.format("Last updated: {0}\n", key.LastWriteTime)
110 renderer.format("\n")
111 renderer.format("Subkeys:\n")
112
113 for subkey in key.subkeys():
114 if not subkey.Name:
115 renderer.format(
116 " Unknown subkey: {0}\n", subkey.Name.reason)
117 else:
118 renderer.format(u" {1} {0}\n",
119 subkey.Name, self.voltext(subkey))
120
121 renderer.format("\n")
122 renderer.format("Values:\n")
123 for value in key.values():
124 renderer.format("{0:addrpad} ", value.obj_vm.vtop(value))
125 if value.Type == 'REG_BINARY':
126 data = value.DecodedData
127 if isinstance(data, basestring):
128 renderer.format(
129 u"{0:width=13} {1:width=15} : {2}\n",
130 value.Type, value.Name, self.voltext(value))
131 utils.WriteHexdump(renderer, value.DecodedData)
132 else:
133 renderer.format(
134 u"{0:width=13} {1:width=15} : {2} {3}\n",
135 value.Type, value.Name, self.voltext(value),
136 utils.SmartUnicode(value.DecodedData).strip())
137
138
139 -class RegDump(core.DirectoryDumperMixin, registry.RegistryPlugin):
140 """Dump all registry hives from memory into a dump directory."""
141
142 __name = 'regdump'
143
144 - def dump_hive(self, hive_offset=None, reg=None, fd=None):
145 """Write the hive into the fd.
146
147 Args:
148 hive_offset: The virtual offset where the hive is located.
149 reg: Optionally an instance of registry.Registry helper. If provided
150 hive_offset is ignored.
151 fd: The file like object we write to.
152 """
153 if reg is None:
154 reg = registry.RegistryHive(
155 profile=self.profile,
156 kernel_address_space=self.kernel_address_space,
157 hive_offset=hive_offset)
158
159 count = 0
160 for data in reg.address_space.save():
161 fd.write(data)
162 count += len(data)
163 self.session.report_progress(
164 "Dumping {0}Mb".format(count/1024/1024))
165
167
168 for hive_offset in self.hive_offsets:
169 reg = registry.RegistryHive(
170 profile=self.profile, session=self.session,
171 kernel_address_space=self.kernel_address_space,
172 hive_offset=hive_offset)
173
174
175 filename = reg.Name.rsplit("\\", 1).pop()
176
177
178 filename = re.sub(r"[^a-zA-Z0-9_\-@ ]", "_", filename)
179
180
181 renderer.section()
182 renderer.format("Dumping {0} into \"{1}\"\n", reg.Name, filename)
183
184 with renderer.open(directory=self.dump_dir,
185 filename=filename,
186 mode="wb") as fd:
187 self.dump_hive(reg=reg, fd=fd)
188 renderer.format("Dumped {0} bytes\n", fd.tell())
189
190
191
192 -class HiveDump(registry.RegistryPlugin):
193 """Prints out a hive"""
194
195 __name = "hivedump"
196
198 yield key
199
200 if key in seen:
201 return
202
203 seen.add(key)
204
205 for subkey in key.subkeys():
206 for subsubkey in self._key_iterator(subkey, seen):
207 yield subsubkey
208
210 seen = set()
211
212 for hive_offset in self.hive_offsets:
213 reg = registry.RegistryHive(
214 hive_offset=hive_offset, session=self.session,
215 kernel_address_space=self.kernel_address_space,
216 profile=self.profile)
217
218 renderer.section()
219 renderer.format("Hive {0}\n\n", reg.Name)
220
221 renderer.table_header([("Last Written", "timestamp", "<24"),
222 ("Key", "key", "")])
223
224 for key in self._key_iterator(reg.root, seen):
225 renderer.table_row(key.LastWriteTime, key.Path)
226
227
228
229 sam_vtypes = {
230 "UNICODE_STRING": [12, {
231 "offset": [0, ["unsigned int"]],
232 "len": [4, ["unsigned int"]],
233 "Value": lambda x: x.obj_profile.UnicodeString(
234 offset=x.offset+0xCC,
235 length=x.len, vm=x.obj_vm),
236
237 }],
238
239 "Hash": [12, {
240 "offset": [0, ["unsigned int"]],
241 "len": [4, ["unsigned int"]],
242 "Value": lambda x: x.obj_vm.read(
243 x.offset+0xCC, x.len).encode("hex"),
244
245 }],
246
247 "V": [None, {
248 "Type": [4, ["Enumeration", dict(
249 choices={
250 0xBC: "Default Admin User",
251 0xd4: "Custom Limited Acct",
252 0xb0: "Default Guest Acct"
253 },
254 target="unsigned int"
255 )]],
256 "UserName": [12, ['UNICODE_STRING']],
257 "FullName": [24, ['UNICODE_STRING']],
258 "Comment": [36, ['UNICODE_STRING']],
259 "LanHash": [156, ['Hash']],
260 "NTHash": [168, ['Hash']],
261 }],
262
263 "F": [None, {
264 "LastLoginTime": [8, ['WinFileTime']],
265 "PwdResetDate": [24, ["WinFileTime"]],
266 "AccountExpiration": [32, ["WinFileTime"]],
267 "PasswordFailedTime": [40, ["WinFileTime"]],
268 "LoginCount": [66, ["unsigned short int"]],
269 "FailedLoginCount": [64, ["unsigned short int"]],
270 "Rid": [48, ["unsigned int"]],
271 "Flags": [56, ["Flags", dict(
272 maskmap=utils.Invert({
273 0x0001: "Account Disabled",
274 0x0002: "Home directory required",
275 0x0004: "Password not required",
276 0x0008: "Temporary duplicate account",
277 0x0010: "Normal user account",
278 0x0020: "MNS logon user account",
279 0x0040: "Interdomain trust account",
280 0x0080: "Workstation trust account",
281 0x0100: "Server trust account",
282 0x0200: "Password does not expire",
283 0x0400: "Account auto locked"
284 }),
285 target="unsigned short int"
286 )]],
287 }],
288 }
289
290
291
292 -class SAMProfile(basic.Profile32Bits, basic.BasicClasses):
293 """A profile to parse the SAM."""
294
295 @classmethod
300
301
302 -class Users(registry.RegistryPlugin):
303 """Enumerate all users of this system.
304
305 Ref:
306 samparse.pl from RegRipper.
307
308 # copyright 2012 Quantum Analytics Research, LLC
309 # Author: H. Carvey, keydet89@yahoo.com
310 """
311 name = "users"
312
338
340 for user_rid, v, f in self.GenerateUsers():
341 renderer.section()
342 renderer.format("Key {0} \n\n", user_rid.Path)
343 renderer.table_header(
344 columns=[("", "property", "20"),
345 ("", "value", "")],
346 suppress_headers=True)
347
348 for field in v.members:
349 try:
350 renderer.table_row(field, getattr(v, field).Value)
351 except AttributeError:
352 renderer.table_row(field, getattr(v, field))
353
354 for field in f.members:
355 renderer.table_row(field, getattr(f, field))
356
357
358 -class Services(registry.RegistryPlugin):
359 """Enumerate all services."""
360 name = "services"
361
362
363
364 SERVICE_TYPE = {
365 0x00000004: 'SERVICE_ADAPTER',
366 0x00000002: 'SERVICE_FILE_SYSTEM_DRIVER',
367 0x00000001: 'SERVICE_KERNEL_DRIVER',
368 0x00000008: 'SERVICE_RECOGNIZER_DRIVER',
369 0x00000010: 'SERVICE_WIN32_OWN_PROCESS',
370 0x00000020: 'SERVICE_WIN32_SHARE_PROCESS'
371 }
372
373 START_TYPE = {
374 0x00000002: 'SERVICE_AUTO_START',
375 0x00000000: 'SERVICE_BOOT_START',
376 0x00000003: 'SERVICE_DEMAND_START',
377 0x00000004: 'SERVICE_DISABLED',
378 0x00000001: 'SERVICE_SYSTEM_START'
379 }
380
381 ERROR_CONTROL = {
382 0x00000003: 'SERVICE_ERROR_CRITICAL',
383 0x00000000: 'SERVICE_ERROR_IGNORE',
384 0x00000001: 'SERVICE_ERROR_NORMAL',
385 0x00000002: 'SERVICE_ERROR_SEVERE'
386 }
387
398
400 for service in self.GenerateServices():
401 renderer.section(service.Name.v())
402 renderer.table_header([("Key", "key", "20"),
403 ("Value", "value", "[wrap:60]")],
404 suppress_headers=True)
405
406 for value in service.values():
407 k = value.Name.v()
408 v = value.DecodedData
409 if value.Type == "REG_BINARY":
410 continue
411
412 if isinstance(v, list):
413 v = ",".join([x for x in v if x])
414
415 if k == "Type":
416 v = self.SERVICE_TYPE.get(v, v)
417
418 if k == "Start":
419 v = self.START_TYPE.get(v, v)
420
421 if k == "ErrorControl":
422 v = self.ERROR_CONTROL.get(v, v)
423
424 renderer.table_row(k, v)
425