Windows.Veeam.RestorePoints.MetadataFiles

Parses the metadata found in Veeam backup chain metadata files (.vbm) to extract relevant fields for each Restore Point.

These files are generated by Veeam Backup & Replication during backup jobs. This artifact accepts metadata from unencrypted backups of virtual and physical infrastructures.


name: Windows.Veeam.RestorePoints.MetadataFiles

description: |
  Parses the metadata found in Veeam backup chain metadata files (`.vbm`) to extract relevant fields for each Restore Point.
  
  These files are generated by Veeam Backup & Replication during backup jobs. This artifact accepts metadata from **unencrypted** backups of virtual and physical infrastructures.

author: Synacktiv, Maxence Fossat - @cybiosity

reference:
  - https://www.synacktiv.com/publications/using-veeam-metadata-for-efficient-extraction-of-backup-artefacts-13

type: CLIENT

precondition: SELECT OS FROM info() WHERE OS = 'windows'

parameters:
  - name: BackupRepositories
    description: List of Backup Repositories where ".vbm" files should be looked for.
    type: csv
    default: |
      BackupRepoPath
      C:/BackupRepo1
      D:/BackupRepo2

required_permissions:
  - FILESYSTEM_READ

sources:
  - query: |
      // ============================
      // === Formatting functions ===
      // ============================
      
      // Function to format XML properties
      LET format_properties(Properties) = to_dict(item={ 
          SELECT AttrName AS _key,
                 Value AS _value
            FROM Properties
      })

      // Function to format disk_info capacity for HvAuxData
      LET hv_disk_capacity(Disks) = to_dict(item= {
          SELECT disk_info.CHvVmRctIdentifier.AttrFileId AS _key,
                 disk_info.Attrcapacity AS _value
            FROM Disks
      })

      // Function to format disk_info sizes for HvAuxData
      LET hv_disk_size(Disks) = to_dict(item= {
          SELECT disk_info.extent.Attrfilename AS _key,
                 disk_info.extent.Attrsize AS _value
            FROM Disks
      })
      
      // Function to format CRawDiskInfo sizes for HvAuxData
      LET hv_raw_disk_size(RawDisks) = to_dict(item= {
          SELECT CRawDiskInfo.SourceFileName AS _key,
                 CRawDiskInfo.ValidProcessedOffset AS _value
            FROM RawDisks
      })
      
      // Function to format Disk capacity for DesktopOibAuxData
      LET desktop_disk_capacity(Disks) = to_dict(item= {
          SELECT DevSetupInfo.AttrDevPath AS _key,
                 Capacity AS _value
            FROM Disks
      })
      
      // Function to format Disk sizes for DesktopOibAuxData
      LET desktop_disk_size(Disks) = to_dict(item= {
          SELECT OriginalDiskUniqueId AS _key,
                 Capacity AS _value
            FROM Disks
      })
      
      // Function to format Disk capacity for COibAuxDataVmware
      LET vmware_disk_capacity(Disks) = to_dict(item= {
          SELECT `Uuid` AS _key,
                 Capacity AS _value
            FROM Disks
      })
      
      // Function to format Disk sizes for COibAuxDataVmware
      LET vmware_disk_size(Disks) = to_dict(item= {
          SELECT FlatFileName AS _key,
                 ValidProcessedOffset AS _value
            FROM Disks
      })
      
      // Restore Point type
      LET restore_point_type = dict(
          `0`='Full',
          `1`='Increment'
      )
      
      // Backup encryption state
      LET back_enc_state = dict(
          `0`='Unencrypted',
          `2`='Encrypted'
      )




      // ========================
      // === Initial parsing ====
      // ========================
      
      // Parsing XML for each Veeam backup chain metadata file
      LET backup_repos = SELECT BackupRepoPath FROM BackupRepositories
      LET xml = SELECT * FROM foreach(row=backup_repos,
          query={
              SELECT Name AS MetadataFile, 
                     parse_xml(file=OSPath) AS Metadata
                FROM glob(globs='/**/*.vbm', root=BackupRepoPath, accessor='auto')
          })
      
      // Extracting interesting fields from the parsed metadata
      LET metadata = SELECT MetadataFile,
             Metadata.BackupMeta.BackupMetaInfo.Oibs.OIB AS ObjectsInBackup,
             Metadata.BackupMeta.BackupMetaInfo.Objects.Object AS Objects,
             Metadata.BackupMeta.BackupMetaInfo.Hosts.Host AS Hosts,
             Metadata.BackupMeta.BackupMetaInfo.Storages.Storage AS Storages,
             Metadata.BackupMeta.BackupMetaInfo.Points.Point AS RestorePoints,
             Metadata.BackupMeta.Backup AS Backups
        FROM xml
      

      

      // =========================      
      // === Objects In Backup ===
      // =========================
      
      // Expanding each Object In Backup (OIB) for each vbm file
      LET oibs = SELECT * FROM foreach(row=metadata,
          query={
              SELECT MetadataFile, Objects, Hosts, Storages, RestorePoints, Backups,
                     _value.AttrDisplayName AS DisplayName,
                     _value.AttrVmName AS VMName,
                     _value.AttrState AS State,
                     _value.AttrType AS Type,
                     _value.AttrAlgorithm AS Algorithm,
                     _value.AttrHealthStatus AS HealthStatus,
                     _value.AttrHasIndex AS HasIndex,
                     _value.AttrHasExchange AS HasExchange,
                     _value.AttrHasSharePoint AS HasSharePoint,
                     _value.AttrHasSql AS HasSQL,
                     _value.AttrHasAd AS HasAD,
                     _value.AttrHasOracle AS HasOracle,
                     _value.AttrHasPostgreSql AS HasPostgreSQL,
                     _value.AttrHasVeeamArchiver AS HasVeeamArchiver,
                     _value.AttrIsCorrupted AS IsCorrupted,
                     _value.AttrIsRecheckCorrupted AS IsRecheckCorrupted,
                     _value.AttrIsConsistent AS IsConsistent,
                     _value.AttrNeedHealthCheckRepair AS NeedHealthCheckRepair,
                     _value.AttrIsPartialActiveFull AS IsPartialActiveFull,
                     _value.AttrProductVersion AS ProductVersion,
                     _value.AttrProductVersionFlags AS ProductVersionFlags,
                     _value.AttrProductIsRentalLicense AS ProductIsRentalLicense,
                     _value.AttrObjectId AS ObjectID,
                     _value.AttrStorageId AS StorageID,
                     _value.AttrPointId AS RestorePointID,
                     _value.AttrEffectiveMemoryMb AS TempMemory,
                     timestamp(string=_value.AttrCreationTimeUtc) AS CreationTimeUTC,
                     timestamp(string=_value.AttrCompletionTimeUtc) AS CompletionTimeUTC,
                     humanize(bytes=int(int=_value.AttrApproxSize)) AS ApproximateSize,
                     parse_xml(file=_value.AttrAuxData, accessor='data').COibAuxData AS AuxData,
                     format_properties(
                            Properties = parse_xml(file=_value.AttrGuestInfo, accessor='data').GuestInfo.Property
                         ) AS GuestInfo
                FROM foreach(row=ObjectsInBackup)
          })
      
      // Correlating OIBs with Objects information
      LET oibs_objects = SELECT * FROM foreach(row=oibs,
          query={
              SELECT MetadataFile, Hosts, Storages, RestorePoints, Backups, DisplayName, VMName, State, Type, Algorithm, HealthStatus, HasIndex, HasExchange, HasSharePoint, HasSQL, HasAD, HasOracle, HasPostgreSQL, HasVeeamArchiver, IsCorrupted, IsRecheckCorrupted, IsConsistent, NeedHealthCheckRepair, IsPartialActiveFull, ProductVersion, ProductVersionFlags, ProductIsRentalLicense, StorageID, RestorePointID, CreationTimeUTC, CompletionTimeUTC, ApproximateSize,
                     format(format='%d MiB',
                         args = int(int=TempMemory) || int(int=AuxData.DesktopOibAuxData.SystemConfiguration.RAMInfo.AttrTotalSizeMB))
                      AS Memory,
                     hv_disk_capacity(Disks=AuxData.HvAuxData.disks.disk)
                       + desktop_disk_capacity(Disks=AuxData.DesktopOibAuxData.Disk)
                       + vmware_disk_capacity(Disks=AuxData.COibAuxDataVmware.Disk)
                       AS DisksCapacity,
                     hv_disk_size(Disks=AuxData.HvAuxData.disks.disk)
                       + hv_raw_disk_size(RawDisks=AuxData.HvAuxData.raw_disks.CRawDiskBackupObject)
                       + desktop_disk_size(Disks=AuxData.DesktopOibAuxData.Disk)
                       + vmware_disk_size(Disks=AuxData.COibAuxDataVmware.Disk)
                       AS ExtractableFilesSize,
                     GuestInfo.GuestOsName AS GuestOSName,
                     GuestInfo.GuestOsType AS GuestOSType,
                     GuestInfo.DnsName AS GuestDNSName,
                     GuestInfo.`Ip` AS GuestIP,
                     GuestInfo.ToolsStatus AS GuestToolsStatus,
                     GuestInfo.ToolsVersionStatus AS GuestToolsVersionStatus,
                     _value.AttrViType || 'Physical machine' AS VirtualType,
                     _value.AttrName AS ExtractName,
                     _value.AttrObjectId AS ExtractID,
                     _value.AttrHostId AS HostID
                FROM foreach(row=Objects) WHERE _value.AttrId = ObjectID
          })
      
      // Correlating OIBs with Hosts information
      LET oibs_hosts = SELECT * FROM foreach(row=oibs_objects,
          query={
              SELECT MetadataFile, Storages, RestorePoints, Backups, DisplayName, VMName, State, Type, Algorithm, HealthStatus, HasIndex, HasExchange, HasSharePoint, HasSQL, HasAD, HasOracle, HasPostgreSQL, HasVeeamArchiver, IsCorrupted, IsRecheckCorrupted, IsConsistent, NeedHealthCheckRepair, IsPartialActiveFull, ProductVersion, ProductVersionFlags, ProductIsRentalLicense, StorageID, RestorePointID, CreationTimeUTC, CompletionTimeUTC, ApproximateSize, Memory, DisksCapacity, ExtractableFilesSize, GuestOSName, GuestOSType, GuestDNSName, GuestIP, GuestToolsStatus, GuestToolsVersionStatus, VirtualType, ExtractName, ExtractID,
                     _value.AttrName AS HostName,
                     _value.AttrHostInstanceId AS HostInstanceID
                FROM foreach(row=Hosts) WHERE _value.AttrId = HostID
          })
    
      // Correlating OIBs with Storages information
      LET oibs_storages = SELECT * FROM foreach(row=oibs_hosts,
          query={
              SELECT MetadataFile, RestorePoints, Backups, DisplayName, VMName, State, Type, Algorithm, HealthStatus, HasIndex, HasExchange, HasSharePoint, HasSQL, HasAD, HasOracle, HasPostgreSQL, HasVeeamArchiver, IsCorrupted, IsRecheckCorrupted, IsConsistent, NeedHealthCheckRepair, IsPartialActiveFull, ProductVersion, ProductVersionFlags, ProductIsRentalLicense, RestorePointID, CreationTimeUTC, CompletionTimeUTC, ApproximateSize, Memory, DisksCapacity, ExtractableFilesSize, GuestOSName, GuestOSType, GuestDNSName, GuestIP, GuestToolsStatus, GuestToolsVersionStatus, VirtualType, ExtractName, ExtractID, HostName, HostInstanceID,
                     parse_xml(file=_value.AttrPartialPath, accessor='data').Path.Elements AS BackupFile,
                     _value.AttrFilePath AS BackupFilePath,
                     parse_xml(file=_value.AttrStats, accessor='data').CBackupStats AS Stats
                FROM foreach(row=Storages) WHERE _value.AttrId = StorageID
          })
          
      // Correlating OIBs with Restore Points information
      LET oibs_points = SELECT * FROM foreach(row=oibs_storages,
          query={
              SELECT MetadataFile, Backups, DisplayName, VMName, State, Type, Algorithm, HealthStatus, HasIndex, HasExchange, HasSharePoint, HasSQL, HasAD, HasOracle, HasPostgreSQL, HasVeeamArchiver, IsCorrupted, IsRecheckCorrupted, IsConsistent, NeedHealthCheckRepair, IsPartialActiveFull, ProductVersion, ProductVersionFlags, ProductIsRentalLicense, CreationTimeUTC, CompletionTimeUTC, ApproximateSize, Memory, DisksCapacity, ExtractableFilesSize, GuestOSName, GuestOSType, GuestDNSName, GuestIP, GuestToolsStatus, GuestToolsVersionStatus, VirtualType, ExtractName, ExtractID, HostName, HostInstanceID, BackupFile, BackupFilePath,
                     Stats.BackupSize AS BackupSize,
                     Stats.DataSize AS DataSize,
                     Stats.DedupRatio AS DeduplicationRatio,
                     Stats.CompressRatio AS CompressionRatio,
                     split(string=_value.AttrNum, sep='\\.')[0] AS RestorePointNumber,
                     restore_point_type[_value.AttrType] AS RestorePointType,
                     _value.AttrBackupId AS BackupID
                FROM foreach(row=RestorePoints) WHERE _value.AttrId = RestorePointID
          })
          
      // Correlating OIBs with Backups information
      LET oibs_backups = SELECT * FROM foreach(row=oibs_points,
          query={
              SELECT MetadataFile, DisplayName, VMName, State, Type, Algorithm, HealthStatus, HasIndex, HasExchange, HasSharePoint, HasSQL, HasAD, HasOracle, HasPostgreSQL, HasVeeamArchiver, IsCorrupted, IsRecheckCorrupted, IsConsistent, NeedHealthCheckRepair, IsPartialActiveFull, ProductVersion, ProductVersionFlags, ProductIsRentalLicense, CreationTimeUTC, CompletionTimeUTC, ApproximateSize, Memory, DisksCapacity, ExtractableFilesSize, GuestOSName, GuestOSType, GuestDNSName, GuestIP, GuestToolsStatus, GuestToolsVersionStatus, VirtualType, ExtractName, ExtractID, HostName, HostInstanceID, BackupFile, BackupFilePath, BackupSize, DataSize, DeduplicationRatio, CompressionRatio, RestorePointNumber, RestorePointType,
                     _value.AttrJobName AS JobName,
                     _value.AttrPolicyName AS PolicyName,
                     _value.AttrDirPath AS BackupDirectory,
                     back_enc_state[_value.AttrEncryptionState] AS BackupEncryptionState
                FROM foreach(row=Backups) WHERE _value.AttrId = BackupID
          })

       


      // ===================
      // === Final query ===
      // ===================
      
      SELECT DisplayName,
             CreationTimeUTC,
             CompletionTimeUTC,
             ApproximateSize,
             DisksCapacity,
             RestorePointNumber,
             RestorePointType,
             HostName,
             HostInstanceID,
             BackupFile,
             BackupFilePath,
             ExtractableFilesSize,
             BackupSize,
             DataSize,
             DeduplicationRatio,
             CompressionRatio,
             VirtualType,
             VMName,
             Memory,
             GuestOSName,
             GuestOSType,
             GuestDNSName,
             GuestIP,
             GuestToolsStatus,
             GuestToolsVersionStatus,
             State,
             Type,
             Algorithm,
             HealthStatus,
             HasIndex,
             HasExchange,
             HasSharePoint,
             HasSQL,
             HasAD,
             HasOracle,
             HasPostgreSQL,
             HasVeeamArchiver,
             IsCorrupted,
             IsRecheckCorrupted,
             IsConsistent,
             NeedHealthCheckRepair,
             IsPartialActiveFull,
             ProductVersion,
             ProductVersionFlags,
             ProductIsRentalLicense,
             JobName,
             PolicyName,
             BackupEncryptionState,
             BackupDirectory,
             MetadataFile,
             ExtractName,
             ExtractID
        FROM oibs_backups