Source code for angr.knowledge_plugins.cfg.memory_data

# pylint:disable=no-member
from typing import Optional
from ...protos import cfg_pb2
from ...serializable import Serializable


[docs]class MemoryDataSort: Unspecified = None Unknown = "unknown" Integer = "integer" PointerArray = "pointer-array" String = "string" UnicodeString = "unicode" SegmentBoundary = "segment-boundary" CodeReference = "code reference" GOTPLTEntry = "GOT PLT Entry" ELFHeader = "elf-header" FloatingPoint = "fp" # the size is determined by the MemoryData itself
_SORT_TO_IDX = { MemoryDataSort.Unspecified: cfg_pb2.MemoryData.Unspecified, MemoryDataSort.Unknown: cfg_pb2.MemoryData.UnknownDataType, MemoryDataSort.Integer: cfg_pb2.MemoryData.Integer, MemoryDataSort.PointerArray: cfg_pb2.MemoryData.PointerArray, MemoryDataSort.String: cfg_pb2.MemoryData.String, MemoryDataSort.UnicodeString: cfg_pb2.MemoryData.UnicodeString, MemoryDataSort.SegmentBoundary: cfg_pb2.MemoryData.SegmentBoundary, MemoryDataSort.CodeReference: cfg_pb2.MemoryData.CodeReference, MemoryDataSort.GOTPLTEntry: cfg_pb2.MemoryData.GOTPLTEntry, MemoryDataSort.ELFHeader: cfg_pb2.MemoryData.ELFHeader, MemoryDataSort.FloatingPoint: cfg_pb2.MemoryData.FloatingPoint, } _IDX_TO_SORT = {v: k for k, v in _SORT_TO_IDX.items()}
[docs]class MemoryData(Serializable): """ MemoryData describes the syntactic content of a single address of memory. """ __slots__ = ( "addr", "size", "sort", "max_size", "pointer_addr", "content", )
[docs] def __init__( self, address: int, size: int, sort: Optional[str], # temporary type pointer_addr: Optional[int] = None, max_size: Optional[int] = None, ): self.addr: int = address self.size: int = size self.sort: Optional[str] = sort self.max_size: Optional[int] = max_size self.pointer_addr: Optional[int] = pointer_addr self.content: Optional[bytes] = None # temporary annotation
@property def address(self): return self.addr def __repr__(self): return "\\{:#x}, {}, {}/".format( self.address, "%d bytes" % self.size if self.size is not None else "size unknown", self.sort )
[docs] def copy(self): """ Make a copy of the MemoryData. :return: A copy of the MemoryData instance. :rtype: MemoryData """ s = MemoryData(self.address, self.size, self.sort, pointer_addr=self.pointer_addr, max_size=self.max_size) s.content = self.content return s
[docs] def fill_content(self, loader): """ Load data to fill self.content. :param loader: The project loader. :return: None """ if self.sort == MemoryDataSort.String: self.content = loader.memory.load(self.addr, self.size) if self.content.endswith(b"\x00"): self.content = self.content.strip(b"\x00") elif self.sort == MemoryDataSort.UnicodeString: self.content = loader.memory.load(self.addr, self.size) while self.content.endswith(b"\x00\x00"): self.content = self.content[:-2] else: # FIXME: Other types are not supported yet return
# # Serialization # @classmethod def _get_cmsg(cls): return cfg_pb2.MemoryData()
[docs] def serialize_to_cmessage(self): cmsg = self._get_cmsg() cmsg.ea = self.addr cmsg.size = self.size if self.size is not None else 0 cmsg.type = _SORT_TO_IDX[self.sort] return cmsg
[docs] @classmethod def parse_from_cmessage(cls, cmsg, **kwargs): md = cls(cmsg.ea, cmsg.size, _IDX_TO_SORT[cmsg.type]) return md