def calculate(self): addr_space = utils.load_as(self._config) self.apply_types(addr_space, self._config.VERSION) scanner = filescan.DriverScan(self._config) for driver in scanner.calculate(): drivername = str(driver.DriverName or '') if drivername.endswith("truecrypt"): for device in driver.devices(): code = device.DeviceType.v() type = devicetree.DEVICE_CODES.get(code) if type == 'FILE_DEVICE_DISK': yield device
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)
def calculate(self): space = utils.load_as(self._config) # enumerate system threads (0x00000010 = PS_CROSS_THREAD_FLAGS_SYSTEM) system_threads = [ t for t in modscan.ThrdScan(self._config).calculate() if t.CrossThreadFlags & 0x00000010 ] # find and dump the malicious kernel driver for item in filescan.DriverScan(self._config).calculate(): # unpack the parameters (object, driver, extension, object_name) = item # looking for unnamed driver objects if driver.DriverName.Length != 0: continue # the first and only device should be ACPI#PNP[...] device = obj.Object("_DEVICE_OBJECT", offset=driver.DeviceObject, vm=space) # get the device's object header object = obj.Object("_OBJECT_HEADER", \ offset = device.obj_offset - \ device.obj_vm.profile.get_obj_offset("_OBJECT_HEADER", "Body"), \ vm = space) object.kas = space device_name = object.get_object_name() # did we find zeroaccess? if not str(device_name).startswith("ACPI#PNP"): continue sys.stdout.write("DriverObject: {0:#x}\n".format( device.DriverObject)) sys.stdout.write(" DriverStart: {0:#x}\n".format( driver.DriverStart)) sys.stdout.write(" DriverSize: {0:#x}\n".format( driver.DriverSize)) sys.stdout.write("DeviceObject: {0:#x} {1}\n".format( device.obj_offset, device_name)) # dump the driver file_name = "Driver.{0:#x}.sys".format(driver.DriverStart) self.dump_pe(space, driver.DriverStart, file_name) # now what we know the memory range, look for bad threads for thread in system_threads: if thread.StartAddress > driver.DriverStart and \ thread.StartAddress < driver.DriverStart + driver.DriverSize: sys.stdout.write("Bad Thread: {0:#x} Tid {1}\n".format(\ thread.obj_offset, thread.Cid.UniqueThread)) # now find and dump the fake usermode ADS process for proc in tasks.pslist(space): for dll in proc.Peb.Ldr.InLoadOrderModuleList.list_of_type(\ "_LDR_DATA_TABLE_ENTRY", "InLoadOrderLinks"): # look for the ADS name if str(dll.BaseDllName).find(":") != -1: sys.stdout.write("Fake ADS EXE: {0} pid {1} base {2:#x}\n".format(\ proc.ImageFileName, proc.UniqueProcessId, dll.DllBase)) file_name = "Dll.{0:#x}.{1:#x}.dll".format( proc.obj_offset, dll.DllBase) self.dump_pe(proc.get_process_address_space(), dll.DllBase, file_name)