Windows.Veeam.RestorePoints.BackupFiles

Parses the metadata found in Veeam full backup files (.vbk), Veeam incremental backup files (.vib) and Veeam reverse incremental backup files (.vrb) to extract relevant fields for each Restore Point.

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


name: Windows.Veeam.RestorePoints.BackupFiles

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

author: Synacktiv, Maxence Fossat - @cybiosity

type: CLIENT

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

parameters:
  - name: BackupRepositories
    description: List of Backup Repositories where ".vbk", ".vib" and ".vrb" 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.Attrdisk_id AS _key,
                 disk_info.Attrcapacity AS _value
            FROM Disks
      })
      
      // 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 capacity for COibAuxDataVmware
      LET vmware_disk_capacity(Disks) = to_dict(item= {
          SELECT `Uuid` AS _key,
                 Capacity AS _value
            FROM Disks
      })
      
      // Function to format OibFiles
      LET oib_files_size(Files) = to_dict(item= {
          SELECT AttrFileName AS _key,
                 AttrSize AS _value
            FROM Files
      })
      
      // 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 ====
      // ========================
      
      LET MetadataStart <= '''
      rule StartOffsetRule {
          strings:
              $start = "<OibSummary>"
          condition: any of them
      }
      '''
      LET MetadataEnd <= '''
      rule EndOffsetRule {
          strings:
              $end = "</OibSummary>"
          condition: any of them
      }
      '''
      
      // Listing all Storage files in the Backup Repositories
      LET backup_repos = SELECT BackupRepoPath FROM BackupRepositories
      LET backup_files = SELECT * FROM foreach(row=backup_repos,
          query={
              SELECT *
                FROM glob(
                    globs=[
                        '/**/*.vbk',
                        '/**/*.vib',
                        '/**/*.vrb'
                    ],
                    root=BackupRepoPath,
                    accessor='file'
                )
          })
      
      // Find last start offset of metadata for each Storage file
      LET start_offsets= SELECT File.FullPath AS FilePath,
             max(item=String.Offset) AS StartOffset
        FROM yara(
            files=backup_files.OSPath,
            rules=MetadataStart,
            start=0,
            end=18446744073709551615,
            number=100
        )
        GROUP BY File.FullPath
        
      // Find end offset for each start offset, extract and parse XML
      LET xml = SELECT parse_xml(
          accessor='data',
          file=read_file(
              filename=BackupFilePath,
              offset=StartOffset,
              length=EndOffset - StartOffset + 13
          )
      ) AS Metadata,
      BackupFilePath
        FROM foreach(row=start_offsets,
        query={
            SELECT File.FullPath AS BackupFilePath,
                   StartOffset,
                   String.Offset + StartOffset AS EndOffset
              FROM yara(
                  files=pathspec(
                      DelegateAccessor='file',
                      DelegatePath=FilePath,
                      Path=str(str=StartOffset)
                  ),
                  accessor='offset',
                  rules=MetadataEnd,
                  end=20971520,
                  number=1
              )
        })
        WHERE Metadata

      // =========================      
      // === Objects In Backup ===
      // =========================

      // Extracting interesting fields from OIB, OibFiles, Object, SourceHost, Storage, Point and Backup
      LET oib = SELECT BackupFilePath, 
              Metadata.OibSummary.OIB.AttrDisplayName AS DisplayName,
              Metadata.OibSummary.OIB.AttrVmName AS VMName,
              Metadata.OibSummary.OIB.AttrState AS State,
              Metadata.OibSummary.OIB.AttrType AS Type,
              Metadata.OibSummary.OIB.AttrAlgorithm AS Algorithm,
              Metadata.OibSummary.OIB.AttrHealthStatus AS HealthStatus,
              Metadata.OibSummary.OIB.AttrHasIndex AS HasIndex,
              Metadata.OibSummary.OIB.AttrHasExchange AS HasExchange,
              Metadata.OibSummary.OIB.AttrHasSharePoint AS HasSharePoint,
              Metadata.OibSummary.OIB.AttrHasSql AS HasSQL,
              Metadata.OibSummary.OIB.AttrHasAd AS HasAD,
              Metadata.OibSummary.OIB.AttrHasOracle AS HasOracle,
              Metadata.OibSummary.OIB.AttrHasPostgreSql AS HasPostgreSQL,
              Metadata.OibSummary.OIB.AttrHasVeeamArchiver AS HasVeeamArchiver,
              Metadata.OibSummary.OIB.AttrIsCorrupted AS IsCorrupted,
              Metadata.OibSummary.OIB.AttrIsRecheckCorrupted AS IsRecheckCorrupted,
              Metadata.OibSummary.OIB.AttrIsConsistent AS IsConsistent,
              Metadata.OibSummary.OIB.AttrIsPartialActiveFull AS IsPartialActiveFull,
              Metadata.OibSummary.OIB.AttrProductVersion AS ProductVersion,
              Metadata.OibSummary.OIB.AttrProductVersionFlags AS ProductVersionFlags,
              Metadata.OibSummary.OIB.AttrProductIsRentalLicense AS ProductIsRentalLicense,
              Metadata.OibSummary.SourceHost.AttrName AS HostName,
              Metadata.OibSummary.SourceHost.AttrHostInstanceId AS HostInstanceID,
              Metadata.OibSummary.Backup.AttrJobName AS JobName,
              Metadata.OibSummary.Backup.AttrPolicyName AS PolicyName,
              Metadata.OibSummary.PrevFileName AS PreviousFileInChain,
              back_enc_state[Metadata.OibSummary.Backup.AttrEncryptionState] AS BackupEncryptionState,
              Metadata.OibSummary.OIB.AttrEffectiveMemoryMb AS TempMemory,
              Metadata.OibSummary.Object.AttrViType || 'Physical machine' AS VirtualType,
              Metadata.OibSummary.Object.AttrName AS ExtractName,
              Metadata.OibSummary.Object.AttrObjectId AS ExtractID,
              oib_files_size(Files=Metadata.OibSummary.OibFiles.File) AS ExtractableFilesSize,
              parse_xml(file=Metadata.OibSummary.Storage.AttrPartialPath, accessor='data').Path.Elements AS BackupFile,
              timestamp(string=Metadata.OibSummary.OIB.AttrCreationTimeUtc) AS CreationTimeUTC,
              timestamp(string=Metadata.OibSummary.OIB.AttrCompletionTimeUtc) AS CompletionTimeUTC,
              humanize(bytes=int(int=Metadata.OibSummary.OIB.AttrApproxSize)) AS ApproximateSize,
              split(string=Metadata.OibSummary.Point.AttrNum, sep='\\.')[0] AS RestorePointNumber,
              restore_point_type[Metadata.OibSummary.Point.AttrType] AS RestorePointType,
              parse_xml(file=Metadata.OibSummary.Storage.`#text`, accessor='data').CBackupStats AS Stats,
              parse_xml(file=Metadata.OibSummary.OIB.AttrAuxData, accessor='data').COibAuxData AS AuxData,
              format_properties(
                  Properties = parse_xml(file=Metadata.OibSummary.OIB.`#text`, accessor='data').GuestInfo.Property
              ) AS GuestInfo
        FROM xml
      
      // Expanding relevant fields into subfields
      LET expand_oib = SELECT BackupFilePath, DisplayName, VMName, State, Type, Algorithm, HealthStatus, HasIndex, HasExchange, HasSharePoint, HasSQL, HasAD, HasOracle, HasPostgreSQL, HasVeeamArchiver, IsCorrupted, IsRecheckCorrupted, IsConsistent, IsPartialActiveFull, ProductVersion, ProductVersionFlags, ProductIsRentalLicense, HostName, HostInstanceID, JobName, PolicyName, PreviousFileInChain, BackupEncryptionState, VirtualType, ExtractName, ExtractID, ExtractableFilesSize, BackupFile, CreationTimeUTC, CompletionTimeUTC, ApproximateSize, RestorePointNumber, RestorePointType,
              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,
              GuestInfo.GuestOsName AS GuestOSName,
              GuestInfo.GuestOsType AS GuestOSType,
              GuestInfo.DnsName AS GuestDNSName,
              GuestInfo.`Ip` AS GuestIP,
              GuestInfo.ToolsStatus AS GuestToolsStatus,
              GuestInfo.ToolsVersionStatus AS GuestToolsVersionStatus,
              Stats.BackupSize AS BackupSize,
              Stats.DataSize AS DataSize,
              Stats.DedupRatio AS DeduplicationRatio,
              Stats.CompressRatio AS CompressionRatio
        FROM oib
        
      // ===================
      // === 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,
             IsPartialActiveFull,
             ProductVersion,
             ProductVersionFlags,
             ProductIsRentalLicense,
             JobName,
             PolicyName,
             BackupEncryptionState,
             PreviousFileInChain,
             ExtractName,
             ExtractID
        FROM expand_oib