Loading...
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 | import operator from abc import ABCMeta, abstractmethod from core import ( caching, gettype, ) from .kmem import KMem, MemoryRange class MemoryObject(object, metaclass=ABCMeta): """ Abstract class for any memory object resolved by Whatis """ MO_KIND = None def __init__(self, kmem, address): self.kmem = kmem self.address = address @property @abstractmethod def object_range(self): """ Returns the MemoryRange for this object if any """ pass @abstractmethod def describe(self, verbose=False): """ Method to describe oneself for whatis """ pass class UnknownMemoryObject(MemoryObject): """ Fallback Memory Object for unclaimed addresses """ MO_KIND = "<unknown>" @property def object_range(self): return None def describe(self, verbose=False): print("Unknown Memory Object Info") print(" this address is not recognized, please implement/extend") print(" a WhatisProvider to recognize it in the future") print() class WhatisProvider(object): """ Base class for Whatis Providers """ """ List of direct subclasses, used for resolution """ subproviders = [] """ Evaluation cost of this provider the higher the cost, the later it gets evaluated. """ COST = 10 def __init__(self, target): self._children = list(cls(target) for cls in self.__class__.subproviders) self.kmem = KMem.get_shared() self.target = target @staticmethod @caching.cache_statically def get_shared(target=None): return WhatisProvider(target) def find_provider(self, address): return next(iter(c for c in self._children if c.claims(address)), self) def claims(self, address): """ Returns whether this provider "claims" the address @param address (int) The addrress being considered """ pass def lookup(self, address): """ Lookup a memory object by address @param address (int) The addrress being considered @returns (MemoryObject) """ return UnknownMemoryObject(self.kmem, address) def describe(self, mo): """ Describe a memory object Providers can override this method to add more information. """ print(( "Basic Info\n" " kind : {0.__class__.MO_KIND}\n" " address : {0.address:#x}" ).format(mo)) mem_r = mo.object_range if mem_r is None: print(" {:<21s}: Unknown".format("object range")) else: print(" {:<21s}: {r.start:#x} - {r.end:#x} ({r.size:,d} bytes)".format( "object range", r = mem_r)) address = mo.address if address != mem_r.start: print(" {:<21s}: {:,d} from start, {:,d} to end".format( "offset", address - mem_r.start, mem_r.end - address)) print() def whatis_provider(cls): """ Class decorator for Whatis providers """ if not issubclass(cls, WhatisProvider): raise TypeError("{} is not a subclass of WhatisProvider".format(cls.__name__)) cls.subproviders = [] base = cls.__base__ if base != object: k = next(( k for k in ['claims', 'lookup'] if getattr(cls, k) == getattr(base, k) ), None) if k: raise TypeError("{} must reimplement function '{}'".format(cls.__name__, k)) base.subproviders.append(cls) base.subproviders.sort(key=operator.attrgetter('COST')) return cls __all__ = [ whatis_provider.__name__, MemoryObject.__name__, WhatisProvider.__name__, ] |