def describe_vtop(self, vaddr, collection=None): """Describe the resolution process of a Virtual Address. See base method for docs. """ if collection is None: collection = intel.DescriptorCollection(self.session) # Bits 51:12 are from CR3 # Bits 11:3 are bits 47:39 of the linear address pml4e_addr = ((self.get_pml4() & 0xffffffffff000) | ((vaddr & 0xff8000000000) >> 36)) pml4e_value = self.read_pte(pml4e_addr, collection=collection) collection.add(intel.AddressTranslationDescriptor, object_name="pml4e", object_value=pml4e_value, object_address=pml4e_addr) if not pml4e_value & self.valid_mask: collection.add(intel.InvalidAddress, "Invalid PML4E\n") return collection # Bits 51:12 are from the PML4E # Bits 11:3 are bits 38:30 of the linear address pdpte_addr = ((pml4e_value & 0xffffffffff000) | ((vaddr & 0x7FC0000000) >> 27)) pdpte_value = self.read_pte(pdpte_addr, collection=collection) collection.add(intel.AddressTranslationDescriptor, object_name="pdpte", object_value=pdpte_value, object_address=pdpte_addr) if not pdpte_value & self.valid_mask: collection.add(intel.InvalidAddress, "Invalid PDPTE\n") return collection # Large page mapping. if pdpte_value & self.page_size_mask: # Bits 51:30 are from the PDE # Bits 29:0 are from the original linear address physical_address = ((pdpte_value & 0xfffffc0000000) | (vaddr & 0x3fffffff)) collection.add(intel.CommentDescriptor, "One Gig page\n") collection.add(intel.PhysicalAddressDescriptor, address=physical_address) return collection # Bits 51:12 are from the PDPTE # Bits 11:3 are bits 29:21 of the linear address pde_addr = ((pdpte_value & 0xffffffffff000) | ((vaddr & 0x3fe00000) >> 18)) self._describe_pde(collection, pde_addr, vaddr) return collection
def render(self, renderer): if self.plugin_args.physical_address is None: return descriptors = intel.DescriptorCollection(self.session) self.ptov(descriptors, self.plugin_args.physical_address) for descriptor in descriptors: descriptor.render(renderer)
def collect(self): ptov = self.session.plugins.ptov(session=self.session) pslist = self.session.plugins.pslist(session=self.session) pfn_database = self.session.profile.get_constant_object( "MmPfnDatabase") # Known tasks: known_tasks = set() for task in pslist.list_eprocess(): known_tasks.add(task.obj_offset) seen_dtbs = set() # Now scan all the physical address space for DTBs. for run in self.physical_address_space.get_mappings(): for page in range(run.start, run.end, 0x1000): self.session.report_progress("Scanning 0x%08X (%smb)" % (page, page / 1024 / 1024)) # Quit early if requested to. if page > self.plugin_args.limit: return collection = intel.DescriptorCollection(self.session) ptov.ptov(collection, page) dtb_descriptor = collection["WindowsDTBDescriptor"] if dtb_descriptor: dtb = dtb_descriptor.dtb if dtb not in seen_dtbs: seen_dtbs.add(dtb) pfn_obj = pfn_database[dtb >> 12] # Report the VA of the DTB (Since DTBs contains # themselves this will equal to the VA of the DTB. va = pfn_obj.PteAddress.v() task = dtb_descriptor.owner() yield (dtb, va, task, task.obj_offset and task.obj_offset in known_tasks)
def collect(self): pfn_obj = self.profile.get_constant_object("MmPfnDatabase")[ self.plugin_args.pfn] yield "PFN", self.plugin_args.pfn yield "PFN Record VA", pfn_obj.obj_offset yield "Type", None, pfn_obj.Type # In these states the other fields are meaningless. if pfn_obj.Type in ("Zeroed", "Freed", "Bad"): yield "Flink", pfn_obj.u1.Flink yield "Blink", pfn_obj.u2.Blink return # The flags we are going to print. flags = ["Modified", "ParityError", "ReadInProgress", "WriteInProgress"] long_flags_string = " ".join( [v for v in flags if pfn_obj.u3.e1.m(v) == 0]) yield "Flags", None, long_flags_string containing_page = int(pfn_obj.u4.PteFrame) pte_physical_address = ((containing_page << self.PAGE_BITS) | (int(pfn_obj.PteAddress) & 0xFFF)) yield "Reference", None, pfn_obj.u3.e2.ReferenceCount yield "ShareCount", None, pfn_obj.u2.ShareCount yield "Color", None, pfn_obj.multi_m("u3.e1.PageColor", "u4.PageColor") yield "Controlling PTE (VA)", pfn_obj.PteAddress yield "Controlling PTE (PA)", pte_physical_address yield ("Controlling PTE Type", None, "Prototype" if pfn_obj.IsPrototype else "Hardware") # PFN is actually a DTB. if containing_page == self.plugin_args.pfn: owning_process = pfn_obj.u1.Flink.cast( "Pointer", target="_EPROCESS") yield "Owning process", owning_process # Now describe the PTE and Prototype PTE pointed to by this PFN entry. collection = intel.DescriptorCollection(self.session) self.session.kernel_address_space.describe_pte( collection, pfn_obj.PteAddress, pfn_obj.PteAddress.Long, 0) yield "Controlling PTE", None, collection if pfn_obj.OriginalPte: collection = intel.DescriptorCollection(self.session) self.session.kernel_address_space.describe_proto_pte( collection, pfn_obj.OriginalPte.v(), pfn_obj.OriginalPte.Long, 0) yield "Original PTE", None, collection
def describe_phys_addr(self, phys_off): pfn_obj = self.pfn_database[phys_off >> 12] collection = intel.DescriptorCollection(self.session) self.ptov_plugin.ptov(collection, phys_off) result = dict(phys_offset=phys_off, List=pfn_obj.Type, Pr=pfn_obj.Priority) # Go through different kinds of use and display them in the table. descriptor = collection["VirtualAddressDescriptor"] if descriptor: dtb_descriptor = collection["WindowsDTBDescriptor"] # Address is in kernel space. if descriptor.address > self.session.GetParameter( "highest_usermode_address"): _, _, pool = self.pools.is_address_in_pool(descriptor.address) if pool: yield dict(Use=pool.PoolType, VA=descriptor.address, **result) else: yield dict(Use="Kernel", VA=descriptor.address, **result) else: yield dict(Use="Private", Process=dtb_descriptor.owner(), VA=descriptor.address, **result) return descriptor = collection["WindowsFileMappingDescriptor"] if descriptor: subsection = descriptor.get_subsection() filename, file_offset = descriptor.filename_and_offset( subsection=subsection) # First show the owner that mapped the file. virtual_address = None depth = 0 # A real mapped file. for process, virtual_address in descriptor.get_owners( subsection=subsection): yield dict(Use="Mapped File", Filename=filename, Offset=file_offset, depth=depth, Process=process, VA=virtual_address, **result) if self.plugin_args.verbosity <= 1: return # If the user wants more, also show the other processes which # map this file. depth = 1 # We could not find a process owner so we just omit it. if depth == 0: yield dict(Use="Mapped File", Filename=filename, Offset=file_offset, **result) return if pfn_obj.u3.e2.ReferenceCount == 0: result["Use"] = "Unused" yield result return yield result
def describe_vtop(self, vaddr, collection=None): if collection is None: collection = intel.DescriptorCollection(self.session) l1_descriptor_addr = (self.dtb | ((vaddr & self.table_index_mask) >> 18)) l1_descriptor = self.read_long_phys(l1_descriptor_addr) collection.add(intel.AddressTranslationDescriptor, object_name="l1 descriptor", object_value=l1_descriptor, object_address=l1_descriptor_addr) l1_descriptor_type = l1_descriptor & 0b11 if l1_descriptor_type == 0b00: collection.add(intel.InvalidAddress, "Invalid L1 descriptor") return collection # l1_descriptor is a Section descriptor. See Figure 3.8. if l1_descriptor_type == 0b10: # Super section. Figure 6.6. # http://infocenter.arm.com/help/topic/com.arm.doc.ddi0333h/DDI0333H_arm1176jzs_r0p7_trm.pdf if l1_descriptor & self.super_section_mask: collection.add( intel.CommentDescriptor, "Super section base @ {0:#x}\n", l1_descriptor & self.super_section_base_address_mask) collection.add(intel.PhysicalAddressDescriptor, address=(l1_descriptor & self.super_section_base_address_mask) | (vaddr & self.super_section_index_mask)) else: # Regular section descriptor. collection.add(intel.CommentDescriptor, "Section base @ {0:#x}\n", l1_descriptor & self.section_base_address_mask) collection.add( intel.PhysicalAddressDescriptor, address=(l1_descriptor & self.section_base_address_mask) | (vaddr & self.section_index_mask)) # l1_descriptor is a coarse page table descriptor. Figure 3.10. elif l1_descriptor_type == 0b01: collection.add( intel.CommentDescriptor, "Coarse table base @ {0:#x}\n", address=(l1_descriptor & self.coarse_page_table_base_address_mask)) l2_addr = ( (l1_descriptor & self.coarse_page_table_base_address_mask) | ((vaddr & self.l2_table_index_mask) >> 10)) l2_descriptor = self.read_long_phys(l2_addr) collection.add(intel.AddressTranslationDescriptor, object_name="2l descriptor", object_value=l2_descriptor, object_address=l2_addr) self._desc_l2_descriptor(collection, l2_descriptor, vaddr) # Fine page table descriptor. Section 3.2.6. elif l1_descriptor_type == 0b11: collection.add(intel.CommentDescriptor, "Fine table base @ {0:#x}\n", address=(l1_descriptor & self.fine_page_table_base_address_mask)) l2_addr = ((l1_descriptor & self.fine_page_table_base_address_mask) | ((vaddr & self.fine_l2_table_index_mask) >> 12)) l2_descriptor = self.read_long_phys(l2_addr) collection.add(intel.AddressTranslationDescriptor, object_name="2l descriptor", object_value=l2_descriptor, object_address=l2_addr) self._desc_l2_descriptor(collection, l2_descriptor, vaddr) return collection