def load_driver(self): """Unpack and load the driver.""" tarfile_handle = tarfile.open(self.driver_path) # Try to extract the resource into a tempdir. with utils.TempDirectory() as tmp_name: self.session.logging.info("Unpacking driver to %s", tmp_name) tarfile_handle.extractall(tmp_name) # Change ownership of the extracted files to make sure they are # owned by root otherwise they will not load. for root, files, dirs in os.walk(tmp_name): for f in files: os.chown(os.path.join(root, f), 0, 0) for d in dirs: os.chown(os.path.join(root, d), 0, 0) for member_name in tarfile_handle.getnames(): if member_name.endswith(".kext"): self.member_name = member_name.lstrip("/") full_driver_path = os.path.join(tmp_name, self.member_name) self.session.logging.info("Loading driver from %s", full_driver_path) res = subprocess.check_call(["kextload", full_driver_path]) if res != 0: raise plugin.PluginError( "Failed to load driver. Are you root?")
def _fetch_and_parse(self, module_name, guid): """Fetch the profile from the symbol server. Raises: IOError if the profile is not found on the symbol server or can not be retrieved. Returns: the profile data. """ with utils.TempDirectory() as dump_dir: pdb_filename = "%s.pdb" % module_name fetch_pdb_plugin = self.session.plugins.fetch_pdb( pdb_filename=pdb_filename, guid=guid, dump_dir=dump_dir) # Store the PDB file somewhere. pdb_pathname = os.path.join(dump_dir, pdb_filename) with fetch_pdb_plugin.FetchPDBFile() as infd: with open(pdb_pathname, "wb") as outfd: shutil.copyfileobj(infd, outfd) parse_pdb = self.session.plugins.parse_pdb( pdb_filename=pdb_pathname, dump_dir=dump_dir) return parse_pdb.parse_pdb()
def DownloadCompressedPDBFile(self, url, pdb_filename, guid, basename): url += "/%s/%s/%s.pd_" % (pdb_filename, guid, basename) self.session.report_progress("Trying to fetch %s\n", url) request = urllib.request.Request(url, None, headers={ 'User-Agent': self.USER_AGENT}) url_handler = urllib.request.urlopen(request) with utils.TempDirectory() as temp_dir: compressed_output_file = os.path.join( temp_dir, "%s.pd_" % basename) output_file = os.path.join( temp_dir, "%s.pdb" % basename) # Download the compressed file to a temp file. with open(compressed_output_file, "wb") as outfd: while True: data = url_handler.read(8192) if not data: break outfd.write(data) self.session.report_progress( "%s: Downloaded %s bytes", basename, outfd.tell()) # Now try to decompress it with system tools. This might fail. try: if platform.system() == "Windows": # This should already be installed on windows systems. subprocess.check_call( ["expand", compressed_output_file, output_file], cwd=temp_dir) else: # In Linux we just hope the cabextract program was # installed. subprocess.check_call( ["cabextract", compressed_output_file], cwd=temp_dir, stdout=sys.stderr) except (subprocess.CalledProcessError, OSError): raise RuntimeError( "Failed to decompress output file %s. " "Ensure cabextract is installed.\n" % output_file) # Sometimes the CAB file contains a PDB file with a different # name or casing than we expect. We use glob to find any PDB # files in the temp directory. output_file = glob.glob("%s/*pdb" % temp_dir)[0] # We read the entire file into memory here - it should not be # larger than approximately 10mb. with open(output_file, "rb") as fd: return fd.read(50 * 1024 * 1024)
def ParsePDB(self, guid, original_pdb_filename): repository = self.args.repository data = repository.GetData("src/pdb/%s.pdb" % guid, raw=True) profile_class = (self.args.profile_class or original_pdb_filename.capitalize()) with utils.TempDirectory() as temp_dir: pdb_filename = os.path.join(temp_dir, guid + ".pdb") with open(pdb_filename, "wb") as fd: fd.write(data) parse_pdb = self.session.plugins.parse_pdb( pdb_filename=pdb_filename, profile_class=profile_class) profile_data = json.loads(str(parse_pdb)) profile_data = self.TransformProfile(profile_data) repository.StoreData("%s/%s" % (self.args.profile_name, guid), profile_data)
def unload_driver(self): tarfile_handle = tarfile.open(self.driver_path) for member_name in tarfile_handle.getnames(): if not member_name.endswith(".kext"): continue self.member_name = member_name.lstrip("/") # Try to extract the resource into a tempdir. with utils.TempDirectory() as tmp_name: tarfile_handle.extractall(tmp_name) full_driver_path = os.path.join(tmp_name, self.member_name) self.session.logging.info("Unloading driver from %s", full_driver_path) try: subprocess.check_call([ "kextunload", os.path.join(tmp_name, self.member_name) ]) except Exception as e: # There isnt much we can do about it here. self.session.logging.debug("Unable to unload driver: %s" % e)