/usr/lib/python2.7/dist-packages/rekall/plugins/overlays/windows/heap.py is in python-rekall-core 1.6.0+dfsg-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | # Rekall Memory Forensics
# Copyright 2014 Google Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or (at
# your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""The module implements user mode heap overlays.
Recent versions of windows use the Low Fragmentation Heap (LFH).
http://illmatics.com/Understanding_the_LFH.pdf
"""
__author__ = "Michael Cohen <scudette@google.com>"
from rekall import addrspace
from rekall import utils
from rekall import obj
from rekall.plugins.overlays.windows import common
from rekall.plugins.overlays.windows import pe_vtypes
_HEAP_Flags = dict(
NO_SERIALIZE=0x00000001L,
GROWABLE=0x00000002L,
GENERATE_EXCEPTIONS=0x00000004L,
ZERO_MEMORY=0x00000008L,
REALLOC_IN_PLACE_ONLY=0x00000010L,
TAIL_CHECKING_ENABLED=0x00000020L,
FREE_CHECKING_ENABLED=0x00000040L,
DISABLE_COALESCE_ON_FREE=0x00000080L,
CREATE_ALIGN_16=0x00010000L,
CREATE_ENABLE_TRACING=0x00020000L,
CREATE_ENABLE_EXECUTE=0x00040000L,
)
_HEAP_ENTRY_Flags = dict(
BUSY=0x01,
EXTRA_PRESENT=0x02,
FILL_PATTERN=0x04,
VIRTUAL_ALLOC=0x08,
LAST_ENTRY=0x10,
SETTABLE_FLAG1=0x20,
SETTABLE_FLAG2=0x40,
SETTABLE_FLAG3=0x80,
)
overlays = {
'_PEB': [None, {
'ProcessHeaps': [None, ['Pointer', dict(
target='Array',
target_args=dict(
count=lambda x: x.NumberOfHeaps,
target='Pointer',
target_args=dict(
target='_HEAP'
)
)
)]],
}],
'_HEAP': [None, {
'BlocksIndex': [None, ['Pointer', dict(
target='_HEAP_LIST_LOOKUP'
)]],
'Flags': [None, ['Flags', dict(
maskmap=_HEAP_Flags,
target="unsigned long"
)]],
'FrontEndHeapType': lambda x: x.cast(
"Enumeration",
# LOOK_ASIDE is not available on Win7+.
choices={
0: "BACKEND", # Only using backend allocator.
1: "LOOK_ASIDE",
2: "LOW_FRAG",
},
value=x.m("FrontEndHeapType")
),
'FrontEndHeap': [None, ["Pointer", dict(
target="_LFH_HEAP"
)]],
}],
'_HEAP_ENTRY': [None, {
'Flags': [None, ['Flags', dict(
maskmap=_HEAP_ENTRY_Flags,
target="unsigned char"
)]],
}],
'_HEAP_FREE_ENTRY': [None, {
'Flags': [None, ['Flags', dict(
maskmap=_HEAP_ENTRY_Flags,
target="unsigned char"
)]],
}],
'_HEAP_LIST_LOOKUP': [None, {
'ListHints': [None, ["Array", dict(
target="_LIST_ENTRY",
count=lambda x: x.ArraySize
)]],
}],
'_HEAP_USERDATA_HEADER': [None, {
'Entries': [lambda x: x.obj_end, ["Array", dict(
target="_HEAP_ENTRY",
count=lambda x: x.obj_parent.BlockCount,
target_size=lambda x: x.obj_parent.BlockSize * 16,
)]],
}],
}
class _HEAP_ENTRY(obj.Struct):
"""A heap entry.
Note that heap entries for a given heap are encoded by using a random field
XORed with the heap entry. This object automatically decodes the heap entry
if the heap is encoded.
"""
def __init__(self, **kwargs):
super(_HEAP_ENTRY, self).__init__(**kwargs)
encoding = self.obj_context.get("Encoding")
if encoding:
heap_as = self.obj_context["HeapAS"]
self.obj_vm = addrspace.BufferAddressSpace(
session=self.obj_session,
base_offset=self.obj_offset,
data=utils.XOR(
heap_as.read(self.obj_offset, self.obj_size),
encoding)
)
@utils.safe_property
def PrevEntry(self):
if self.PreviousSize == 0:
return obj.NoneObject("First Entry")
return self.cast(
"Pointer",
target="_HEAP_ENTRY",
value=(self.obj_offset +
self.PreviousSize * self.obj_size))
@utils.safe_property
def NextEntry(self):
if self.Flags.LAST_ENTRY or self.Size == 0:
return obj.NoneObject("Last Entry")
return self.cast(
"Pointer",
target="_HEAP_ENTRY",
value=(self.obj_offset +
self.Size * self.obj_profile.get_obj_size("_HEAP_ENTRY")))
@utils.safe_property
def Allocation(self):
allocation_size = self.Size * self.obj_size
# On 64 bit platforms allocations are allowed to overflow into the first
# 8 bytes of the next allocation.
if self.obj_profile.metadata("arch") == "AMD64":
allocation_size -= 8
return self.obj_profile.String(offset=self.obj_end,
term=None,
length=allocation_size)
class _HEAP(obj.Struct):
"""
Ref:
http://www.informit.com/articles/article.aspx?p=1081496
"""
def __init__(self, **kwargs):
super(_HEAP, self).__init__(**kwargs)
# This passes the heap's encoding to all members of this heap.
if self.m("Encoding"):
self.obj_context["Encoding"] = self.obj_vm.read(
self.Encoding.obj_offset, self.Encoding.obj_size)
self.obj_context["HeapAS"] = self.obj_vm
@utils.safe_property
def Segments(self):
"""Returns an iterator over the segments."""
# Windows XP has an array of segments.
segment_array = self.m("Segments")
if segment_array:
for segment in segment_array:
segment = segment.dereference()
# Since we operate in the process address space address 0 may be
# valid.
if not segment:
break
yield segment
return
# Windows 7 has a linked list of segments.
for segment in self.SegmentList.list_of_type(
"_HEAP_SEGMENT", "SegmentListEntry"):
yield segment
@utils.safe_property
def Entries(self):
"""Iterates over all the entries in all the segments."""
for segment in self.Segments:
for entry in segment.FirstEntry.walk_list("NextEntry", True):
yield entry
class Ntdll(pe_vtypes.BasicPEProfile):
"""A profile for the ntdll user mode DLL."""
@classmethod
def Initialize(cls, profile):
super(cls, Ntdll).Initialize(profile)
InitializeHeapProfile(profile)
common.InitializeWindowsProfile(profile)
def InitializeHeapProfile(profile):
profile.add_overlay(overlays)
profile.add_classes(
_HEAP=_HEAP,
_HEAP_ENTRY=_HEAP_ENTRY,
_HEAP_FREE_ENTRY=_HEAP_ENTRY,
)
|