Skip to content
Please update to the latest release 0.77.2 to address Multiple CVEs.
Encrypt and decrypt an offline collector using PGP public and private keys

Encrypt and decrypt an offline collector using PGP public and private keys

Velociraptor supports three modes for encrypting Offline Collectors: Password, X.509 Secured, and PGP-secured (as described here). While X.509 is the standard for automatic server imports, using PGP is a great alternative when you need to decrypt collections independently of the Velociraptor Server.

The PGP Encryption Workflow: When using PGP, Velociraptor follows a “hybrid” encryption approach:

  1. Generation: Velociraptor generates a high-entropy random password.
  2. Encryption: The collected data is encrypted with this password.
  3. Envelope: The password itself is encrypted using your PGP Public Key and stored in the metadata.
  4. Decryption: To access the data, you must first decrypt the password using your PGP Private Key, then decompress the protected zip using the password.

Step 1: Generate a PGP key-pair

First, generate an RSA key-pair. We will use a batch file for automation, but you can also do this interactively.

gpg --batch --generate-key <<EOF
    Key-Type: RSA
    Key-Length: 3072
    Subkey-Type: RSA
    Subkey-Length: 3072
    Name-Real: Ilo
    Name-Email: ilo@test.com
    Expire-Date: 1y
    %no-protection
    %commit
EOF

# Export the public key for use in the collector
gpg --armor --export ilo@test.com > key.pub

Step 2: Configure the Collector Spec

The easiest way to build the Offline Collector is in the GUI. This approach will generate a Velociraptor Offline Collector and a spec.yaml.

The following will show how to build the offline collector using CLI:

  1. Setup a datastore location
  2. Setup a artifact location (only needed if external artifacts will be used)
  3. Create a template-spec.yaml
  4. Create the Velociraptor Offline Collector

Prepare the CLI environment

mkdir datastore artifacts

# Download reference artifacts and the Velociraptor binary
wget https://triage.velocidex.com/artifacts/Velociraptor_Triage_v0.1.zip -P artifacts
7z x artifacts/Velociraptor_Triage_v0.1.zip -oartifacts
wget https://github.com/Velocidex/velociraptor/releases/download/v0.75/velociraptor-v0.75.6-linux-amd64
chmod +x velociraptor-v0.75.6-linux-amd64

# Generate a base template
./velociraptor-v0.75.6-linux-amd64 collector > template-spec.yaml

Update template-spec.yaml

Edit your YAML file to include your public key in the field public_key. Ensure the EncryptionScheme is set to PGP.

OS: Windows
Artifacts:
 Windows.Triage.Targets:
   HighLevelTargets: '["_SANS_Triage", "_KapeTriage"]'
   Devices: '["C:","D:","E:"]'
Target: ZIP
EncryptionScheme: PGP
EncryptionArgs:
  public_key: |-
    -----BEGIN PGP PUBLIC KEY BLOCK-----

    REDACTED...
    -----END PGP PUBLIC KEY BLOCK-----
  password: ""
OptVerbose: Y
OptBanner: Y
OptPrompt: N
OptAdmin: Y
OptTempdir: ""
OptLevel: 9
OptConcurrency: 2
OptFilenameTemplate: "Collection-%Hostname%-%TIMESTAMP%"
OptCollectorTemplate: ""
OptFormat: jsonl
OptOutputDirectory: ""
OptCpuLimit: 0
OptProgressTimeout: 1800
OptTimeout: 0
OptVersion: ""
OptDeleteAtExit: N

Step 3: Build the Offline Collector

Run the following command to “repack” the Velociraptor binary into a standalone collector based on your spec.

./velociraptor-v0.75.6-linux-amd64 collector --datastore datastore --definitions artifacts template-spec.yaml

[
 {
  "Repacked": {
   "Path": "/REDACTED/datastore/Collector_velociraptor-v0.75.6-windows-amd64.exe",
   "Size": 87421951,
   "UploadId": 0,
   "sha256": "f1487b5686c9616def5c55cd32266b4726162758456d7f5149ebfde51bc3a582",
   "md5": "d46f704b4014dd7a76fa2847b21f813e",
   "Components": [
    "Collector_velociraptor-v0.75.6-windows-amd64.exe"
   ]
  },
  "_Source": "Server.Utils.CreateCollector"
 }
]

Step 4: Decrypt the Results

The Velociraptor Offline Collector will generate a Collector.zip file. The file structure within the container is documented as described here:

  • data.zip
  • metadata.json

Within the metadata.json file you fill find the encrypted password in the EncryptedPass entry:

[
 {
  "EncryptedPass": "REDACTED",
  "Scheme": "PGP",
  "PublicKey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nREDACTED\n-----END PGP PUBLIC KEY BLOCK-----"
 }
]

You can decrypt the password and the data using the following commands:

# 1. Extract the encrypted pass from metadata
# 2. Base64 decode it
# 3. Decrypt with GPG
# 4. Use the result as the password for the data zip
PASS=$(7z e -so Collection.zip metadata.json | jq -r '.[].EncryptedPass' | base64 -d | gpg --decrypt)
7z x Collection.zip "-p$PASS" -y

This assumes that the private key is in your gpg vault.

Working with the data

Working with the Offline Collection data is described here