1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """The module implements user mode heap overlays.
20
21 Recent versions of windows use the Low Fragmentation Heap (LFH).
22
23 http://illmatics.com/Understanding_the_LFH.pdf
24
25 """
26
27 __author__ = "Michael Cohen <scudette@google.com>"
28
29 from rekall import addrspace
30 from rekall import obj
31 from rekall.plugins.overlays.windows import common
32 from rekall.plugins.overlays.windows import pe_vtypes
33 from rekall_lib import utils
34
35
36 _HEAP_Flags = dict(
37 NO_SERIALIZE=0x00000001L,
38 GROWABLE=0x00000002L,
39 GENERATE_EXCEPTIONS=0x00000004L,
40 ZERO_MEMORY=0x00000008L,
41 REALLOC_IN_PLACE_ONLY=0x00000010L,
42 TAIL_CHECKING_ENABLED=0x00000020L,
43 FREE_CHECKING_ENABLED=0x00000040L,
44 DISABLE_COALESCE_ON_FREE=0x00000080L,
45 CREATE_ALIGN_16=0x00010000L,
46 CREATE_ENABLE_TRACING=0x00020000L,
47 CREATE_ENABLE_EXECUTE=0x00040000L,
48 )
49
50 _HEAP_ENTRY_Flags = dict(
51 BUSY=0x01,
52 EXTRA_PRESENT=0x02,
53 FILL_PATTERN=0x04,
54 VIRTUAL_ALLOC=0x08,
55 LAST_ENTRY=0x10,
56 SETTABLE_FLAG1=0x20,
57 SETTABLE_FLAG2=0x40,
58 SETTABLE_FLAG3=0x80,
59 )
60
61 overlays = {
62 '_PEB': [None, {
63 'ProcessHeaps': [None, ['Pointer', dict(
64 target='Array',
65 target_args=dict(
66 count=lambda x: x.NumberOfHeaps,
67 target='Pointer',
68 target_args=dict(
69 target='_HEAP'
70 )
71 )
72 )]],
73 }],
74
75 '_HEAP': [None, {
76 'BlocksIndex': [None, ['Pointer', dict(
77 target='_HEAP_LIST_LOOKUP'
78 )]],
79
80 'Flags': [None, ['Flags', dict(
81 maskmap=_HEAP_Flags,
82 target="unsigned long"
83 )]],
84
85 'FrontEndHeapType': lambda x: x.cast(
86 "Enumeration",
87
88 choices={
89 0: "BACKEND",
90 1: "LOOK_ASIDE",
91 2: "LOW_FRAG",
92 },
93 value=x.m("FrontEndHeapType")
94 ),
95
96 'FrontEndHeap': [None, ["Pointer", dict(
97 target="_LFH_HEAP"
98 )]],
99
100 }],
101
102 '_HEAP_ENTRY': [None, {
103 'Flags': [None, ['Flags', dict(
104 maskmap=_HEAP_ENTRY_Flags,
105 target="unsigned char"
106 )]],
107
108 }],
109
110 '_HEAP_FREE_ENTRY': [None, {
111 'Flags': [None, ['Flags', dict(
112 maskmap=_HEAP_ENTRY_Flags,
113 target="unsigned char"
114 )]],
115
116 }],
117
118 '_HEAP_LIST_LOOKUP': [None, {
119 'ListHints': [None, ["Array", dict(
120 target="_LIST_ENTRY",
121 count=lambda x: x.ArraySize
122 )]],
123 }],
124
125 '_HEAP_USERDATA_HEADER': [None, {
126 'Entries': [lambda x: x.obj_end, ["Array", dict(
127 target="_HEAP_ENTRY",
128 count=lambda x: x.obj_parent.BlockCount,
129 target_size=lambda x: x.obj_parent.BlockSize * 16,
130 )]],
131 }],
132 }
133
134
135 -class _HEAP_ENTRY(obj.Struct):
136 """A heap entry.
137
138 Note that heap entries for a given heap are encoded by using a random field
139 XORed with the heap entry. This object automatically decodes the heap entry
140 if the heap is encoded.
141 """
142
143 - def __init__(self, **kwargs):
144 super(_HEAP_ENTRY, self).__init__(**kwargs)
145
146 encoding = self.obj_context.get("Encoding")
147 if encoding:
148 heap_as = self.obj_context["HeapAS"]
149 self.obj_vm = addrspace.BufferAddressSpace(
150 session=self.obj_session,
151 base_offset=self.obj_offset,
152 data=utils.XOR(
153 heap_as.read(self.obj_offset, self.obj_size),
154 encoding)
155 )
156
157 @utils.safe_property
158 - def PrevEntry(self):
159 if self.PreviousSize == 0:
160 return obj.NoneObject("First Entry")
161
162 return self.cast(
163 "Pointer",
164 target="_HEAP_ENTRY",
165 value=(self.obj_offset +
166 self.PreviousSize * self.obj_size))
167
168 @utils.safe_property
169 - def NextEntry(self):
170 if self.Flags.LAST_ENTRY or self.Size == 0:
171 return obj.NoneObject("Last Entry")
172
173 return self.cast(
174 "Pointer",
175 target="_HEAP_ENTRY",
176 value=(self.obj_offset +
177 self.Size * self.obj_profile.get_obj_size("_HEAP_ENTRY")))
178
179 @utils.safe_property
180 - def Allocation(self):
181 allocation_size = self.Size * self.obj_size
182
183
184
185 if self.obj_profile.metadata("arch") == "AMD64":
186 allocation_size -= 8
187
188 return self.obj_profile.String(offset=self.obj_end,
189 term=None,
190 length=allocation_size)
191
192
193 -class _HEAP(obj.Struct):
194 """
195 Ref:
196 http://www.informit.com/articles/article.aspx?p=1081496
197 """
198
200 super(_HEAP, self).__init__(**kwargs)
201
202
203 if self.m("Encoding"):
204 self.obj_context["Encoding"] = self.obj_vm.read(
205 self.Encoding.obj_offset, self.Encoding.obj_size)
206
207 self.obj_context["HeapAS"] = self.obj_vm
208
209 @utils.safe_property
211 """Returns an iterator over the segments."""
212
213 segment_array = self.m("Segments")
214 if segment_array:
215 for segment in segment_array:
216 segment = segment.dereference()
217
218
219
220 if not segment:
221 break
222
223 yield segment
224
225 return
226
227
228 for segment in self.SegmentList.list_of_type(
229 "_HEAP_SEGMENT", "SegmentListEntry"):
230 yield segment
231
232
233 @utils.safe_property
235 """Iterates over all the entries in all the segments."""
236 for segment in self.Segments:
237 for entry in segment.FirstEntry.walk_list("NextEntry", True):
238 yield entry
239
240
241
242 -class Ntdll(pe_vtypes.BasicPEProfile):
243 """A profile for the ntdll user mode DLL."""
244
245 @classmethod
251
260