| Trees | Indices | Help |
|
|---|
|
|
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
62 _fields_ = [
63 ("BaseAddress", wintypes.DWORD),
64 ("AllocationBase", wintypes.DWORD),
65 ("AllocationProtect", wintypes.DWORD),
66 ("RegionSize", wintypes.UINT),
67 ("State", wintypes.DWORD),
68 ("Protect", wintypes.DWORD),
69 ("Type", wintypes.DWORD)
70 ]
71
74 _fields_ = [
75 ("BaseAddress", wintypes.LARGE_INTEGER),
76 ("AllocationBase", wintypes.LARGE_INTEGER),
77 ("AllocationProtect", wintypes.DWORD),
78 ("RegionSize", wintypes.LARGE_INTEGER),
79 ("State", wintypes.DWORD),
80 ("Protect", wintypes.DWORD),
81 ("Type", wintypes.DWORD)
82 ]
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
115 handle = self.handle = ctypes.windll.kernel32.OpenProcess(
116 READ_ACCESS, # win32con.PROCESS_ALL_ACCESS,
117 False,
118 pid)
119
120 # Close the handle on GC so we do not leak handles.
121 self._closer = weakref.ref(self, lambda x: CloseHandle(handle))
122
125 """Collect information about a VAD region.
126
127 This is the Live equivalent of _MMVAD.
128 """
129
130 @utils.safe_property
133
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 # Try to resolve the filename if possible.
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 # Try to merge this range with the previous range.
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 # Yield the old range:
227 if old_vad:
228 yield old_vad
229
230 old_vad = vad
231
232 # Emit the last range.
233 if old_vad:
234 yield old_vad
235
237 generator = self.generate_vads
238 if self.plugin_args.verbosity <= 1:
239 generator = self.merge_ranges
240
241 for proc in self.filter_processes():
242 divider = "{0} pid: {1:6}\n".format(proc.name, proc.pid)
243 yield dict(divider=divider)
244
245 for vad in generator(proc.pid):
246 if (self.plugin_args.regex and not
247 self.plugin_args.regex.search(vad.filename or "")):
248 continue
249
250 if (self.plugin_args.offset is not None and
251 not vad.start <= self.plugin_args.offset <= vad.end):
252 continue
253
254 yield dict(proc=proc,
255 VAD=vad,
256 start=vad.start,
257 end=vad.end,
258 Protect=MEMORY_PROTECTIONS.get(
259 vad.protection),
260 filename=vad.filename)
261
264 """An address space which read processes using ReadProcessMemory()."""
265
267 super(WinAPIProcessAddressSpace, self).__init__(**kwargs)
268
269 self.process_handle = ProcessHandle(pid)
270 for vad in self.session.plugins.vad().merge_ranges(pid):
271 self.add_run(vad.start, vad.start, vad.length,
272 address_space=self, data=dict(pid=pid, vad=vad))
273
275 if length > self.session.GetParameter("buffer_size"):
276 raise IOError("Too much data to read.")
277
278 result = ctypes.create_string_buffer(length)
279 bytes_read = ctypes.c_size_t()
280 status = ReadProcessMemory(
281 self.process_handle.handle,
282 addr, result, length, ctypes.byref(bytes_read))
283
284 # Failed ... return zeros.
285 if status == 0:
286 return addrspace.ZEROER.GetZeros(length)
287
288 return result.raw
289
290 # Register the process AS as a windows one.
291 common.IRProcessAddressSpace = WinAPIProcessAddressSpace
295 """Determine if the proc is Wow64."""
296 # Not the most accurate method but very fast.
297 return (proc.environ.get("PROCESSOR_ARCHITECTURE") == 'x86' and
298 proc.environ.get("PROCESSOR_ARCHITEW6432") == 'AMD64')
299
302 """Profile for Windows live analysis."""
303
305 super(WinAPIProfile, self).__init__(**kwargs)
306
307 # This is a profile for a dll or module in the current process
308 # context. Depending if the current process is a Wow64 process we need
309 # to load the 32 or 64 bit profiles.
310 process_context = proc or self.session.GetParameter("process_context")
311 if process_context:
312 if is_wow64(process_context):
313 basic.Profile32Bits.Initialize(self)
314 else:
315 basic.ProfileLLP64.Initialize(self)
316
317
318 # Register the profile for windows.
319 common.IRProfile = WinAPIProfile
320
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Oct 9 03:29:53 2017 | http://epydoc.sourceforge.net |