1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 """ A Hiber file Address Space """
28 from rekall import addrspace
29 from rekall import obj
30 from rekall import utils
31 from rekall.plugins.addrspaces import xpress
32 import struct
33
34
35
36
37 PAGE_SIZE = 0x1000
38 page_shift = 12
42 """Support hibernation file structures for different versions of windows."""
43
44 vtypes = {
45 '_PO_MEMORY_RANGE_ARRAY_LINK' : [ 0x10, {
46 'NextTable' : [ 0x4, ['unsigned long']],
47 'EntryCount' : [ 0xc, ['unsigned long']],
48 } ],
49 '_PO_MEMORY_RANGE_ARRAY_RANGE' : [ 0x10, {
50 'StartPage' : [ 0x4, ['unsigned long']],
51 'EndPage' : [ 0x8, ['unsigned long']],
52 } ],
53 '_PO_MEMORY_RANGE_ARRAY' : [ 0x20, {
54 'MemArrayLink' : [ 0x0, ['_PO_MEMORY_RANGE_ARRAY_LINK']],
55 'RangeTable': [ 0x10, ['array', lambda x: x.MemArrayLink.EntryCount,
56 ['_PO_MEMORY_RANGE_ARRAY_RANGE']]],
57 } ],
58
59 '_IMAGE_XPRESS_HEADER' : [ 0x20 , {
60 'u09' : [ 0x9, ['unsigned char']],
61 'u0A' : [ 0xA, ['unsigned char']],
62 'u0B' : [ 0xB, ['unsigned char']],
63 } ]
64 }
65
66 vistasp01_vtypes = {
67 '_PO_MEMORY_RANGE_ARRAY' : [ 0x20, {
68 'RangeTable': [ 0x10, ['array', lambda x: x.Link.EntryCount,
69 ['_PO_MEMORY_RANGE_ARRAY_RANGE']]],
70 } ],
71 }
72
73 vistasp2_vtypes = {
74 '_PO_MEMORY_RANGE_ARRAY_LINK' : [ 0x10, {
75 'NextTable' : [ 0x4, ['unsigned long']],
76 'EntryCount' : [ 0x8, ['unsigned long']],
77 } ],
78 '_PO_MEMORY_RANGE_ARRAY_RANGE' : [ 0x8, {
79 'StartPage' : [ 0x0, ['unsigned long']],
80 'EndPage' : [ 0x4, ['unsigned long']],
81 } ],
82 '_PO_MEMORY_RANGE_ARRAY' : [ 0x20, {
83 'MemArrayLink' : [ 0x0, ['_PO_MEMORY_RANGE_ARRAY_LINK']],
84 'RangeTable': [ 0xc, ['array', lambda x: x.MemArrayLink.EntryCount,
85 ['_PO_MEMORY_RANGE_ARRAY_RANGE']]],
86 } ],
87 }
88
89 win7_vtypes = {
90 '_PO_MEMORY_RANGE_ARRAY_LINK' : [ 0x10, {
91 'NextTable' : [ 0x0, ['unsigned long']],
92 'EntryCount' : [ 0x4, ['unsigned long']],
93 } ],
94 '_PO_MEMORY_RANGE_ARRAY_RANGE' : [ 0x8, {
95 'StartPage' : [ 0x0, ['unsigned long']],
96 'EndPage' : [ 0x4, ['unsigned long']],
97 } ],
98 '_PO_MEMORY_RANGE_ARRAY' : [ 0x20, {
99 'MemArrayLink' : [ 0x0, ['_PO_MEMORY_RANGE_ARRAY_LINK']],
100 'RangeTable': [ 0x8, ['array', lambda x: x.MemArrayLink.EntryCount,
101 ['_PO_MEMORY_RANGE_ARRAY_RANGE']]],
102 } ],
103 }
104
105 win7_x64_vtypes = {
106 '_PO_MEMORY_RANGE_ARRAY_LINK' : [ 0x10, {
107 'NextTable' : [ 0x0, ['unsigned long long']],
108 'EntryCount' : [ 0x8, ['unsigned long']],
109 } ],
110 '_PO_MEMORY_RANGE_ARRAY_RANGE' : [ 0x10, {
111 'StartPage' : [ 0x0, ['unsigned long long']],
112 'EndPage' : [ 0x8, ['unsigned long long']],
113 } ],
114 '_PO_MEMORY_RANGE_ARRAY' : [ 0x20, {
115 'MemArrayLink' : [ 0x0, ['_PO_MEMORY_RANGE_ARRAY_LINK']],
116 'RangeTable': [ 0x10, ['array', lambda x: x.MemArrayLink.EntryCount,
117 ['_PO_MEMORY_RANGE_ARRAY_RANGE']]],
118 } ],
119 }
120
121 x64_vtypes = {
122 '_PO_MEMORY_RANGE_ARRAY_LINK' : [ 0x20, {
123 'NextTable' : [ 0x8, ['unsigned long long']],
124 'EntryCount' : [ 0x14, ['unsigned long']],
125 } ],
126 '_PO_MEMORY_RANGE_ARRAY_RANGE' : [ 0x20, {
127 'StartPage' : [ 0x8, ['unsigned long long']],
128 'EndPage' : [ 0x10, ['unsigned long long']],
129 } ],
130 '_PO_MEMORY_RANGE_ARRAY' : [ 0x40, {
131 'MemArrayLink' : [ 0x0, ['_PO_MEMORY_RANGE_ARRAY_LINK']],
132 'RangeTable': [ 0x20, ['array', lambda x: x.MemArrayLink.EntryCount,
133 ['_PO_MEMORY_RANGE_ARRAY_RANGE']]],
134 } ],
135 }
136
137 vistaSP2_x64_vtypes = {
138 '_PO_MEMORY_RANGE_ARRAY_LINK' : [ 0x18, {
139 'NextTable' : [ 0x8, ['unsigned long long']],
140 'EntryCount' : [ 0x10, ['unsigned long']],
141 } ],
142 '_PO_MEMORY_RANGE_ARRAY_RANGE' : [ 0x10, {
143 'StartPage' : [ 0x0, ['unsigned long long']],
144 'EndPage' : [ 0x8, ['unsigned long long']],
145 } ],
146 '_PO_MEMORY_RANGE_ARRAY' : [ 0x28, {
147 'MemArrayLink' : [ 0x0, ['_PO_MEMORY_RANGE_ARRAY_LINK']],
148 'RangeTable': [ 0x18, ['array', lambda x: x.MemArrayLink.EntryCount,
149 ['_PO_MEMORY_RANGE_ARRAY_RANGE']]],
150 } ],
151 }
152
153 @classmethod
155 profile.add_overlay(cls.vtypes)
156 profile.add_constants(HibrProcPage=0x2, HibrEntryCount=0xff)
157
158 major = profile.metadata("major")
159 minor = profile.metadata("minor")
160 build = profile.metadata("build")
161 architecture = profile.metadata("arch")
162
163 if architecture == "I386":
164 if major == 6 and minor == 0:
165 if build < 6000:
166 profile.add_overlay(cls.vistasp01_vtypes)
167
168 elif build == 6000:
169 profile.add_overlay(cls.vistasp01_vtypes)
170 profile.add_constants(HibrProcPage=0x4, HibrEntryCount=0xff)
171
172 elif build == 6001:
173 profile.add_overlay(cls.vistasp01_vtypes)
174 profile.add_constants(HibrProcPage=0x1, HibrEntryCount=0xff)
175
176 elif build == 6002:
177 profile.add_constants(HibrProcPage=0x1, HibrEntryCount=0x1fe)
178 profile.add_overlay(cls.vistasp2_vtypes)
179
180 elif major == 6 and minor == 1:
181 profile.add_constants(HibrProcPage=0x1, HibrEntryCount=0x1ff)
182
183 if build <= 7601:
184 profile.add_overlay(cls.win7_vtypes)
185
186 elif architecture == "AMD64":
187
188 if major == 5 and minor == 2 and build <= 3790:
189 profile.add_constants(HibrProcPage=0x2, HibrEntryCount=0x7f)
190 profile.add_overlay(cls.x64_vtypes)
191
192 elif major == 6 and minor == 0:
193 if build <= 6000:
194 profile.add_constants(HibrProcPage=0x4, HibrEntryCount=0x7f)
195 profile.add_overlay(cls.x64_vtypes)
196
197 elif build == 6001:
198 profile.add_constants(HibrProcPage=0x1, HibrEntryCount=0x7f)
199 profile.add_overlay(cls.x64_vtypes)
200
201 elif build == 6002:
202 profile.add_constants(HibrProcPage=0x1, HibrEntryCount=0xfe)
203 profile.add_overlay(cls.vistaSP2_x64_vtypes)
204
205 elif major == 6 and minor == 1:
206 profile.add_constants(HibrProcPage=0x1, HibrEntryCount=0xff)
207
208 if build <= 7601:
209 profile.add_overlay(cls.win7_x64_vtypes)
210
213 """ This is a hibernate address space for windows hibernation files.
214
215 In order for us to work we need to:
216 1) have a valid baseAddressSpace
217 2) the first 4 bytes must be 'hibr'
218 """
219
220 __name = "hiber"
221 __image = True
222
223 order = 100
224
226 self.as_assert(self.base == None, "No base Address Space")
227 self.as_assert(self.base.read(0, 4).lower() in ["hibr", "wake"])
228 self.runs = []
229 self.PageDict = {}
230 self.HighestPage = 0
231 self.PageIndex = 0
232 self.AddressList = []
233 self.LookupCache = {}
234 self.PageCache = utils.FastStore(500)
235 self.MemRangeCnt = 0
236 self.offset = 0
237 self.entry_count = 0xFF
238
239
240 self.profile = HibernationSupport(self.profile)
241
242
243 self.as_assert(self.profile.has_type("PO_MEMORY_IMAGE"),
244 "PO_MEMORY_IMAGE is not available in profile")
245
246 self.header = self.profile.Object('PO_MEMORY_IMAGE', offset=0, vm=self.base)
247 self.entry_count = self.profile.get_constant("HibrEntryCount")
248
249 proc_page = self.profile.get_constant("HibrProcPage")
250
251
252 self.as_assert(self._get_first_table_page() is not None,
253 "No xpress signature found")
254
255
256 self.ProcState = self.profile.Object(
257 "_KPROCESSOR_STATE", offset=proc_page * 4096, vm=base)
258
259
260
261 self.dtb = self.ProcState.SpecialRegisters.Cr3.v()
262
263
264
265 self.build_page_cache()
266 super(WindowsHiberFileSpace, self).__init__(**kwargs)
267
269 if self.header:
270 return self.header.FirstTablePage
271
272 for i in range(10):
273 if self.base.read(i * PAGE_SIZE, 8) == "\x81\x81xpress":
274 return i - 1
275
277 XpressIndex = 0
278
279 XpressHeader = self.profile.Object("_IMAGE_XPRESS_HEADER",
280 offset=(self._get_first_table_page() + 1) * 4096,
281 vm=self.base)
282
283 XpressBlockSize = self.get_xpress_block_size(XpressHeader)
284
285 MemoryArrayOffset = self._get_first_table_page() * 4096
286
287 while MemoryArrayOffset:
288 MemoryArray = self.profile.Object(
289 '_PO_MEMORY_RANGE_ARRAY', MemoryArrayOffset, self.base)
290
291 EntryCount = MemoryArray.MemArrayLink.EntryCount.v()
292 for i in MemoryArray.RangeTable:
293 start = i.StartPage.v()
294 end = i.EndPage.v()
295 LocalPageCnt = end - start
296
297 if end > self.HighestPage:
298 self.HighestPage = end
299
300 self.AddressList.append((start * 0x1000,
301 start * 0x1000,
302 LocalPageCnt * 0x1000))
303
304 for j in range(0, LocalPageCnt):
305 if (XpressIndex and ((XpressIndex % 0x10) == 0)):
306 XpressHeader, XpressBlockSize = \
307 self.next_xpress(XpressHeader, XpressBlockSize)
308
309 PageNumber = start + j
310 XpressPage = XpressIndex % 0x10
311 if XpressHeader.obj_offset not in self.PageDict:
312 self.PageDict[XpressHeader.obj_offset] = [
313 (PageNumber, XpressBlockSize, XpressPage)]
314 else:
315 self.PageDict[XpressHeader.obj_offset].append(
316 (PageNumber, XpressBlockSize, XpressPage))
317
318
319 self.LookupCache[PageNumber] = (
320 XpressHeader.obj_offset, XpressBlockSize, XpressPage)
321
322 self.PageIndex += 1
323 XpressIndex += 1
324
325 NextTable = MemoryArray.MemArrayLink.NextTable.v()
326
327
328 if (NextTable and (EntryCount == self.entry_count)):
329 MemoryArrayOffset = NextTable * 0x1000
330 self.MemRangeCnt += 1
331
332 XpressHeader, XpressBlockSize = self.next_xpress(
333 XpressHeader, XpressBlockSize)
334
335
336 while (XpressHeader.obj_offset < MemoryArrayOffset):
337 XpressHeader, XpressBlockSize = self.next_xpress(
338 XpressHeader, 0)
339
340 XpressIndex = 0
341 else:
342 MemoryArrayOffset = 0
343
345 page_count = 0
346 for _i, xb in enumerate(self.PageDict.keys()):
347 size = self.PageDict[xb][0][1]
348 data_z = self.base.read(xb + 0x20, size)
349 if size == 0x10000:
350 data_uz = data_z
351 else:
352 data_uz = xpress.xpress_decode(data_z)
353 for page, size, offset in self.PageDict[xb]:
354 ofile.seek(page * 0x1000)
355 ofile.write(data_uz[offset * 0x1000:offset * 0x1000 + 0x1000])
356 page_count += 1
357 del data_z, data_uz
358 yield page_count
359
361 XpressHeaderOffset = int(XpressBlockSize) + XpressHeader.obj_offset + \
362 XpressHeader.size()
363
364
365 BLOCKSIZE = 1024
366 original_offset = XpressHeaderOffset
367 while 1:
368 data = self.base.read(XpressHeaderOffset, BLOCKSIZE)
369 Magic_offset = data.find("\x81\x81xpress")
370 if Magic_offset >= 0:
371 XpressHeaderOffset += Magic_offset
372 break
373
374 else:
375 XpressHeaderOffset += len(data)
376
377
378 if XpressHeaderOffset - original_offset > 10240:
379 return None, None
380
381 XpressHeader = self.profile.Object(
382 "_IMAGE_XPRESS_HEADER", XpressHeaderOffset, self.base)
383 XpressBlockSize = self.get_xpress_block_size(XpressHeader)
384
385 return XpressHeader, XpressBlockSize
386
388 u0B = xpress_header.u0B.v() << 24
389 u0A = xpress_header.u0A.v() << 16
390 u09 = xpress_header.u09.v() << 8
391
392 Size = u0B + u0A + u09
393 Size = Size >> 10
394 Size = Size + 1
395
396 if ((Size % 8) == 0):
397 return Size
398 return (Size & ~7) + 8
399
402
405
408
410 return self.header.SystemTime
411
413 return (self.ProcState.SpecialRegisters.Cr0.v() >> 31) & 1
414
416 return (self.ProcState.SpecialRegisters.Cr4.v() >> 4) & 1
417
419 return (self.ProcState.SpecialRegisters.Cr4.v() >> 5) & 1
420
422 return self.MemRangeCnt
423
425 return self.PageIndex
426
428 page = addr >> page_shift
429 if page in self.LookupCache:
430 (hoffset, size, pageoffset) = self.LookupCache[page]
431 return hoffset, size, pageoffset
432 return None, None, None
433
435 page = addr >> page_shift
436 if page in self.LookupCache:
437 (_hoffset, _size, pageoffset) = self.LookupCache[page]
438 return pageoffset
439 return None
440
442 XpressHeaderOffset, _XpressBlockSize, _XpressPage = self.get_addr(addr)
443 return XpressHeaderOffset != None
444
446 data_uz = self.PageCache.Get(baddr)
447 if data_uz is None:
448 data_read = self.base.read(baddr, BlockSize)
449 if BlockSize == 0x10000:
450 data_uz = data_read
451 else:
452 data_uz = xpress.xpress_decode(data_read)
453
454 self.PageCache.Put(baddr, data_uz)
455
456 return data_uz
457
458 - def fread(self, length):
462
464 """ A function which reads as much as possible from the current page.
465
466 May return a short read.
467 """
468
469 page_offset = (addr & 0x00000FFF)
470
471
472 available = min(PAGE_SIZE - page_offset, len)
473
474 ImageXpressHeader, BlockSize, XpressPage = self.get_addr(addr)
475 if not ImageXpressHeader:
476 return None
477
478 baddr = ImageXpressHeader + 0x20
479
480 data = self.read_xpress(baddr, BlockSize)
481
482
483
484 offset = XpressPage * 0x1000 + page_offset
485
486 return data[offset:offset + available]
487
488 - def read(self, addr, length):
489 result = ''
490 while length > 0:
491 data = self._partial_read(addr, length)
492 if not data:
493 break
494
495 addr += len(data)
496 length -= len(data)
497 result += data
498
499 if result == '':
500 result = obj.NoneObject("Unable to read data at %s for length %s." % (
501 addr, length))
502
503 return result
504
506 _baseaddr = self.get_addr(addr)
507 string = self.read(addr, 4)
508 if not string:
509 return obj.NoneObject("Could not read long at %s" % addr)
510 (longval,) = struct.unpack('=I', string)
511 return longval
512
514 page_list = []
515 for _i, xb in enumerate(self.PageDict.keys()):
516 for page, _size, _offset in self.PageDict[xb]:
517 page_list.append([page * 0x1000, page * 0x1000, 0x1000])
518 return page_list
519
521 """ This relates to the logical address range that is indexable """
522 size = self.HighestPage * 0x1000 + 0x1000
523 return [0, size]
524
526 memrange = self.get_address_range()
527 if addr < memrange[0] or addr > memrange[1]:
528 raise IOError
529
531 """ This returns the ranges of valid addresses """
532 for i in self.AddressList:
533 yield i
534
537