1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """Plugins to inspect the windows pools."""
19
20 __author__ = "Michael Cohen <scudette@google.com>"
21
22
23
24 from rekall import obj
25 from rekall.plugins.windows import common
26 from rekall_lib import utils
27
28
29
61
62
63 -class Pools(common.WindowsCommandPlugin):
64 """Prints information about system pools.
65
66 Ref:
67 http://illmatics.com/Windows%208%20Heap%20Internals.pdf
68 https://media.blackhat.com/bh-dc-11/Mandt/BlackHat_DC_2011_Mandt_kernelpool-wp.pdf
69 https://immunityinc.com/infiltrate/archives/kernelpool_infiltrate2011.pdf
70 http://gate.upm.ro/os/LABs/Windows_OS_Internals_Curriculum_Resource_Kit-ACADEMIC/WindowsResearchKernel-WRK/WRK-v1.2/base/ntos/ex/pool.c
71 """
72
73 name = "pools"
74
75 _pool_lookup = None
76
77 table_header = [
78 dict(name="descriptor", width=20, style="address"),
79 dict(name="type", width=20),
80 dict(name="index", width=5),
81 dict(name="size", width=10, align="r"),
82 dict(name="start", style="address"),
83 dict(name="end", style="address"),
84 dict(name="comment")
85 ]
86
88 vector_pool = self.profile.get_constant_object(
89 "PoolVector",
90 target="Array",
91 target_args=dict(
92 count=2,
93 target="Pointer",
94 )
95 )
96
97 resolver = self.session.address_resolver
98
99 for desc in vector_pool[0].dereference_as(
100 "Array",
101 target_args=dict(
102 count=self.profile.get_constant_object(
103 "ExpNumberOfNonPagedPools", "unsigned int").v(),
104 target="_POOL_DESCRIPTOR",
105 )
106 ):
107
108 start_va = resolver.get_constant_object(
109 "nt!MmNonPagedPoolStart", "Pointer").v()
110
111 end_va = resolver.get_constant_object(
112 "nt!MmNonPagedPoolEnd", "Pointer").v()
113
114
115
116 if start_va == None:
117
118
119 start_va = resolver.get_constant_object(
120 "nt!MiNonPagedPoolStartAligned", "Pointer").v()
121
122 end_va = resolver.get_constant_object(
123 "nt!MiNonPagedPoolEnd", "Pointer").v()
124
125 if end_va == None:
126 bitmap = resolver.get_constant_object(
127 "nt!MiNonPagedPoolBitMap", "_RTL_BITMAP")
128
129
130
131
132 end_va = start_va + bitmap.SizeOfBitMap * 8 * 0x1000
133
134
135 if start_va == None:
136 mistate = resolver.get_constant_object(
137 "nt!MiState", "_MI_SYSTEM_INFORMATION")
138
139 for node_index, node_info in enumerate(mistate.multi_m(
140 "Hardware.SystemNodeInformation",
141 "SystemNodeInformation"
142 )):
143 start_va = node_info.NonPagedPoolFirstVa.v()
144 end_va = start_va
145
146 for bitmap in node_info.NonPagedBitMap:
147 end_va = max(end_va, start_va + bitmap.SizeOfBitMap * 8)
148
149 desc.PoolStart = start_va
150 desc.PoolEnd = end_va
151 desc.Comment = "Node %i" % node_index
152
153 yield desc
154
155 else:
156 desc.PoolStart = start_va
157 desc.PoolEnd = end_va
158 desc.Comment = ""
159
160 yield desc
161
162 - def find_paged_pool(self):
163 vector_pool = self.profile.get_constant_object(
164 "PoolVector",
165 target="Array",
166 target_args=dict(
167 count=2,
168 target="Pointer",
169 )
170 )
171
172
173 paged_pool_start = self.profile.get_constant_object(
174 "MmPagedPoolStart", "Pointer").v()
175
176 if paged_pool_start == None:
177 paged_pool_start = self.profile.get_constant_object(
178 "MiPagedPoolStart", "Pointer").v()
179
180 paged_pool_end = (
181 paged_pool_start + self.profile.get_constant_object(
182 "MmSizeOfPagedPoolInBytes", "address"))
183
184 if paged_pool_start == None:
185
186
187 paged_pool_end = self.profile.get_constant_object(
188 "MmPagedPoolEnd", "Pointer").v()
189
190 bitmap = self.profile.get_constant_object(
191 "MmPagedPoolInfo", "_MM_PAGED_POOL_INFO").PagedPoolAllocationMap
192
193 if bitmap:
194 paged_pool_start = (
195 paged_pool_end - bitmap.SizeOfBitMap * 8 * 0x1000)
196
197 else:
198 paged_pool_start = (
199 paged_pool_end - self.profile.get_constant_object(
200 "MmSizeOfPagedPoolInBytes", "unsigned long long"))
201
202
203
204 if paged_pool_start == None:
205 mistate = self.session.address_resolver.get_constant_object(
206 "nt!MiState", "_MI_SYSTEM_INFORMATION")
207 dynamic_paged_pool = mistate.multi_m(
208
209 "SystemVa.DynamicBitMapPagedPool",
210
211
212 "DynamicBitMapPagedPool"
213 )
214 paged_pool_start = dynamic_paged_pool.BaseVa.v()
215 paged_pool_end = (
216 paged_pool_start +
217 dynamic_paged_pool.MaximumSize * 0x1000)
218
219 comment = ""
220 if not paged_pool_start:
221 if self.profile.metadata("arch") == "I386":
222
223
224 comment = "Fragmented (See virt_map plugin)"
225 paged_pool_start = paged_pool_end = None
226
227 else:
228
229
230
231 paged_pool_start = obj.Pointer.integer_to_address(
232 0xFFFFF8A000000000)
233 paged_pool_end = obj.Pointer.integer_to_address(
234 0xFFFFF8CFFFFFFFFF)
235
236 for desc in vector_pool[1].dereference_as(
237 "Array",
238 target_args=dict(
239 count=self.profile.get_constant_object(
240 "ExpNumberOfPagedPools", "unsigned int").v() + 1,
241 target="_POOL_DESCRIPTOR",
242 )
243 ):
244
245 desc.PoolStart = paged_pool_start
246 desc.PoolEnd = paged_pool_end
247 desc.Comment = comment
248
249 yield desc
250
263
270
280
282 descriptors = self.find_all_pool_descriptors()
283 for desc in sorted(descriptors):
284 yield dict(descriptor=desc,
285 type=desc.PoolType,
286 index=desc.PoolIndex,
287 size=desc.m("TotalBytes") or desc.TotalPages * 0x1000,
288 start=desc.PoolStart,
289 end=desc.PoolEnd,
290 comment=getattr(desc, "Comment", ""))
291
292
294 """Enumerate pool tag usage statistics."""
295
296 name = "pool_tracker"
297
298 table_header = [
299 dict(name="tag", width=4),
300 dict(name="nonpaged", width=20, align="r"),
301 dict(name="nonpaged_bytes", width=10, align="r"),
302 dict(name="paged", width=20, align="r"),
303 dict(name="paged_bytes", width=10, align="r"),
304 ]
305
307 table = self.profile.get_constant_object(
308 "PoolTrackTable",
309 target="Pointer",
310 target_args=dict(
311 target="Array",
312 target_args=dict(
313 count=self.profile.get_constant_object(
314 "PoolTrackTableSize", "unsigned int").v(),
315 target="_POOL_TRACKER_TABLE",
316 )
317 )
318 )
319
320 for item in table:
321 if item.Key == 0:
322 continue
323
324 self.session.report_progress()
325 yield (
326 item.Key.cast("String", length=4),
327 "%s (%s)" % (item.NonPagedAllocs,
328 item.NonPagedAllocs - item.NonPagedFrees),
329 item.NonPagedBytes,
330 "%s (%s)" % (item.PagedAllocs,
331 item.PagedAllocs - item.PagedFrees),
332 item.PagedBytes,
333 )
334