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