Windows.Vhdx.RemapConfigBuilder

Create remapping configuration YAML file(s) to virtually mount
VHDX profiles into virtual Velociraptor clients.

This artifact is part of the Vhdx Suite. This suite requires to have the Velociraptor server artifact Windows.Sys.Users override on the server to work properly.

Read the dedicated blog post before using this artifact.


  name: Windows.Vhdx.RemapConfigBuilder
  description: |
    Create remapping configuration YAML file(s) to virtually mount  
    VHDX profiles into virtual Velociraptor clients.
    
    This artifact is part of the Vhdx Suite. This suite requires to have 
    the Velociraptor server artifact `Windows.Sys.Users` override on the 
    server to work properly.

    Read the dedicated blog post before using this artifact.

  author: Yann Malherbe - @mirwitch

  reference: 
    - https://labs.infoguard.ch/posts/automation_of_vhdx_investigations/

  type: CLIENT

  implied_permissions:
    - FILESYSTEM_WRITE

  parameters:
    - name: vhdxFolderPath
      type: string
      default: "F:\\vhdx\\"
      description: "Directory containing VHDX profile files."

    - name: usernameExtractor
      type: regex
      default: "profile_(?<Username>.*).vhdx"
      description: "Regex used to extract usernames from filenames."

    - name: user
      type: regex
      default: Administrator
      description: "Optional filter to restrict which profiles to process."

    - name: virtualHostname
      type: string
      default: "VHDX"
      description: "Hostname to assign to the virtual clients."

    - name: vhdxOffset
      type: hidden
      default: 1048576
      description: "NTFS start offset inside VHDX."
      
    - name: batchSize
      type: int
      default: 30
      description: "Number of profiles per virtual client." 

  sources:
    - precondition:
        SELECT OS From info() where OS = 'windows'

      query: |
          // Static remapping header
          LET RemappingHeader =''' 
          remappings:
          - type: permissions
            permissions:
            - COLLECT_CLIENT
            - FILESYSTEM_READ
            - FILESYSTEM_WRITE
            - READ_RESULTS
            - MACHINE_STATE
            - SERVER_ADMIN
          - type: impersonation
            os: windows
            hostname: "<VIRTUAL_HOSTNAME>"
            env:
            - key: SystemRoot
              value: C:\Windows
            - key: WinDir
              value: C:\Windows
            disabled_functions:
            - amsi
            - lookupSID
            - token
            disabled_plugins:
            - users
            - certificates
            - handles
            - pslist
            - interfaces
            - modules
            - netstat
            - partitions
            - proc_dump
            - proc_yara
            - vad
            - winobj
            - wmi
          
          - type: shadow
            from:
              accessor: data
            "on":
              accessor: data
          
          - type: shadow
            from:
              accessor: raw_reg
            "on":
              accessor: raw_reg
          
          - type: shadow
            from:
              accessor: zip
            "on":
              accessor: zip
          '''
          
          // Remapping required per user
          LET RemappingUser = '''
          - type: mount
            description: 'NTFS - <USERNAME>'
            from:
              accessor: raw_ntfs
              prefix: |
                {
                  "DelegateAccessor": "offset",
                  "Delegate": {
                    "DelegateAccessor": "vhdx",
                    "DelegatePath": "<VHDX_PATH>",
                    "Path":"/<VHDX_OFFSET>"
                  },
                  "Path": "<PROFILE_PATH>"
                }
            "on":
              accessor: ntfs
              prefix: '\\.\C:\Users\<USERNAME>'
              path_type: ntfs
          
          - type: mount
            description: 'File - <USERNAME>'
            from:
              accessor: raw_ntfs
              prefix: |
                {
                  "DelegateAccessor": "offset",
                  "Delegate": {
                    "DelegateAccessor": "vhdx",
                    "DelegatePath": "<VHDX_PATH>",
                    "Path":"/<VHDX_OFFSET>"
                  },
                  "Path": "<PROFILE_PATH>"
                }
            "on":
              accessor: file
              prefix: 'C:\Users\<USERNAME>'
              path_type: windows
          
          - type: mount
            description: 'Auto - <USERNAME>'
            from:
              accessor: raw_ntfs
              prefix: |
                {
                  "DelegateAccessor": "offset",
                  "Delegate": {
                    "DelegateAccessor": "vhdx",
                    "DelegatePath": "<VHDX_PATH>",
                    "Path":"/<VHDX_OFFSET>"
                  },
                  "Path": "<PROFILE_PATH>"
                }
            "on":
              accessor: auto
              prefix: 'C:\Users\<USERNAME>'
              path_type: windows
          
          - type: mount
            description: 'Registry - <USERNAME> NTUSER.DAT'
            from:
              accessor: raw_reg
              prefix: |-
                {
                  "Path": "/",
                  "DelegateAccessor": "raw_ntfs",
                  "Delegate": {
                    "DelegateAccessor":"offset",
                    "Delegate": {
                      "DelegateAccessor": "vhdx",
                      "DelegatePath": "<VHDX_PATH>",
                      "Path": "/<VHDX_OFFSET>"
                    },
                    "Path":"<PROFILE_PATH>/NTUSER.DAT"
                  }
                }
              path_type: registry
            "on":
              accessor: registry
              prefix: HKEY_USERS\<USERNAME>
              path_type: registry  
          
          - type: mount
            description: 'Registry - <USERNAME> UsrClass'
            from:
              accessor: raw_reg
              prefix: |-
                {
                  "Path": "/",
                  "DelegateAccessor": "raw_ntfs",
                  "Delegate": {
                    "DelegateAccessor":"offset",
                    "Delegate": {
                      "DelegateAccessor": "vhdx",
                      "DelegatePath": "<VHDX_PATH>",
                      "Path": "/<VHDX_OFFSET>"
                    },
                    "Path":"<PROFILE_PATH>/AppData/Local/Microsoft/Windows/UsrClass.dat"
                  }
                }
              path_type: registry
            "on":
              accessor: registry
              prefix: HKEY_USERS\<USERNAME>_Classes
              path_type: registry
          '''

          // Get the list of user profiles of interest
          LET userProfilesList = SELECT *,
                  parse_string_with_regex(
                      string=Name, 
                      regex=usernameExtractor
                  ) AS userProfile 
              FROM glob(globs=vhdxFolderPath+"/*.vhdx") 
              WHERE userProfile.Username AND userProfile.Username =~ user
              
              
          // Split the user list into batches
          LET userBatch = SELECT rows AS user_batch 
              FROM batch(query={
                SELECT *
                FROM userProfilesList
              }, batch_size=batchSize)


          // Create the header of the remapping file
          LET HeaderRemapping = regex_replace(re="<VIRTUAL_HOSTNAME>", 
                                              replace=virtualHostname + "_" + firstBatchUser, 
                                              source=RemappingHeader)
          
          // Create the user sections of the remapping file
          LET UserRemapping = SELECT
                  regex_replace(re="<USERNAME>", 
                      replace=userProfile.Username, source= 
                  regex_replace(re="<PROFILE_PATH>", 
                      replace="/Profile", source= 
                  regex_replace(re="<VHDX_OFFSET>", 
                      replace=vhdxOffset, source=
                  regex_replace(re="<VHDX_PATH>", 
                      replace=regex_replace(
                          re="\\\\", replace="/", source=OSPath), 
                  source=RemappingUser)
                  ))) AS Content
              FROM scope()
              
          // Iterate on the users part of the bulk
          LET BulkUserRemapping = SELECT * FROM foreach(
              row=user_batch,
              query=UserRemapping
              )
          
          // Write the remapping content in a temp file
          LET tmpFile = tempfile(
                      data=HeaderRemapping + BulkUserRemapping.Content, 
                      remove_last=TRUE
                  )
              
          // Retrieve the directory from the running Velociraptor executable
          LET veloInfo = SELECT Exe FROM info()

          // Get the first user of the batch
          LET firstBatchUser = user_batch[0].userProfile.Username

          // Get the remapping filename
          LET remappingFilename = firstBatchUser + ".yaml"
          
          // Copy the file to the remapping YAML file
          LET copyFile = SELECT copy(
                  filename=tmpFile, 
                  dest=pathspec(parse=veloInfo[0].Exe).Dirname + "Vhdx" + "Remapping" + remappingFilename,
                  create_directories=TRUE) AS CreatedConfig
              FROM scope()



          // Create dedicated YAML file for each batch of users
          SELECT * FROM foreach(row=userBatch, query=copyFile)