def ParseMultiple(self, stats, knowledge_base): """Parse Service registry keys and return WindowsServiceInformation.""" _ = knowledge_base services = {} field_map = { "Description": "description", "DisplayName": "display_name", "Group": "group_name", "DriverPackageId": "driver_package_id", "ErrorControl": "error_control", "ImagePath": "image_path", "ObjectName": "object_name", "Start": "startup_type", "Type": "service_type", "Parameters/ServiceDLL": "service_dll" } # Field map key should be converted to lowercase because key aquired through # self._GetKeyName could have some characters in different case than the # field map, e.g. ServiceDLL and ServiceDll. field_map = {k.lower(): v for k, v in field_map.items()} for stat in stats: # Ignore subkeys if not stat.HasField("registry_data"): continue service_name = self._GetServiceName(stat.pathspec.path) reg_key = os.path.dirname(stat.pathspec.path) service_info = rdf_client.WindowsServiceInformation( name=service_name, registry_key=reg_key) services.setdefault(service_name, service_info) key = self._GetKeyName(stat.pathspec.path) if key in field_map: try: services[service_name].Set(field_map[key], stat.registry_data.GetValue()) except type_info.TypeValueError: # Flatten multi strings into a simple string if (stat.registry_type == rdf_client.StatEntry.RegistryType.REG_MULTI_SZ): services[service_name].Set( field_map[key], utils.SmartUnicode(stat.registry_data.GetValue())) else: # Log failures for everything else # TODO(user): change this to yield a ParserAnomaly object. dest_type = type(services[service_name].Get( field_map[key])) logging.debug( "Wrong type set for %s:%s, expected %s, got %s", stat.pathspec.path, stat.registry_data.GetValue(), dest_type, type(stat.registry_data.GetValue())) return services.itervalues()
def testParse(self): parser = windows_persistence.WindowsPersistenceMechanismsParser() path = (r"HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion" r"\Run\test") pathspec = rdf_paths.PathSpec( path=path, pathtype=rdf_paths.PathSpec.PathType.REGISTRY) reg_data = "C:\\blah\\some.exe /v" reg_type = rdf_client.StatEntry.RegistryType.REG_SZ stat = rdf_client.StatEntry( aff4path="aff4:/asdfasdf/", pathspec=pathspec, registry_type=reg_type, registry_data=rdf_protodict.DataBlob(string=reg_data)) persistence = [stat] image_paths = [ "system32\\drivers\\ACPI.sys", "%systemroot%\\system32\\svchost.exe -k netsvcs", "\\SystemRoot\\system32\\drivers\\acpipmi.sys" ] reg_key = rdfvalue.RDFURN("aff4:/C.1000000000000000/registry" "/HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001" "/services/AcpiPmi") for path in image_paths: serv_info = rdf_client.WindowsServiceInformation( name="blah", display_name="GRRservice", image_path=path, registry_key=reg_key) persistence.append(serv_info) knowledge_base = rdf_client.KnowledgeBase() knowledge_base.environ_systemroot = "C:\\Windows" expected = [ "C:\\blah\\some.exe", "C:\\Windows\\system32\\drivers\\ACPI.sys", "C:\\Windows\\system32\\svchost.exe", "C:\\Windows\\system32\\drivers\\acpipmi.sys" ] for index, item in enumerate(persistence): results = list( parser.Parse(item, knowledge_base, rdf_paths.PathSpec.PathType.OS)) self.assertEqual(results[0].pathspec.path, expected[index]) self.assertEqual(len(results), 1)