Package rekall :: Package plugins :: Package darwin :: Module compressor
[frames] | no frames]

Source Code for Module rekall.plugins.darwin.compressor

  1  # Rekall Memory Forensics 
  2  # 
  3  # Copyright 2014 Google Inc. All Rights Reserved. 
  4  # 
  5  # This program is free software; you can redistribute it and/or modify 
  6  # it under the terms of the GNU General Public License as published by 
  7  # the Free Software Foundation; either version 2 of the License, or (at 
  8  # your option) any later version. 
  9  # 
 10  # This program is distributed in the hope that it will be useful, but 
 11  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 13  # General Public License for more details. 
 14  # 
 15  # You should have received a copy of the GNU General Public License 
 16  # along with this program; if not, write to the Free Software 
 17  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 18  """Enumerate and dump all compressed memory pages on Darwin.""" 
 19   
 20  __author__ = "Andreas Moser <amoser@google.com>" 
 21   
 22  import os 
 23   
 24  from rekall.plugins import core 
 25  from rekall.plugins.darwin import common 
 26  from rekall.plugins.darwin import WKdm 
 27   
 28   
29 -class DarwinDumpCompressedPages(core.DirectoryDumperMixin, common.AbstractDarwinCommand):
30 """Dumps all compressed pages.""" 31 32 __name = "dumpcompressedmemory" 33 34 SLOT_ARRAY_SIZE = 64 35 PAGE_SIZE = 4096 36
37 - def UnpackCSize(self, c_slot):
38 39 size = c_slot.c_size 40 if size == self.PAGE_SIZE - 1: 41 return self.PAGE_SIZE 42 else: 43 return size
44
45 - def render(self, renderer):
46 47 pages = self.profile.get_constant_object("_c_segment_count", "int") 48 49 renderer.format("Going to dump {0} segments.\n", pages) 50 51 p_segu = self.profile.get_constant_object( 52 "_c_segments", "Pointer", target_args={ 53 "target": "Array", 54 "target_args": { 55 "target": "c_segu", 56 "count": int(pages), 57 }}) 58 59 segu_array = p_segu.deref() 60 61 for i, segu in enumerate(segu_array): 62 renderer.RenderProgress("Segment: %d" % i) 63 64 c_seg = segu.c_seg 65 66 if (c_seg.c_ondisk or 67 c_seg.c_on_swappedout_q or 68 c_seg.c_on_swappedout_sparse_q): 69 # Data swapped out. 70 continue 71 72 c_buffer = c_seg.c_store.c_buffer 73 if c_buffer == 0: 74 # No data in this segment. 75 continue 76 77 seg_buffer = c_buffer.obj_vm.read(c_buffer.v(), 78 c_seg.c_nextoffset * 4) 79 80 c_slot_arrays = [] 81 for slot in c_seg.c_slots: 82 c_slot_arrays.append( 83 slot.dereference_as( 84 target="Array", target_args=dict(target="c_slot"))) 85 86 for slot_nr in xrange(c_seg.c_nextslot): 87 c_slot_array = c_slot_arrays[slot_nr / self.SLOT_ARRAY_SIZE] 88 c_slot = c_slot_array[slot_nr % self.SLOT_ARRAY_SIZE] 89 90 if not (c_slot.c_offset and c_slot.c_size): 91 continue 92 93 c_size = self.UnpackCSize(c_slot) 94 95 # This should never happen. 96 if c_slot.c_offset * 4 + c_size >= len(seg_buffer): 97 continue 98 99 data = seg_buffer[c_slot.c_offset * 4: 100 c_slot.c_offset * 4 + c_size] 101 102 offset_alignment_mask = 0x3 103 104 c_rounded_size = (c_size + offset_alignment_mask) 105 c_rounded_size &= ~offset_alignment_mask 106 107 if (c_rounded_size == self.PAGE_SIZE): 108 # Page was not compressible. 109 # Copy anyways? 110 111 # with renderer.open( 112 # directory=self.dump_dir, 113 # filename="seg%d_slot%d.dat" % (i, slot_nr), 114 # mode="wb") as fd: 115 # fd.write(data) 116 continue 117 118 try: 119 decompressed = WKdm.WKdm_decompress_apple(data) 120 if decompressed: 121 dirname = os.path.join(self.dump_dir, "segment%d" % i) 122 try: 123 os.mkdir(dirname) 124 except OSError: 125 pass 126 127 with renderer.open( 128 directory=dirname, 129 filename="slot%d.dmp" % slot_nr, 130 mode="wb") as fd: 131 fd.write(decompressed) 132 133 except Exception as e: 134 renderer.report_error(str(e))
135