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 @author: AAron Walters
26 @license: GNU General Public License 2.0 or later
27 @contact: awalters@volatilesystems.com
28 @organization: Volatile Systems
29
30 Alias for all address spaces
31
32 """
33 from rekall_lib import registry
34 from rekall_lib import utils
39 self.store = utils.FastStore(10, lock=True)
40
42 try:
43 return self.store.Get(length)
44 except KeyError:
45 zeros = "\x00" * length
46 self.store.Put(length, zeros)
47 return zeros
48
49
50
51 ZEROER = Zeroer()
55 """An implementation of a TLB.
56
57 This can be used by an address space to cache translations.
58 """
59
60 PAGE_SHIFT = 12
61 PAGE_ALIGNMENT = (1 << PAGE_SHIFT) - 1
62 PAGE_MASK = ~ PAGE_ALIGNMENT
63
65 self.page_cache = utils.FastStore(max_size)
66
67 - def Get(self, vaddr):
68 """Returns the cached physical address for this virtual address."""
69
70
71
72 result = self.page_cache.Get(vaddr & self.PAGE_MASK)
73
74
75 if result is not None:
76 return result + (vaddr & self.PAGE_ALIGNMENT)
77
78 - def Put(self, vaddr, paddr):
79 if vaddr & self.PAGE_ALIGNMENT:
80 raise TypeError("TLB must only cache aligned virtual addresses.")
81
82 self.page_cache.Put(vaddr, paddr)
83
84
85 -class Run(object):
86 """A container for runs."""
87 __slots__ = ("start", "end", "address_space", "file_offset", "data")
88
89 - def __init__(self, start=None, end=None, address_space=None,
90 file_offset=None, data=None):
96
97 @utils.safe_property
100
101 @length.setter
104
105 - def copy(self, **kw):
113
121
124 """ This is the base class of all Address Spaces. """
125
126 __metaclass__ = registry.MetaclassRegistry
127 __abstract = True
128
129 order = 10
130
131
132 name = ""
133
134
135
136
137
138
139
140 __image = False
141
142
143
144
145 volatile = False
146
147
148 virtualized = False
149
150 - def __init__(self, base=None, session=None, profile=None, **_):
151 """Base is the AS we will be stacking on top of, opts are options which
152 we may use.
153
154 Args:
155 base: A base address space to stack on top of (i.e. delegate to it for
156 satisfying read requests).
157
158 session: An optional session object.
159
160 profile: An optional profile to use for parsing the address space
161 (e.g. needed for hibernation, crash etc.)
162 """
163 if session is None and base is not None:
164 session = base.session
165
166 self.base = base
167 if base:
168 self.volatile = self.base.volatile
169
170 self.profile = profile
171 self.session = session
172 if session is None:
173 raise RuntimeError("Session must be provided.")
174
176 """Duplicate for the assert command (so that optimizations don't disable
177 them)
178
179 It had to be called as_assert, since assert is a keyword
180 """
181 if not assertion:
182 raise ASAssertionError(
183 error or "Instantiation failed for unspecified reason")
184
186 """Return a string describing an address."""
187 return "%#x" % addr
188
189 - def read(self, unused_addr, length):
195
197 """Generates a sequence of Run() objects.
198
199 Each Run object describes a single range transformation from this
200 address space to another address space at a potentially different
201 mapped_offset.
202
203 Runs are assumed to not overlap and are generated in increasing order.
204
205 Args:
206 start: The suggested start address we are interested in. This function
207 may omit runs that lie entirely below this start address. Note:
208 Runs are not adjusted to begin at the start address - it may be
209 possible that this method returns a run which starts earlier than
210 the specified start address.
211 """
212 _ = start
213 _ = end
214 return []
215
222
224 """Generates the runs which fall between start and end.
225
226 Note that start and end are here specified in the virtual address
227 space. More importantly this does not say anything about the pages in
228 the physical address space - just because pages in the virtual address
229 space are contiguous does not mean they are also contiguous in the
230 physical address space.
231
232 Yields:
233 Run objects describing merged virtual address ranges. NOTE: These runs
234 do not have file_offset or address_space members since the file_offset
235 is not the same across the entire range and therefore it does not make
236 sense to directly read the base address space - If you want to do
237 this, use merge_base_ranges() instead.
238 """
239 last_voffset = last_voffset_end = 0
240
241 for run in self.get_mappings(start=start, end=end):
242
243 if run.start > end:
244 break
245
246 if run.start < start:
247
248
249 run = run.copy(start=start)
250
251
252 self.session.report_progress(
253 "%(name)s: Merging Address Ranges %(offset)#x %(spinner)s",
254 offset=run.start, name=self.name)
255
256
257
258 if run.start == last_voffset_end:
259 last_voffset_end = run.end
260
261 else:
262
263 if last_voffset_end > last_voffset:
264 yield Run(start=last_voffset,
265 end=last_voffset_end)
266
267
268 last_voffset = run.start
269 last_voffset_end = min(run.end, end)
270
271 if last_voffset_end > last_voffset:
272 yield Run(start=last_voffset, end=last_voffset_end)
273
275 """Generates merged address ranges from get_mapping().
276
277 This method is subtly different from get_address_ranges in that runs are
278 contiguous in the base address space, hence the yielded runs have a
279 valid file_offset member. Callers can safely issue read operations to
280 the address space.
281
282 Yields:
283 runs which are contiguous in the base address space. This function
284 is designed to produce ranges more optimized for reducing the number
285 of read operations from the underlying base address space.
286
287 """
288 contiguous_voffset = 0
289 contiguous_voffset_end = 0
290 contiguous_poffset = 0
291 last_run_length = 0
292 last_as = None
293
294 for run in self.get_mappings(start=start, end=end):
295
296 if end and run.start > end:
297 break
298
299 if run.start < start:
300 run = run.copy(
301 start=start,
302 file_offset=run.file_offset + start - run.start)
303
304
305 self.session.report_progress(
306 "%(name)s: Merging Address Ranges %(offset)#x %(spinner)s",
307 offset=run.start, name=self.name)
308
309
310 if (run.start == contiguous_voffset_end and
311 run.file_offset == contiguous_poffset + last_run_length and
312 run.address_space is last_as):
313 contiguous_voffset_end = min(run.end, end)
314 last_run_length = contiguous_voffset_end - contiguous_voffset
315 last_as = run.address_space
316
317 else:
318 if last_run_length > 0:
319 yield Run(start=contiguous_voffset,
320 end=contiguous_voffset_end,
321 address_space=last_as,
322 file_offset=contiguous_poffset)
323
324
325 contiguous_voffset = run.start
326 contiguous_voffset_end = min(run.end, end)
327 contiguous_poffset = run.file_offset or 0
328 last_run_length = contiguous_voffset_end - contiguous_voffset
329 last_as = run.address_space
330
331 if last_run_length > 0:
332 yield Run(start=contiguous_voffset,
333 end=contiguous_voffset_end,
334 address_space=last_as,
335 file_offset=contiguous_poffset)
336
338 """Tell us if the address is valid """
339 return True
340
341 - def write(self, addr, buf):
342 """Write to the address space, if writable.
343
344 The default behavior is to delegate the write to the base address space.
345 If an address space has no base then this function will throw an
346 IOError. Address spaces that actually implement writing should override.
347
348 Raises:
349 IOError if there is no base address space. Subclasses may raise
350 under additional circumstances.
351
352 Arguments:
353 addr: The address to write at, as understood by this AS (i.e.
354 a virtual address for virtual address spaces, physical for
355 physical).
356 buf: The data to write - most commonly a basestring instance.
357
358 Returns:
359 Number of bytes written.
360 """
361 if not self.base:
362 raise IOError("No base address space set on %r." % self)
363
364 return self.base.write(self.vtop(addr), buf)
365
366 - def vtop(self, addr):
367 """Return the physical address of this virtual address."""
368
369 return addr
370
377
378 @classmethod
382
384 return self.__class__.__name__
385
387 return utils.SmartStr(self)
388
390 return "<%s @ %#x %s>" % (
391 self.__class__.__name__, hash(self), self.name)
392
394 return (isinstance(other, self.__class__) and
395 self.base == other.base)
396
398 """Implement this to return an address space for filename."""
399
401 """Implement this if we can map files into this address space."""
402
405
408
411 """Specialized address space for internal use.
412
413 Provides transparent reads through to a string buffer, so that profile
414 types can be instantiated on top of strings.
415 """
416 __image = False
417
418 @utils.safe_property
420 """Buffer AS is always writable, no matter what the session says."""
421 return True
422
423 - def __init__(self, base_offset=0, data='', **kwargs):
428
432
436
437 - def read(self, addr, length):
441
442 - def write(self, addr, data):
443 if addr > len(self.data):
444 raise ValueError(
445 "Cannot write to offset %d of buffer with size %d." %
446 (addr, len(self.data)))
447 self.data = self.data[:addr] + data + self.data[addr + len(data):]
448 return len(data)
449
456
458 """Returns the offset in self.data for the virtual offset."""
459 return offset - self.base_offset
460
462 return "<%s @ %#x %s [%#X-%#X]>" % (
463 self.__class__.__name__, hash(self), self.name,
464 self.base_offset, self.end())
465
467 return len(self.data)
468
470 """Return the end address of the buffer."""
471 return self.base_offset + len(self.data)
472
529
530
531 -class PagedReader(BaseAddressSpace):
532 """An address space which reads in page size.
533
534 This automatically takes care of splitting a large read into smaller reads.
535 """
536 PAGE_SIZE = 0x1000
537 PAGE_MASK = ~(PAGE_SIZE - 1)
538 __abstract = True
539
540 - def _read_chunk(self, vaddr, length):
541 """Read bytes from a virtual address.
542
543 Args:
544 vaddr: A virtual address to read from.
545 length: The number of bytes to read.
546
547 Returns:
548 As many bytes as can be read within this page.
549 """
550 to_read = min(length, self.PAGE_SIZE - (vaddr % self.PAGE_SIZE))
551 paddr = self.vtop(vaddr)
552 if paddr is None:
553 return ZEROER.GetZeros(to_read)
554
555 return self.base.read(paddr, to_read)
556
557 - def _write_chunk(self, vaddr, buf):
558 to_write = min(len(buf), self.PAGE_SIZE - (vaddr % self.PAGE_SIZE))
559 if not to_write:
560 return 0
561
562 paddr = self.vtop(vaddr)
563 if not paddr:
564 return 0
565
566 return self.base.write(paddr, buf[:to_write])
567
568 - def write(self, addr, buf):
569 available = len(buf)
570 written = 0
571
572 while available > written:
573 chunk_len = self._write_chunk(addr + written, buf[written:])
574 if not chunk_len:
575 break
576 written += chunk_len
577
578 return written
579
580 - def read(self, addr, length):
581 """Read 'length' bytes from the virtual address 'vaddr'."""
582 if length > self.session.GetParameter("buffer_size"):
583 raise IOError("Too much data to read.")
584
585 addr, length = int(addr), int(length)
586
587 result = ''
588
589 while length > 0:
590 buf = self._read_chunk(addr, length)
591 if not buf:
592 break
593
594 result += buf
595 addr += len(buf)
596 length -= len(buf)
597
598 return result
599
600 - def is_valid_address(self, addr):
601 vaddr = self.vtop(addr)
602 return vaddr != None and self.base.is_valid_address(vaddr)
603
606 """An address space which uses a list of runs to specify a mapping.
607
608 This essentially delegates certain address ranges to other address spaces
609 "mapped" into this address space.
610
611 The runs are tuples of this form:
612
613 (virtual_address, physical_address, length, address_space)
614
615 - Virtual Address - An address in this address space's virtual address
616 space.
617
618 - Physical Address - An address in the delegate address space.
619
620 - Length - The length of the mapped region.
621
622 - Address space - the address space that should be read for this
623 region. Note that the physical address above refers to addresses in this
624 delegate address space.
625 """
626
627
628 runs = None
629 __abstract = True
630
634
635 - def add_run(self, virt_addr, file_address, file_len, address_space=None,
636 data=None):
650
668
686
694
695 - def vtop(self, addr):
696 """Returns the physical address for this virtual address.
697
698 Note that this does not mean much without also knowing the address space
699 to read from. Maybe we need to change this method's prototype?
700 """
701 start, end, run = self.runs.get_containing_range(addr)
702 if start is not None:
703 if addr < end:
704 return run.file_offset + addr - start
705
707 return self.vtop(addr) is not None
708
710 """Yields the mappings.
711
712 Yields: A seqence of Run objects representing each run.
713 """
714 for _, _, run in self.runs:
715 if start > run.end:
716 continue
717
718 if run.start > end:
719 return
720
721 yield run
722
723
724 -class Error(Exception):
725 """Address space errors."""
726
729 """The address space failed to instantiate."""
730
733 """Address Space Exception.
734
735 This exception is raised when an AS decides to not be instantiated. It is
736 used in the voting algorithm.
737 """
738
740 self.reasons = []
741 Error.__init__(self, "No suitable address space mapping found")
742
744 self.reasons.append((driver, reason))
745
747 result = Error.__str__(self) + "\nTried to open image as:\n"
748 for k, v in self.reasons:
749 result += " {0}: {1}\n".format(k, v)
750
751 return result
752