1 import weakref
2 import win32con
3
4 import ctypes
5 from ctypes import wintypes
6 from rekall import addrspace
7 from rekall_lib import utils
8 from rekall.plugins.overlays import basic
9 from rekall.plugins.response import common
10 from rekall.plugins.response import processes
11
12
13 READ_ACCESS = (win32con.PROCESS_VM_READ |
14 win32con.PROCESS_VM_OPERATION |
15 win32con.PROCESS_QUERY_INFORMATION)
16
17 MEMORY_PROTECTIONS = {
18 0x10: "x---",
19 0x20: "xr--",
20 0x40: "xrw-",
21 0x80: "xrwc",
22 0x01: "----",
23 0x02: "-r--",
24 0x04: "-rw-",
25 0x08: "--wc"
26 }
27
28 MEMORY_TYPES = {
29 0x1000000: "MEM_IMAGE",
30 0x40000: "MEM_MAPPED",
31 0x20000: "MEM_PRIVATE"
32 }
35 _fields_ = [("wProcessorArchitecture", wintypes.WORD),
36 ("wReserved", wintypes.WORD),
37 ("dwPageSize", wintypes.DWORD),
38 ("lpMinimumApplicationAddress", wintypes.DWORD),
39 ("lpMaximumApplicationAddress", wintypes.DWORD),
40 ("dwActiveProcessorMask", wintypes.DWORD),
41 ("dwNumberOfProcessors", wintypes.DWORD),
42 ("dwProcessorType", wintypes.DWORD),
43 ("dwAllocationGranularity", wintypes.DWORD),
44 ("wProcessorLevel", wintypes.WORD),
45 ("wProcessorRevision", wintypes.WORD)]
46
48 _fields_ = [("wProcessorArchitecture", wintypes.WORD),
49 ("wReserved", wintypes.WORD),
50 ("dwPageSize", wintypes.DWORD),
51 ("lpMinimumApplicationAddress", wintypes.LARGE_INTEGER),
52 ("lpMaximumApplicationAddress", wintypes.LARGE_INTEGER),
53 ("dwActiveProcessorMask", wintypes.LARGE_INTEGER),
54 ("dwNumberOfProcessors", wintypes.DWORD),
55 ("dwProcessorType", wintypes.DWORD),
56 ("dwAllocationGranularity", wintypes.DWORD),
57 ("wProcessorLevel", wintypes.WORD),
58 ("wProcessorRevision", wintypes.WORD)]
59
71
83
84 OpenProcess = ctypes.windll.kernel32.OpenProcess
85 ReadProcessMemory = ctypes.windll.kernel32.ReadProcessMemory
86 ReadProcessMemory.argtypes = [wintypes.HANDLE,
87 wintypes.LPCVOID,
88 wintypes.LPVOID,
89 ctypes.c_size_t,
90 ctypes.POINTER(ctypes.c_size_t)]
91 ReadProcessMemory.restype = wintypes.BOOL
92
93 CloseHandle = ctypes.windll.kernel32.CloseHandle
94
95
96 GetMappedFileNameA = ctypes.windll.psapi.GetMappedFileNameA
97 GetMappedFileNameA.argtypes = [wintypes.HANDLE,
98 wintypes.LPVOID,
99 wintypes.LPSTR,
100 wintypes.DWORD]
101 GetMappedFileNameA.restype = wintypes.DWORD
102
103 VirtualQueryEx = ctypes.windll.kernel32.VirtualQueryEx
104 VirtualQueryEx.argtypes = [wintypes.HANDLE,
105 wintypes.LPCVOID,
106 wintypes.LPVOID,
107 wintypes.DWORD]
108 VirtualQueryEx.restype = wintypes.DWORD
109
110 MAX_PATH = 1024
122
123
124 -class LiveVad(utils.AttributeDict):
125 """Collect information about a VAD region.
126
127 This is the Live equivalent of _MMVAD.
128 """
129
130 @utils.safe_property
133
134
135 -class APIVad(processes.APIProcessFilter):
136 """A VAD plugin using the APIs."""
137
138 name = "vad"
139
140 __args = [
141 dict(name="regex", type="RegEx",
142 help="A regular expression to filter VAD filenames."),
143
144 dict(name="offset", type="SymbolAddress",
145 help="Only print the vad corresponding to this offset."),
146
147 dict(name="verbosity", type="IntParser", default=1,
148 help="With high verbosity print more information on each region."),
149 ]
150
151 table_header = [
152 dict(name='proc', type="proc", hidden=True),
153 dict(name="divider", type="Divider"),
154 dict(name='VAD', hidden=True),
155 dict(name='start', style="address"),
156 dict(name='end', style="address"),
157 dict(name='Protect', width=4),
158 dict(name='filename')
159 ]
160
162 process_handle = ProcessHandle(pid)
163
164 if not process_handle.handle:
165 return
166
167 SYSTEM_INFO = SYSTEM_INFO_64
168 MEMORY_BASIC_INFORMATION = MEMORY_BASIC_INFORMATION_64
169
170 system_info = SYSTEM_INFO()
171 psystem_info = ctypes.byref(system_info)
172 ctypes.windll.kernel32.GetSystemInfo(psystem_info)
173
174 base_address = system_info.lpMinimumApplicationAddress
175 max_address = system_info.lpMaximumApplicationAddress
176 page_address = base_address
177
178 while page_address < max_address:
179 mbi = MEMORY_BASIC_INFORMATION()
180 mbi_pointer = ctypes.byref(mbi)
181 size = ctypes.sizeof(mbi)
182 success = VirtualQueryEx(
183 process_handle.handle,
184 page_address,
185 mbi_pointer,
186 size)
187
188 if not success:
189 break
190
191 if mbi.AllocationProtect != 0:
192
193 filename = ctypes.create_string_buffer("", MAX_PATH)
194 copied = GetMappedFileNameA(
195 process_handle.handle, page_address, filename, MAX_PATH)
196 if copied > 0:
197 filename = filename.value
198 else:
199 filename = None
200
201 yield LiveVad(
202 start=mbi.BaseAddress,
203 end=mbi.BaseAddress + mbi.RegionSize,
204 protection=mbi.AllocationProtect,
205 current_protection=mbi.Protect,
206 type=MEMORY_TYPES.get(mbi.Type, mbi.Type),
207 filename=filename,
208 pid=pid
209 )
210
211 page_address = mbi.BaseAddress + mbi.RegionSize
212
214 """Generate merged ranges."""
215 old_vad = None
216
217 for vad in self.generate_vads(pid):
218
219 if (old_vad and
220 old_vad.end == vad.start and
221 old_vad.protection == vad.protection and
222 old_vad.filename == vad.filename):
223 old_vad.end = vad.end
224 continue
225
226
227 if old_vad:
228 yield old_vad
229
230 old_vad = vad
231
232
233 if old_vad:
234 yield old_vad
235
261
264 """An address space which read processes using ReadProcessMemory()."""
265
266 - def __init__(self, pid=None, **kwargs):
273
274 - def read(self, addr, length):
289
290
291 common.IRProcessAddressSpace = WinAPIProcessAddressSpace
295 """Determine if the proc is Wow64."""
296
297 return (proc.environ.get("PROCESSOR_ARCHITECTURE") == 'x86' and
298 proc.environ.get("PROCESSOR_ARCHITEW6432") == 'AMD64')
299
302 """Profile for Windows live analysis."""
303
304 - def __init__(self, proc=None, **kwargs):
316
317
318
319 common.IRProfile = WinAPIProfile
320