1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
70 continue
71
72 c_buffer = c_seg.c_store.c_buffer
73 if c_buffer == 0:
74
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
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
109
110
111
112
113
114
115
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