def get_fileobj_offset(self, regex, cache=filescan_cache): file_re = re.compile(regex, re.IGNORECASE) if not cache: cache = dict() data = filescan.FileScan(self._config).calculate() for fileobj in data: if fileobj.file_name_with_device(): cache[fileobj.file_name_with_device()] = fileobj.obj_offset for fname, offset in cache.items(): if file_re.search(fname): yield fname, offset
def scan(self): # Enumerate all available file paths directories = [] scanner = filescan.FileScan(self._config) for fobj in scanner.calculate(): fpath = "{0}".format(fobj.file_name_with_device() or '') if fpath: path = fpath.upper().rsplit('\\', 1)[0] if not path in directories: directories.append(path) return directories
def get_tasks(self): addr_space = utils.load_as(self._config) f = filescan.FileScan(self._config) tasks = [] parsed_tasks = [] for file in f.calculate(): filename = str(file.file_name_with_device() or '') if "system32\\tasks\\" in filename.lower() and ( 'system32\\tasks\\microsoft' not in filename.lower() or self._config.VERBOSE): header = file.get_object_header() tasks.append((file.obj_offset, filename)) debug.debug("Found task: 0x{0:x} {1}".format( file.obj_offset, filename)) for offset, name in tasks: self._config.PHYSOFFSET = '0x{:x}'.format(offset) df = dumpfiles.DumpFiles(self._config) self._config.DUMP_DIR = '.' for data in df.calculate(): # Doing this with mmap would probably be cleaner # Create a sufficiently large (dynamically resizable?) # memory map so that we can seek and write the file accordingly # # SystemError: mmap: resizing not available--no mremap() chopped_file = {} for mdata in data['present']: rdata = addr_space.base.read(mdata[0], mdata[2]) chopped_file[mdata[1]] = rdata task_xml = "".join(part[1] for part in sorted(chopped_file.items(), key=lambda x: x[0])) parsed = self.parse_task_xml(task_xml) if parsed: args = parsed['Actions']['Exec'].get("Arguments", None) if args: parsed['Actions']['Exec']['Command'] += " {}".format( args) pids = self.find_pids_for_imagepath( parsed['Actions']['Exec']['Command']) parsed_tasks.append( (name.split('\\')[-1], parsed, task_xml, pids)) return parsed_tasks
def find_tasks(self): addr_space = utils.load_as(self._config) file_list = [] file_scan = filescan.FileScan(self._config) file_results = file_scan.calculate() for file in file_results: filename = str(file.file_name_with_device()).lower() address = Address(file.obj_offset) access_string = str(file.access_string()) for task_location in TASK_LOCATIONS: if task_location in filename: if not "system32\\tasks\\microsoft" in filename: print address, filename, access_string offset = "0x{:x}".format(address) self.task_files(offset)
def calculate(self): addr_space = utils.load_as(self._config) # we currently don't use this on x64 because for some reason the # x64 version actually doesn't create a DisplayVersion value memory_model = addr_space.profile.metadata.get('memory_model') if memory_model == '32bit': regapi = registryapi.RegistryApi(self._config) regapi.reset_current() regapi.set_current(hive_name = "software") x86key = "Microsoft\\Windows\\CurrentVersion\\Uninstall" x64key = "Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall" for subkey in regapi.reg_get_all_subkeys(None, key = x86key): if str(subkey.Name) == "TrueCrypt": subpath = x86key + "\\" + subkey.Name version = regapi.reg_get_value("software", key = subpath, value = "DisplayVersion") if version: yield "Registry Version", "{0} Version {1}".format( str(subkey.Name), version) scanner = TrueCryptPassphrase(self._config) for offset, passphrase in scanner.calculate(): yield "Password", "{0} at offset {1:#x}".format( passphrase, offset) for proc in tasks.pslist(addr_space): if str(proc.ImageFileName).lower() == "truecrypt.exe": yield "Process", "{0} at {1:#x} pid {2}".format( proc.ImageFileName, proc.obj_offset, proc.UniqueProcessId) scanner = svcscan.SvcScan(self._config) for service in scanner.calculate(): name = str(service.ServiceName.dereference()) if name == "truecrypt": yield "Service", "{0} state {1}".format( name, service.State) for mod in modules.lsmod(addr_space): basename = str(mod.BaseDllName or '').lower() fullname = str(mod.FullDllName or '').lower() if (basename.endswith("truecrypt.sys") or fullname.endswith("truecrypt.sys")): yield "Kernel Module", "{0} at {1:#x} - {2:#x}".format( mod.BaseDllName, mod.DllBase, mod.DllBase + mod.SizeOfImage) scanner = filescan.SymLinkScan(self._config) for symlink in scanner.calculate(): object_header = symlink.get_object_header() if "TrueCryptVolume" in str(symlink.LinkTarget or ''): yield "Symbolic Link", "{0} -> {1} mounted {2}".format( str(object_header.NameInfo.Name or ''), str(symlink.LinkTarget or ''), str(symlink.CreationTime or '')) scanner = filescan.FileScan(self._config) for fileobj in scanner.calculate(): filename = str(fileobj.file_name_with_device() or '') if "TrueCryptVolume" in filename: yield "File Object", "{0} at {1:#x}".format( filename, fileobj.obj_offset) scanner = filescan.DriverScan(self._config) for driver in scanner.calculate(): object_header = driver.get_object_header() driverext = driver.DriverExtension drivername = str(driver.DriverName or '') servicekey = str(driverext.ServiceKeyName or '') if (drivername.endswith("truecrypt") or servicekey.endswith("truecrypt")): yield "Driver", "{0} at {1:#x} range {2:#x} - {3:#x}".format( drivername, driver.obj_offset, driver.DriverStart, driver.DriverStart + driver.DriverSize) for device in driver.devices(): header = device.get_object_header() devname = str(header.NameInfo.Name or '') type = devicetree.DEVICE_CODES.get(device.DeviceType.v()) yield "Device", "{0} at {1:#x} type {2}".format( devname or "<HIDDEN>", device.obj_offset, type or "UNKNOWN") if type == "FILE_DEVICE_DISK": data = addr_space.read(device.DeviceExtension, 2000) ## the file-hosted container path. no other fields in ## the struct are character based, so we should not ## hit false positives on this scan. offset = data.find("\\\x00?\x00?\x00\\\x00") if offset == -1: container = "<HIDDEN>" else: container = obj.Object("String", length = 255, offset = device.DeviceExtension + offset, encoding = "utf16", vm = addr_space) yield "Container", "Path: {0}".format(container)