def detect_guid_from_mapped_file(self): """Guess the guid for the PE file.""" # Try to load the file from the physical address space. if self.session.physical_address_space.metadata("can_map_files"): phys_as = self.session.physical_address_space if self.filename: image_offset = phys_as.get_mapped_offset(self.filename, 0) if image_offset: try: file_as = addrspace.RunBasedAddressSpace( base=phys_as, session=self.session) file_as.add_run(0, image_offset, 2**63) pe_file_as = pe_vtypes.PEFileAddressSpace( base=file_as, session=self.session) pe_helper = pe_vtypes.PE( address_space=pe_file_as, image_base=pe_file_as.image_base, session=self.session) return pe_helper.RSDS.GUID_AGE except IOError: pass
def DetectFromHit(self, hit, _, address_space): for potential_path in self.KERNEL_PATHS: # Try to make the kernel image into the address_space. image_offset = address_space.get_mapped_offset(potential_path, 0) if image_offset is not None: file_as = addrspace.RunBasedAddressSpace( base=address_space, session=self.session) file_as.add_run(0, image_offset, 2**63) pe_file_as = pe_vtypes.PEFileAddressSpace( base=file_as, session=self.session) pe_helper = pe_vtypes.PE( session=self.session, address_space=pe_file_as, image_base=pe_file_as.image_base) rsds = pe_helper.RSDS self.session.logging.info( "Found RSDS in kernel image: %s (%s)", rsds.GUID_AGE, rsds.Filename) result = self._test_rsds(rsds) if result: return result
def DetectFromHit(self, hit, _, address_space): # If the file is a PE file, we simply return the PE address space. if self.pe_profile._IMAGE_DOS_HEADER(vm=address_space).NTHeader: pe_as = pe_vtypes.PEFileAddressSpace( base=address_space, profile=self.pe_profile) self.session.kernel_address_space = pe_as self.session.SetCache("default_image_base", pe_as.image_base) machine_type = pe_as.nt_header.FileHeader.Machine if machine_type == "IMAGE_FILE_MACHINE_AMD64": self.pe_profile.set_metadata("arch", "AMD64") else: self.pe_profile.set_metadata("arch", "I386") return self.pe_profile
def DetectFromHit(self, hit, _, address_space): # Try to make the kernel image into the address_space. image_offset = address_space.get_mapped_offset(self.KERNEL_PATH, 0) if image_offset is not None: file_as = addrspace.RunBasedAddressSpace(base=address_space, session=self.session) file_as.add_run(0, image_offset, 2**63) pe_file_as = pe_vtypes.PEFileAddressSpace(base=file_as, session=self.session) pe_helper = pe_vtypes.PE(session=self.session, address_space=pe_file_as, image_base=pe_file_as.image_base) return self._test_rsds(pe_helper.RSDS)
def ScanProfiles(self): pe_profile = self.session.LoadProfile("pe") address_space = self.session.physical_address_space best_profile = None best_match = 0 # If the file is a PE file, we simply return the PE address space. if pe_profile._IMAGE_DOS_HEADER(vm=address_space).NTHeader: self.session.kernel_address_space = pe_vtypes.PEFileAddressSpace( base=address_space, profile=pe_profile) return pe_profile for hit in ProfileScanner(address_space=address_space, session=self.session).scan(): # Try Windows by GUID: rsds = pe_profile.CV_RSDS_HEADER(offset=hit, vm=address_space) if (rsds.Signature.is_valid() and str(rsds.Filename) in self.KERNEL_NAMES): profile = self.VerifyWinProfile("nt/GUID/%s" % rsds.GUID_AGE) if profile: logging.info("Detected %s with GUID %s", rsds.Filename, rsds.GUID_AGE) best_profile = profile best_match = 1 # Try OS X by profile similarity: elif address_space.read(hit, len(OSX_NEEDLE)) == OSX_NEEDLE: # To work around KASLR, we have an index of known symbols' # offsets relative to the Catfish string, along with the data we # expect to find at those offsets. Profile similarity is the # percentage of these symbols that match as expected. # # Ideally, we'd like a 100% match, but in case we don't have the # exact profile, we'll make do with anything higher than 0% that # can resolve the DTB. logging.debug("Hit for Darwin at 0x%x", hit) index = self.session.LoadProfile("OSX/index") for profile_name, match in index.LookupIndex( image_base=hit, address_space=self.session.physical_address_space): profile = self.VerifyDarwinProfile(profile_name) if profile: if match > best_match: logging.info("New best match: %s (%.0f%% match)", profile_name, match * 100) best_profile, best_match = profile, match self.session.SetParameter("catfish_offset", hit) if match == 1.0: break # Try Linux by version string: else: guess = address_space.read(hit - 100, 300) m = self.LINUX_TEMPLATE.search(guess) if m: # Try to guess the distribution. distribution = "LinuxGeneric" if "Ubuntu" in guess: distribution = "Ubuntu" if "Debian" in guess: distribution = "Debian" profile_name = "%s/%s" % (distribution, m.group(1)) profile = self.VerifyLinuxProfile(profile_name) if profile: logging.info("Detected %s: %s", profile_name, m.group(0)) best_profile = profile best_match = 1 if best_match == 1.0: # If we have an exact match we can stop scanning. break threshold = self.session.GetParameter("autodetect_threshold") if best_match == 0: logging.error( "No profiles match this image. Try specifying manually.") elif best_match < threshold: logging.error( "Best match for profile is %s with %.0f%%, which is too low " + "for given threshold of %.0f%%. Try lowering " + "--autodetect-threshold.", best_profile.name, best_match * 100, threshold * 100) else: logging.info("Profile %s matched with %.0f%% confidence.", best_profile.name, best_match * 100) return best_profile