Package rekall :: Package plugins :: Package overlays :: Module basic
[frames] | no frames]

Source Code for Module rekall.plugins.overlays.basic

  1  # Rekall Memory Forensics 
  2  # 
  3  # Copyright 2013 Google Inc. All Rights Reserved. 
  4  # 
  5  # Authors: 
  6  # Copyright (C) 2012 Michael Cohen <scudette@users.sourceforge.net> 
  7  # Mike Auty <mike.auty@gmail.com> 
  8  # 
  9  # This program is free software; you can redistribute it and/or modify 
 10  # it under the terms of the GNU General Public License as published by 
 11  # the Free Software Foundation; either version 2 of the License, or (at 
 12  # your option) any later version. 
 13  # 
 14  # This program is distributed in the hope that it will be useful, but 
 15  # WITHOUT ANY WARRANTY; without even the implied warranty of 
 16  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 
 17  # General Public License for more details. 
 18  # 
 19  # You should have received a copy of the GNU General Public License 
 20  # along with this program; if not, write to the Free Software 
 21  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 22  # 
 23   
 24  """ This file defines some basic types which might be useful for many 
 25  OS's 
 26  """ 
 27  import datetime 
 28  import socket 
 29  import struct 
 30   
 31  import arrow 
 32   
 33  from rekall import config 
 34  from rekall import obj 
 35  from rekall.plugins.overlays import native_types 
 36  from rekall_lib import utils 
 37   
 38   
 39  config.DeclareOption( 
 40      "--timezone", default="UTC", group="Interface", 
 41      help="Timezone to output all times (e.g. Australia/Sydney).") 
42 43 44 -class String(obj.StringProxyMixIn, obj.NativeType):
45 """Class for dealing with Null terminated C Strings. 46 47 Note that these strings are _not_ text strings - they are effectively bytes 48 arrays and therefore are not encoded in any particular unicode encoding. 49 """ 50
51 - def __init__(self, length=1024, max_length=1024000, term="\x00", **kwargs):
52 """Constructor. 53 54 Args: 55 length: The maximum length of the string. 56 57 terminator: The terminator for this string. If None, there will be no 58 checking for null terminations (Pure character array). 59 """ 60 super(String, self).__init__(**kwargs) 61 62 # Allow length to be a callable: 63 if callable(length): 64 length = length(self.obj_parent) 65 66 self.term = term 67 self.length = int(length) 68 self.max_length = max_length
69 70 @utils.safe_property
71 - def obj_end(self):
72 return self.obj_offset + self.length
73
74 - def startswith(self, other):
75 return self.v().startswith(other)
76
77 - def v(self, vm=None):
78 # Make sure to protect ourselves before reading too much at once. 79 length = self.length 80 if self.length > self.max_length: 81 self.obj_session.logging.warn("%s@%#x truncated", 82 self.obj_name, self.obj_offset) 83 length = 0 84 85 # TODO: Make this read in chunks to support very large reads. 86 vm = vm or self.obj_vm 87 data = vm.read(self.obj_offset, length) 88 if self.term is not None: 89 try: 90 left, sep, _ = data.partition(self.term) 91 data = left + sep 92 # We can not split it, just return the full length. 93 except ValueError: 94 pass 95 96 return data
97
98 - def write(self, data):
99 return self.obj_vm.write(self.obj_offset, data)
100
101 - def proxied(self):
102 """ Return an object to be proxied """ 103 return str(self)
104
105 - def __str__(self):
106 # Remove any null termination chars. 107 return self.v().rstrip("\x00")
108
109 - def __unicode__(self):
110 return self.v().decode("utf8", "replace").split("\x00")[0] or u""
111
112 - def __len__(self):
113 return len(str(self))
114 115 @utils.safe_property
116 - def indices(self):
117 return (str(self),)
118
119 - def __getitem__(self, *args):
120 return self.v().__getitem__(*args)
121
122 - def __add__(self, other):
123 """Set up mappings for concat""" 124 return str(self) + other
125
126 - def __radd__(self, other):
127 """Set up mappings for reverse concat""" 128 return other + str(self)
129 130 @utils.safe_property
131 - def obj_size(self):
132 """This is equivalent to strlen() plus the terminator.""" 133 # The length is really determined by the terminator here. 134 return len(self.v())
135
136 137 -class Signature(String):
138 """A string forming a signature.""" 139
140 - def __init__(self, value=None, **kwargs):
141 super(Signature, self).__init__(length=len(value), term=None, 142 **kwargs) 143 self.signature = value
144
145 - def is_valid(self):
146 return self.v() == self.signature
147
148 149 -class UnicodeString(String):
150 """A class for dealing with encoded text strings. 151 152 Text strings are always encoded in some way in memory. The specific way of 153 encoding them is called the "encoding" - for example usually (but not 154 always) in windows the encoding is called "utf16", while on linux its 155 usually "utf8". 156 157 By default we take the encoding from the profile constant 158 "default_text_encoding". 159 """ 160
161 - def __init__(self, encoding=None, **kwargs):
162 super(UnicodeString, self).__init__(**kwargs) 163 self.encoding = encoding or self.obj_profile.get_constant( 164 'default_text_encoding')
165
166 - def v(self, vm=None):
167 vm = vm or self.obj_vm 168 169 data = vm.read(self.obj_offset, self.length) 170 171 # Try to interpret it as a unicode encoded string. 172 data = data.decode(self.encoding, "ignore") 173 174 # Now null terminate if needed. 175 if self.term is not None: 176 left, sep, _ = data.partition(self.term) 177 data = left + sep 178 179 return data
180
181 - def proxied(self):
182 return unicode(self)
183
184 - def __unicode__(self):
185 return self.v().split("\x00")[0] or u""
186
187 - def __getitem__(self, *args):
188 return unicode(self).__getitem__(*args)
189
190 - def __len__(self):
191 return len(unicode(self))
192
193 - def __repr__(self):
194 value = utils.SmartStr(self) 195 elide = "" 196 if len(value) > 50: 197 elide = "..." 198 value = value[:50] 199 200 return "%s (%s%s)" % (super(UnicodeString, self).__repr__(), 201 value, elide)
202 203 @utils.safe_property
204 - def obj_size(self):
205 return len(self.v()) * 2
206 # This will only work if the encoding and decoding are equivalent. 207 # return len(self.v().encode(self.encoding, 'ignore')) 208
209 - def write(self, data):
210 return self.obj_vm.write( 211 self.obj_offset, data.encode(self.encoding, "ignore"))
212
213 214 -class Flags(obj.NativeType):
215 """ This object decodes each flag into a string """ 216 # This dictionary maps a string mask name to an integer mask. 217 maskmap = None 218
219 - def __init__(self, bitmap=None, maskmap=None, 220 target="unsigned long", target_args=None, **kwargs):
221 super(Flags, self).__init__(**kwargs) 222 self.maskmap = maskmap or {} 223 if bitmap: 224 for k, v in bitmap.items(): 225 self.maskmap[k] = 1 << v 226 227 self.target = target 228 self.target_obj = self.obj_profile.Object( 229 target, offset=self.obj_offset, vm=self.obj_vm, 230 context=self.obj_context, **(target_args or {}))
231 232 @utils.safe_property
233 - def obj_size(self):
234 return self.target_obj.obj_size
235
236 - def v(self, vm=None):
237 return self.target_obj.v(vm=vm)
238
239 - def __iter__(self):
240 value = self.v() 241 for k, v in sorted(self.maskmap.items()): 242 if value & v: 243 yield k
244
245 - def __repr__(self):
246 flags = [] 247 length = 0 248 249 for flag in self: 250 length += len(flag) 251 if length >= 40: 252 flags.append(u'...') 253 break 254 255 flags.append(flag) 256 257 return "%s (%s)" % (super(Flags, self).__repr__(), ", ".join(flags))
258
259 - def write(self, data):
260 if isinstance(data, basestring): 261 value = 0 262 for item in data.split("|"): 263 item = item.strip() 264 mask = self.maskmap.get(item, 0) 265 value |= mask 266 267 data = value 268 269 return self.target_obj.write(data)
270
271 - def __getattr__(self, attr):
272 mask = self.maskmap.get(attr) 273 if not mask: 274 return obj.NoneObject("Mask {0} not known".format(attr)) 275 276 return self.v() & mask
277
278 279 -class Enumeration(obj.NativeType):
280 """Enumeration class for handling multiple meanings for a single value""" 281
282 - def __init__(self, choices=None, enum_name=None, 283 target="unsigned long", target_args=None, value=None, 284 default=None, **kwargs):
285 """Construct an enumeration instance. 286 287 The enumeration is constructed over the top of a target (which is 288 assumed to produce an integer value). The value of the target is then 289 looked up in the choices. Note that the enumeration is treated as an 290 integer. 291 292 Args: 293 choices: A dict of int values (keys) and names (values). 294 295 enum_name: If provided, the choices dict is retrieved from the 296 profile's constant area. This avoids the profile generator from 297 having to make copies of the enum choices for each field which uses 298 the same enum. 299 300 target: The target type which we overlay on. 301 302 value: Usually the value is parsed from the address space, but if the 303 value parameter is provided, we initialize from this value. 304 305 default: If the underlying integer does not appear in the choices 306 dict, we use this default value. 307 """ 308 super(Enumeration, self).__init__(**kwargs) 309 310 if enum_name: 311 choices = self.obj_profile.get_enum(enum_name) or {} 312 313 if callable(choices): 314 choices = choices(self.obj_parent) 315 elif not choices: 316 choices = {} 317 318 # Due to the way JSON serializes dicts, we must always operate on the 319 # choices dict with string keys. 320 self.choices = dict((str(k), v) for k, v in choices.iteritems()) 321 self.default = default 322 if callable(value): 323 value = value(self.obj_parent) 324 325 self.value = value 326 if value is None: 327 self.target = target 328 self.target_obj = self.obj_profile.Object( 329 target, offset=self.obj_offset, 330 vm=self.obj_vm, context=self.obj_context, 331 **(target_args or {}))
332 333 @utils.safe_property
334 - def obj_size(self):
335 return self.target_obj.obj_size
336
337 - def is_valid(self):
338 return str(self.v()) in self.choices
339
340 - def v(self, vm=None):
341 if self.value is None: 342 return self.target_obj.v(vm=vm) 343 344 # This return an instance of the target type. 345 return self.value
346
347 - def write(self, data):
348 if data in self.reverse_choices: 349 data = self.reverse_choices.get(data) 350 351 return self.target_obj.write(data)
352
353 - def __hash__(self):
354 # TODO: This hash function is dangerous, because the Enum compares 355 # as string or int, but hashes only as int. We need to implement a 356 # version of dict that supports multiple hash entries and then uncomment 357 # the exception: 358 # raise NotImplementedError("Enumerations are not hashable.") 359 return hash(self.v())
360
361 - def __unicode__(self):
362 value = self.v() 363 # Choices dict keys are always strings. 364 return self.choices.get(utils.SmartStr(value), self.default) or ( 365 u"UNKNOWN (%s)" % utils.SmartUnicode(value))
366
367 - def __eq__(self, other):
368 if isinstance(other, (int, long)): 369 return str(self.v()) == str(other) 370 371 # Search the choices. 372 for k, v in self.choices.iteritems(): 373 if v == other: 374 return str(self.v()) == k
375
376 - def __repr__(self):
377 return "%s (%s)" % (super(Enumeration, self).__repr__(), 378 self.__str__())
379 380 _reverse_choices = None 381 382 @utils.safe_property
383 - def reverse_choices(self):
384 if self._reverse_choices is None: 385 self._reverse_choices = {v: int(k) 386 for k, v in self.choices.items()} 387 return self._reverse_choices
388
389 - def __getattr__(self, attr):
390 value = self.reverse_choices.get(attr, None) 391 if value is None: 392 raise AttributeError(attr) 393 return value is not None and self.v() == value
394
395 396 -class Ipv4Address(obj.NativeType):
397 """Provides proper output for Ipv4Address objects""" 398
399 - def __init__(self, **kwargs):
400 super(Ipv4Address, self).__init__(**kwargs) 401 402 # Ipv4Address is always a 32 bit int. 403 self.format_string = "<I"
404
405 - def v(self, vm=None):
406 value = super(Ipv4Address, self).v(vm=vm) 407 return socket.inet_ntoa(struct.pack("<I", value))
408
409 410 -class Ipv6Address(obj.NativeType):
411 """Provides proper output for Ipv6Address objects""" 412
413 - def __init__(self, **kwargs):
414 super(Ipv6Address, self).__init__(**kwargs) 415 # Ipv4Address is always a 128 bit int. 416 self.format_string = "16s"
417
418 - def v(self, vm=None):
419 return utils.inet_ntop(socket.AF_INET6, obj.NativeType.v(self))
420
421 422 -class MacAddress(obj.NativeType):
423 """A MAC address.""" 424
425 - def __init__(self, **kwargs):
426 super(MacAddress, self).__init__(**kwargs) 427 # Ipv4Address is always a 128 bit int. 428 self.format_string = "6s"
429
430 - def v(self, vm=None):
431 return ":".join( 432 ["{0:02X}".format(ord(y)) for y in super(MacAddress, self).v()])
433
434 435 -class ListMixIn(object):
436 """A helper for following lists.""" 437 _forward = "Flink" 438 _backward = "Blink" 439
440 - def dereference_as(self, type, member, vm=None):
441 """Recasts the list entry as a member in a type, and return the type. 442 443 Args: 444 type: The name of this Struct type. 445 member: The name of the member of this Struct. 446 address_space: An optional address space to switch during 447 deferencing. 448 """ 449 offset = self.obj_profile.get_obj_offset(type, member) 450 451 item = self.obj_profile.Object( 452 type_name=type, offset=self.obj_offset - offset, 453 vm=vm or self.obj_vm, parent=self.obj_parent, 454 name=type, context=self.obj_context) 455 456 return item
457
458 - def find_all_lists(self):
459 """Follows all the list entries starting from self. 460 461 We basically convert the list to a tree and recursively search it for 462 new nodes. From each node we follow the Flink and then the Blink. When 463 we see a node we already have, we backtrack. This allows us to find 464 nodes which do not satisfy the relation (Due to smear): 465 466 x.Flink.Blink = x 467 468 Reference: 469 http://en.wikipedia.org/wiki/Depth-first_search 470 """ 471 # Maintain the order of discovery. 472 result = [] 473 seen = set() 474 475 stack = [self] 476 while stack: 477 item = stack.pop() 478 if item.obj_offset not in seen: 479 offset = item.obj_offset 480 seen.add(offset) 481 result.append(offset) 482 483 Blink = item.m(self._backward) 484 if Blink.is_valid(): 485 stack.append(Blink.dereference()) 486 487 Flink = item.m(self._forward) 488 if Flink.is_valid(): 489 stack.append(Flink.dereference()) 490 491 return result
492
493 - def list_of_type(self, type, member):
494 relative_offset = self.obj_profile.get_obj_offset(type, member) 495 496 # We traverse all the _LIST_ENTRYs we can find, and cast them all back 497 # to the required member. 498 for lst in self.find_all_lists(): 499 # Skip ourselves in this (list_of_type is usually invoked on a list 500 # head). 501 if lst == self.obj_offset: 502 continue 503 504 # Only yield valid objects (In case of dangling links). 505 if lst != 0: 506 yield self.obj_profile.Object( 507 type_name=type, offset=lst - relative_offset, 508 vm=self.obj_vm, parent=self.obj_parent, 509 name=type, context=self.obj_context)
510
511 - def list_of_type_fast(self, type, member, include_current=True):
512 for lst in self.walk_list( 513 self._forward, include_current=include_current): 514 yield container_of(lst, type, member)
515
516 - def reflect(self, vm=None):
517 """Reflect this list element by following its Flink and Blink. 518 519 This is basically the same as Flink.Blink except that it also checks 520 Blink.Flink. It also ensures that Flink and Blink are dereferences to 521 the correct type in case the vtypes do not specify them as pointers. 522 523 Returns: 524 the result of Flink.Blink. 525 """ 526 result = self.m(self._forward).dereference_as( 527 self.obj_type, vm=vm).m(self._backward).dereference_as( 528 self.obj_type) 529 530 if not result: 531 return obj.NoneObject("Flink not valid.") 532 533 return result
534
535 - def empty(self):
536 return self.m(self._forward) == self.m(self._backward)
537
538 - def __nonzero__(self):
539 # List entries are valid when both Flinks and Blink are valid 540 return bool(self.m(self._forward)) or bool(self.m(self._backward))
541
542 - def __iter__(self):
543 return self.list_of_type(self.obj_parent.obj_type, self.obj_name)
544
545 546 -class _LIST_ENTRY(ListMixIn, obj.Struct):
547 """ Adds iterators for _LIST_ENTRY types """
548
549 550 551 -class ShiftedTimezone(datetime.tzinfo):
552 tz_name = "" 553 tz_dst = datetime.timedelta(0) 554
555 - def __init__(self, utcoffset):
556 self.offset = datetime.timedelta(seconds=utcoffset)
557
558 - def utcoffset(self, dt):
559 return self.offset
560
561 - def dst(self, dt):
562 return self.tz_dst
563
564 - def tzname(self, dt):
565 return self.__class__.tz_name
566
567 568 -class UnixTimeStamp(obj.NativeType):
569 """A unix timestamp (seconds since the epoch).""" 570 571 timeformat = "YYYY-MM-DD HH:mm:ss" 572
573 - def __init__(self, format_string="I", **kwargs):
574 super(UnixTimeStamp, self).__init__( 575 format_string=format_string, **kwargs)
576
577 - def __nonzero__(self):
578 return self.v() != 0
579
580 - def __add__(self, other):
581 if isinstance(other, (float, int, long)): 582 return UnixTimeStamp( 583 value=self.v() + other, profile=self.obj_profile) 584 585 raise NotImplementedError
586
587 - def display(self, custom_tz=None, utc_shift=None):
588 try: 589 arw = self.as_arrow() 590 if custom_tz: 591 try: 592 arw = arw.to(custom_tz) 593 except RuntimeError: 594 pass 595 elif utc_shift is not None: 596 arw = arw.to(ShiftedTimezone(int(utc_shift))) 597 598 else: 599 arw = arw.to(self.obj_session.GetParameter("timezone", "UTC")) 600 601 # Mark UTC timezone with a Z 602 formatted_date = arw.format(self.timeformat) 603 formatted_tz = arw.format("Z") 604 if formatted_tz == "-0000": 605 formatted_tz = "Z" 606 607 return formatted_date + formatted_tz 608 609 except ValueError as e: 610 return obj.NoneObject("Error: %s", e)
611
612 - def __unicode__(self):
613 return unicode(self.display())
614
615 - def __repr__(self):
616 return "%s (%s)" % (super(UnixTimeStamp, self).__repr__(), 617 str(self))
618
619 - def as_arrow(self):
620 value = self.v() 621 if not value: 622 return obj.NoneObject("") 623 624 try: 625 # Return a data time object in UTC. 626 return arrow.Arrow.utcfromtimestamp(self.v()) 627 except (ValueError, TypeError) as e: 628 return obj.NoneObject("Datetime conversion failure: " + str(e))
629
630 - def as_datetime(self):
631 return self.as_arrow().datetime
632
633 634 -class ValueEnumeration(Enumeration):
635 """An enumeration which receives its value from a callable.""" 636
637 - def __init__(self, value=None, parent=None, **kwargs):
638 super(ValueEnumeration, self).__init__(parent=parent, **kwargs) 639 if callable(value): 640 value = value(parent) 641 642 self.value = value
643
644 - def v(self, vm=None):
645 return self.value
646
647 648 -class timeval(UnixTimeStamp, obj.Struct):
649
650 - def v(self, vm=None):
651 return float(self.m("tv_sec")) + self.m("tv_usec") / 1e6
652
653 654 -class WinFileTime(UnixTimeStamp):
655 """Class for handling Windows Time Stamps""" 656
657 - def __init__(self, is_utc=False, **kwargs):
658 super(WinFileTime, self).__init__(format_string="q", **kwargs) 659 self.is_utc = is_utc
660
661 - def as_windows_timestamp(self):
662 return super(WinFileTime, self).v()
663
664 - def v(self, vm=None):
665 value = self.as_windows_timestamp() 666 667 unix_time = value / 10000000 - 11644473600 668 if unix_time < 0: 669 unix_time = 0 670 671 return unix_time
672
673 674 -class ThreadCreateTimeStamp(WinFileTime):
675 """Handles ThreadCreateTimeStamps which are bit shifted WinFileTimes""" 676
677 - def as_windows_timestamp(self):
678 return super(ThreadCreateTimeStamp, self).as_windows_timestamp() >> 3
679
680 681 -class IndexedArray(obj.Array):
682 """An array which can be addressed via constant names.""" 683
684 - def __init__(self, index_table=None, **kwargs):
685 super(IndexedArray, self).__init__(**kwargs) 686 try: 687 self.index_table = dict( 688 (x, int(y)) for x, y in index_table.items()) 689 except ValueError: 690 self.index_table = dict( 691 (y, int(x)) for x, y in index_table.items()) 692 693 if self.count == 0: 694 self.count = len(index_table)
695
696 - def __getitem__(self, item):
697 # Still support numeric indexes 698 if isinstance(item, (int, long)): 699 index = item 700 701 # Try to name the object appropriately. 702 for k, v in self.index_table.items(): 703 if v == item: 704 item = k 705 break 706 707 elif item in self.index_table: 708 index = self.index_table[item] 709 else: 710 raise KeyError("Unknown index %s" % item) 711 712 result = super(IndexedArray, self).__getitem__(index) 713 result.obj_name = str(item) 714 715 return result
716
717 # We define three kinds of basic profiles, a 32 bit one and two 64 bit ones. 718 719 720 -class ProfileMIPS32Bits(obj.Profile):
721 """Basic profile for 32 bit MIPS systems.""" 722 METADATA = dict( 723 arch="MIPS", 724 data_model="BE32" 725 ) 726 727 @classmethod
728 - def Initialize(cls, profile):
729 super(ProfileMIPS32Bits, cls).Initialize(profile) 730 profile.add_classes(native_types.BE32) 731 profile.add_constants(dict(PoolAlignment=8, MAX_FAST_REF=7, 732 MaxPointer=2 ** 32 - 1))
733
734 735 -class Profile32Bits(obj.Profile):
736 """Basic profile for 32 bit systems.""" 737 METADATA = dict( 738 arch="I386", 739 data_model="ILP32" 740 ) 741 742 @classmethod
743 - def Initialize(cls, profile):
744 super(Profile32Bits, cls).Initialize(profile) 745 profile.add_classes(native_types.ILP32) 746 profile.add_constants(dict(PoolAlignment=8, MAX_FAST_REF=7, 747 MaxPointer=2 ** 32 - 1))
748
749 750 -class ProfileLLP64(obj.Profile):
751 """Basic profile for 64 bit Windows systems.""" 752 METADATA = dict( 753 arch="AMD64", 754 data_model="LLP64" 755 ) 756 757 @classmethod
758 - def Initialize(cls, profile):
759 super(ProfileLLP64, cls).Initialize(profile) 760 profile.add_classes(native_types.LLP64) 761 profile.add_constants(dict(PoolAlignment=16, MAX_FAST_REF=15, 762 MaxPointer=2 ** 48 - 1))
763
764 765 -class ProfileLP64(obj.Profile):
766 """Basic profile for 64 bit Linux systems.""" 767 METADATA = dict( 768 arch="AMD64", 769 data_model="LP64" 770 ) 771 772 @classmethod
773 - def Initialize(cls, profile):
776 777 778 common_overlay = { 779 'LIST_ENTRY32': [0x8, { 780 'Flink': [0x0, ['Pointer32', dict( 781 target='LIST_ENTRY32' 782 )]], 783 'Blink': [0x4, ['Pointer32', dict( 784 target='LIST_ENTRY32' 785 )]], 786 }], 787 788 'LIST_ENTRY64': [0x10, { 789 'Flink': [0x0, ['pointer', ['LIST_ENTRY64']]], 790 'Blink': [0x8, ['pointer', ['LIST_ENTRY64']]], 791 }] 792 }
793 794 795 -class BasicClasses(obj.Profile):
796 """Basic profile which introduces the basic classes.""" 797 798 @classmethod
799 - def Initialize(cls, profile):
800 super(BasicClasses, cls).Initialize(profile) 801 802 profile.add_classes({ 803 'String': String, 804 "Signature": Signature, 805 'UnicodeString': UnicodeString, 806 'Flags': Flags, 807 'Enumeration': Enumeration, 808 'Ipv4Address': Ipv4Address, 809 'Ipv6Address': Ipv6Address, 810 'MacAddress': MacAddress, 811 '_LIST_ENTRY': _LIST_ENTRY, 812 'LIST_ENTRY32': _LIST_ENTRY, 813 'LIST_ENTRY64': _LIST_ENTRY, 814 'WinFileTime': WinFileTime, 815 'ThreadCreateTimeStamp': ThreadCreateTimeStamp, 816 'UnixTimeStamp': UnixTimeStamp, 'timeval': timeval, 817 "IndexedArray": IndexedArray, 818 "ValueEnumeration": ValueEnumeration, 819 }) 820 profile.add_constants(dict(default_text_encoding="utf-16-le")) 821 profile.add_overlay(common_overlay)
822
823 824 -class RelativeOffsetMixin(object):
825 """A mixin which shifts all constant addresses by a constant.""" 826
827 - def __init__(self, **kwargs):
828 super(RelativeOffsetMixin, self).__init__(**kwargs) 829 830 # Some constants are specified as a absolute values - i.e. we do not 831 # shift them by the image base. This is especially the case for 832 # dynamically calculated constants which are derived from the image - 833 # i.e. after all addresses are shifted. 834 self.absolute_constants = {}
835 836 # This should be adjusted to the correct image base.
837 - def GetImageBase(self):
838 return 0
839
840 - def add_constants(self, constants=None, constants_are_absolute=False, 841 **opts):
842 if constants_are_absolute: 843 self.absolute_constants.update(constants) 844 else: 845 super(RelativeOffsetMixin, self).add_constants(constants, **opts)
846
847 - def get_constant(self, name, is_address=False):
848 """Gets the constant from the profile. 849 850 The windows profile specify addresses relative to the kernel image base. 851 """ 852 base_constant = super(RelativeOffsetMixin, self).get_constant( 853 name, is_address=is_address) 854 if is_address and isinstance(base_constant, (int, long)): 855 return base_constant + self.GetImageBase() 856 857 # Handle absolute constants specifically. 858 if base_constant == None: 859 absolute_constant = self.absolute_constants.get(name) 860 if absolute_constant: 861 # Support callable absolute constants. 862 if callable(absolute_constant): 863 absolute_constant = absolute_constant() 864 return absolute_constant 865 866 return base_constant
867
868 - def get_nearest_constant_by_address(self, address, below=True):
869 if address < self.GetImageBase(): 870 return 0, "" 871 872 try: 873 offset, name = super( 874 RelativeOffsetMixin, self).get_nearest_constant_by_address( 875 address - self.GetImageBase(), below=below) 876 877 return offset + self.GetImageBase(), name 878 except ValueError: 879 return self.GetImageBase(), "image_base"
880
881 882 -def container_of(ptr, type, member):
883 """cast a member of a structure out to the containing structure. 884 885 http://lxr.free-electrons.com/source/include/linux/kernel.h?v=3.7#L677 886 """ 887 offset = ptr.v() - ptr.obj_profile.get_obj_offset(type, member) 888 return ptr.obj_profile.Object(type, offset=offset, vm=ptr.obj_vm)
889