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