Posh-VirusTotal.psm1


# .ExternalHelp Posh-VirusTotal.Help.xml
function Set-VTAPIKey
{
    [CmdletBinding()]
    Param
    (
        # VirusToral API Key.
        [Parameter(Mandatory=$true)]
        [string]$APIKey,

        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=1)]
        [securestring]$MasterPassword
    )

    Begin
    {
    }
    Process
    {
        $Global:VTAPIKey = $APIKey
        $SecureKeyString = ConvertTo-SecureString -String $APIKey -AsPlainText -Force
        $EncryptedString = $SecureKeyString | ConvertFrom-SecureString -SecureKey $MasterPassword

        $FolderName = 'Posh-VirusTotal'
        $ConfigName = 'api.key'
        
        if (!(Test-Path "$($env:AppData)\$FolderName"))
        {
            Write-Verbose -Message 'Seems this is the first time the config has been set.'
            Write-Verbose -Message "Creating folder $("$($env:AppData)\$FolderName")"
            New-Item -ItemType directory -Path "$($env:AppData)\$FolderName" | Out-Null
        }
        
        Write-Verbose -Message "Saving the information to configuration file $("$($env:AppData)\$FolderName\$ConfigName")"
        "$($EncryptedString)"  | Set-Content  "$($env:AppData)\$FolderName\$ConfigName" -Force
    }
    End
    {
    }
}

# .ExternalHelp Posh-VirusTotal.Help.xml
function Read-VTAPIKey
{
    [CmdletBinding()]

    Param
    (

        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [securestring]$MasterPassword
    )

    Begin
    {
        # Test if configuration file exists.
        if (!(Test-Path "$($env:AppData)\Posh-VirusTotal\api.key"))
        {
            throw 'Configuration has not been set, Set-VTAPIKey to configure the API Keys.'
        }
    }
    Process
    {
        Write-Verbose -Message "Reading key from $($env:AppData)\Posh-VirusTotal\api.key."
        $ConfigFileContent = Get-Content -Path "$($env:AppData)\Posh-VirusTotal\api.key"
        Write-Debug -Message "Secure string is $($ConfigFileContent)"
        $SecString = ConvertTo-SecureString -SecureKey $MasterPassword $ConfigFileContent

        # Decrypt the secure string.
        $SecureStringToBSTR = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecString)
        $APIKey = [Runtime.InteropServices.Marshal]::PtrToStringAuto($SecureStringToBSTR)

        # Set session variable with the key.
        Write-Verbose -Message "Setting key $($APIKey) to variable for use by other commands."
        $Global:VTAPIKey = $APIKey
        Write-Verbose -Message 'Key has been set.'
    }
    End
    {
    }
}

# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTIPReport
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # IP Address to scan for.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$IPAddress,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/ip-address/report'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }
    }
    Process
    {

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Body = @{'ip'= $IPAddress; 'apikey'= $APIKey}

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $IPReport = Invoke-RestMethod @Params
        
        $ErrorActionPreference = $OldEAP
        
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }

        $IPReport.pstypenames.insert(0,'VirusTotal.IP.Report')
        $IPReport
        
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTDomainReport
{
    [CmdletBinding(DefaultParametersetName = 'Direct')]
    Param
    (
        # Domain to scan.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Domain,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/domain/report'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }
    }
    Process
    {
        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Body = @{'domain'= $Domain; 'apikey'= $APIKey}

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        
        $DomainReport = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP
        
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }

        $DomainReport.pstypenames.insert(0,'VirusTotal.Domain.Report')
        $DomainReport
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTFileReport
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # File MD5 Checksum, File SHA1 Checksum, File SHA256 Checksum or ScanID to query.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [ValidateCount(1,4)]
        [string[]]$Resource,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/file/report'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }
    }
    Process
    {
        $QueryResources =  $Resource -join ','

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Body =  @{'resource'= $QueryResources; 'apikey'= $APIKey}

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }


        $ReportResult =Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP
        
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }

        foreach ($FileReport in $ReportResult)
        {
            $FileReport.pstypenames.insert(0,'VirusTotal.File.Report')
            $FileReport
        }
        
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTURLReport
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # URL or ScanID to query.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [ValidateCount(1,4)]
        [string[]]$Resource,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        # Automatically submit the URL for analysis if no report is found for it in VirusTotal.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [switch]$Scan,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/url/report'
        
        if ($Scan)
        {
            $scanurl = 1
        }
        else
        {
            $scanurl = 0
        }

        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }
    }
    Process
    {
        $QueryResources =  $Resource -join ','

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Body = @{'resource'= $QueryResources; 'apikey'= $APIKey; 'scan'=$scanurl}


        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $ReportResult = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP
        
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }

        foreach ($URLReport in $ReportResult)
        {
            $URLReport.pstypenames.insert(0,'VirusTotal.URL.Report')
            $URLReport
        }
        
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Submit-VTURL
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # URL or ScanID to query.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [ValidateCount(1,4)]
        [string[]]$URL,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        # Automatically submit the URL for analysis if no report is found for it in VirusTotal.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [switch]$Scan,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/url/scan'
        if ($Scan)
        {
            $scanurl = 1
        }
        else
        {
            $scanurl = 0
        }

        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }
    }
    Process
    {
        $URLList =  $URL -join "`n"
        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'
        
        $Body =  @{'url'= $URLList; 'apikey'= $APIKey}

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Post')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $SubmitedList = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP
        
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }

        foreach($submited in $SubmitedList)
        {
            $submited.pstypenames.insert(0,'VirusTotal.URL.Submission')
            $submited
        }
      
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Submit-VTFile
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # URL or ScanID to query.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [ValidateScript({Test-Path $_ -PathType Leaf})]
        [string]$File,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    )

    Begin
    {
        $URI = 'http://www.virustotal.com/vtapi/v2/file/scan'

        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            Write-Error 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }
    }
    Process
    {
        $fileinfo = Get-ItemProperty -Path $File

        # Check the file size
        if ($fileinfo.length -gt 64mb)
        {
            Write-Error 'VirusTotal has a limit of 64MB per file submited' -ErrorAction Stop
        }
   
        $req = [System.Net.WebRequest]::Create('http://www.virustotal.com/vtapi/v2/file/scan')
        #$req.Headers = $headers
        $req.Method = 'POST'
        $req.AllowWriteStreamBuffering = $true
        $req.SendChunked = $false
        $req.KeepAlive = $true

        # Set the Proxy values.
        if ($PSCmdlet.ParameterSetName -eq 'Proxy')
        {
            $ProxyObject = New-Object System.Net.WebProxy
            $ProxyObject.Address = [uri]$Proxy

            if ($ProxyUseDefaultCredentials)
            {
                $ProxyObject.UseDefaultCredentials = $ProxyUseDefaultCredentials
            }

            if ($ProxyCredential)
            {
                $ProxyObject.Credentials = $ProxyCredential.GetNetworkCredential()
            }

            $req.Proxy = $ProxyObject
        }

        # Set the proper headers.
        $headers = New-Object -TypeName System.Net.WebHeaderCollection

        # Prep the POST Headers for the message
        $headers.add('apikey',$apikey)
        $boundary = '----------------------------' + [DateTime]::Now.Ticks.ToString('x')
        $req.ContentType = 'multipart/form-data; boundary=' + $boundary
        [byte[]]$boundarybytes = [System.Text.Encoding]::ASCII.GetBytes("`r`n--" + $boundary + "`r`n")
        [string]$formdataTemplate = "`r`n--" + $boundary + "`r`nContent-Disposition: form-data; name=`"{0}`";`r`n`r`n{1}"
        [string]$formitem = [string]::Format($formdataTemplate, 'apikey', $apikey)
        [byte[]]$formitembytes = [System.Text.Encoding]::UTF8.GetBytes($formitem)
        [string]$headerTemplate = "Content-Disposition: form-data; name=`"{0}`"; filename=`"{1}`"`r`nContent-Type: application/octet-stream`r`n`r`n"
        [string]$header = [string]::Format($headerTemplate, 'file', (get-item $file).name)
        [byte[]]$headerbytes = [System.Text.Encoding]::UTF8.GetBytes($header)
        [string]$footerTemplate = "Content-Disposition: form-data; name=`"Upload`"`r`n`r`nSubmit Query`r`n" + $boundary + '--'
        [byte[]]$footerBytes = [System.Text.Encoding]::UTF8.GetBytes($footerTemplate)


        # Read the file and format the message
        $stream = $req.GetRequestStream()
        $rdr = new-object System.IO.FileStream($fileinfo.FullName, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read)
        [byte[]]$buffer = new-object byte[] $rdr.Length
        [int]$total = [int]$count = 0
        $stream.Write($formitembytes, 0, $formitembytes.Length)
        $stream.Write($boundarybytes, 0, $boundarybytes.Length)
        $stream.Write($headerbytes, 0,$headerbytes.Length)
        $count = $rdr.Read($buffer, 0, $buffer.Length)
        do{
            $stream.Write($buffer, 0, $count)
            $count = $rdr.Read($buffer, 0, $buffer.Length)
        }while ($count > 0)
        $stream.Write($boundarybytes, 0, $boundarybytes.Length)
        $stream.Write($footerBytes, 0, $footerBytes.Length)
        $stream.close()

        Try
        {
            # Upload the file
            $response = $req.GetResponse()

            # Read the response
            $respstream = $response.GetResponseStream()
            $sr = new-object System.IO.StreamReader $respstream
            $result = $sr.ReadToEnd()
            ConvertFrom-Json $result
        }
        Catch [Net.WebException]
        {
            if ($Error[0].ToString() -like '*403*')
            {
                Write-Error 'API key is not valid.'
            }
            elseif ($Error[0].ToString() -like '*204*')
            {
                Write-Error 'API key rate has been reached.'
            }
        }
    }
    End
    {
    }
}

# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-PoshVTVersion
 {
     [CmdletBinding()]
     [OutputType([pscustomobject])]
     Param
     ()
 
     Begin
     {
        $currentversion = ''
        $installed = Get-Module -Name 'Posh-VirusTotal' 
     }
     Process
     {
        $webClient = New-Object System.Net.WebClient
        Try
        {
            $current = Invoke-Expression  $webClient.DownloadString('https://raw.github.com/darkoperator/Posh-VirusTotal/master/Posh-VirusTotal.psd1')
            $currentversion = $current.moduleversion
        }
        Catch
        {
            Write-Warning 'Could not retrieve the current version.'
        }
        $majorver,$minorver = $currentversion.split('.')

        if ($majorver -gt $installed.Version.Major)
        {
            Write-Warning 'You are running an outdated version of the module.'
        }
        elseif ($minorver -gt $installed.Version.Minor)
        {
            Write-Warning 'You are running an outdated version of the module.'
        } 
        
        $props = @{
            InstalledVersion = "$($installed.Version)"
            CurrentVersion   = $currentversion
        }
        New-Object -TypeName psobject -Property $props
     }
     End
     {
          
     }
 }

# .ExternalHelp Posh-VirusTotal.Help.xml
 function Get-VTAPIKeyInfo
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    )

    Begin
    {
        $URI = 'http://www.virustotal.com/vtapi/v2/key/details'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }
    }
    Process
    {

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Body = @{'apikey'= $APIKey}

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $IPReport = Invoke-RestMethod @Params
        
        $ErrorActionPreference = $OldEAP
        
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }

        $IPReport.pstypenames.insert(0,'VirusTotal.IP.Report')
        $IPReport
        
    }
    End
    {
    }
}


# Private API
###############


# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTSpecialURL
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # VirusToral Private API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    )

    Begin
    {
        
        $URI = 'https://www.virustotal.com/vtapi/v2/file/scan/upload_url'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verifies as a Private API Key.'
    }
    Process
    {

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Body = @{'apikey' = $APIKey}

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }
        
        $IPReport = Invoke-RestMethod $Params

        $ErrorActionPreference = $OldEAP
        
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }

        $IPReport.pstypenames.insert(0,'VirusTotal.SpecialUploadURL')
        $IPReport
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTFileComment
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # File MD5, SHA1 or SHA256 Checksum to get comments from.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Resource,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/comments/get'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            Write-Error 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verifies as a Private API Key.'

        $Body = @{'apikey'= $APIKey}
    }
    Process
    {

        $Body.add('resource',$Resource)

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Response = Invoke-RestMethod @Params
        
        $ErrorActionPreference = $OldEAP
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                Write-Error 'API key is not valid.' -ErrorAction Stop
            }
            elseif ($RESTError.Message -like '*204*')
            {
                Write-Error 'API key rate has been reached.' -ErrorAction Stop
            }
            else
            {
                Write-Error $RESTError
            }
        }
        $Response.pstypenames.insert(0,'VirusTotal.Comment')
        $Response

    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Set-VTFileComment
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # File MD5, SHA1 or SHA256 Checksum to comment on.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Resource,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Comment,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/comments/put'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verifies as a Private API Key.'

        $Body = @{'apikey'= $APIKey}
    }
    Process
    {

        $Body.add('resource',$Resource)

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Post')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Response = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }
        $Response.pstypenames.insert(0,'VirusTotal.Comment')
        $Response

    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Set-VTFileRescan
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # File MD5 Checksum, File SHA1 Checksum, File SHA256 Checksum or ScanID to query.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Resource,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        # Date in which the rescan should be performed. If not specified the rescan will be performed immediately.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [datetime]$Date,

        # Period in days in which the file should be rescanned.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [int32]$Period,

        # Used in conjunction with period to specify the number of times the file should be rescanned.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [int32]$Repeat,

        # An URL where a POST notification should be sent when the rescan finishes.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [string]$NotifyURL,

        # Indicates if POST notifications should be sent only if the scan results differ from the previous one.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$false)]
        [bool]$NotifyChanges,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/file/rescan'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            Write-Error 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        $Body = @{'apikey'= $APIKey}

        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verifies as a Private API Key.'
    }
    Process
    {
        $Body.add('resource',$Resource)
        if ($Date)
        {
            $Body.add('date', ($Date.ToString('yyyyMMddhhmmss')))
        }

        if ($Period)
        {
            $Body.add('period', $Period)
        }

        if ($Repeat)
        {
            $Body.add('repeat', $Repeat)
        }

        if ($NotifyURL)
        {
            $Body.add('notify_url', $NotifyURL)
        }

        if ($NotifyChanges)
        {
            $Body.add('notify_changes_only', $NotifyChanges)
        }

        $Body.add('resource',$Resource)
        
        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Post')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Response = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }

        $Response.pstypenames.insert(0,'VirusTotal.ReScan')
        $Response
        
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Remove-VTFileRescan
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # File MD5 Checksum, File SHA1 Checksum, File SHA256 Checksum or ScanID to remove rescan.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Resource,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/file/rescan/delete'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            Write-Error 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        $Body = @{'apikey'= $APIKey}

        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verifies as a Private API Key.'

    }
    Process
    {

        $Body.add('resource',$Resource)

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Post')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }
        
        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'
        
        $Response = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP

        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                Write-Error 'API key is not valid.' -ErrorAction Stop
            }
            elseif ($RESTError.Message -like '*204*')
            {
                Write-Error 'API key rate has been reached.' -ErrorAction Stop
            }
            else
            {
                Write-Error $RESTError
            }
        }

        $Response.pstypenames.insert(0,'VirusTotal.ReScan')
        $Response

    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTFileScanReport
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # File MD5 Checksum, File SHA1 Checksum, File SHA256 Checksum or ScanID of the scan.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Resource,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [switch]$AllInfo,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/file/report'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        $Body = @{'apikey'= $APIKey}

        if ($AllInfo)
        {
            $Body.Add('allinfo',1)
        }

        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verified as a Private API Key.'
    }
    Process
    {

        $Body.add('resource',$Resource)
        
        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        $Response = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP
        
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                Write-Error 'API key is not valid.' -ErrorAction Stop
            }
            elseif ($RESTError.Message -like '*204*')
            {
                Write-Error 'API key rate has been reached.' -ErrorAction Stop
            }
            else
            {
                Write-Error $RESTError
            }
        }
        $Response.pstypenames.insert(0,'VirusTotal.Scan.Report')
        $Response

    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTFileBehaviourReport
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # File MD5 Checksum, File SHA1 Checksum or File SHA256 Checksum of file.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Resource,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        # File name and path to save Behaviour report as a Cuckoo JSON Dump.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Report,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials

    
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/file/behaviour'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verified as a Private API Key.'

        $Body = @{'apikey'= $APIKey}
    }
    Process
    {

        $Body.add('hash',$Resource)

        $ReportFullPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Report)
        
        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')
        $Params.Add('Outfile', $ReportFullPath)

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }
        
        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        Write-Verbose "Saving report to $($ReportFullPath)."

        $bahaviour_report = Invoke-WebRequest @Params

        $ErrorActionPreference = $OldEAP
        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTFileSample
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # File MD5 Checksum, File SHA1 Checksum or File SHA256 Checksum of file.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Resource,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        # File name and path to save sample.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position = 1)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position = 1)]
        [string]$File,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/file/download'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            Write-Error 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verified as a Private API Key.'

        $Body = @{'apikey'= $APIKey}
    }
    Process
    {

        $Body.add('hash',$Resource)

        $SampleFullPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($File)

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')
        $Params.Add('OutFile', $SampleFullPath)

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        Write-Verbose "Saving report to $($SampleFullPath)."

        $SampleResponse = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP

        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Get-VTFileNetworkTraffic
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # File MD5 Checksum, File SHA1 Checksum or File SHA256 Checksum.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Hash,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        # File name and path to save Network Traffic in PCAP format.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position = 1)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position = 1)]
        [string]$File,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials

    
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/file/network-traffic'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            throw 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verified as a Private API Key.'

        $Body = @{'apikey'= $APIKey}
    }
    Process
    {

        $Body.add('hash',$Resource)

        $NTFullPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($File)

        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')
        $Params.Add('OutFile', $NTFullPath)

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'

        

        Write-Verbose "Saving file to $($NTFullPath)."

        $NTResponse = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP

        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                throw 'API key is not valid.'
            }
            elseif ($RESTError.Message -like '*204*')
            {
                throw 'API key rate has been reached.'
            }
            else
            {
                throw $RESTError
            }
        }
    }
    End
    {
    }
}


# .ExternalHelp Posh-VirusTotal.Help.xml
function Search-VTAdvancedReversed
{
    [CmdletBinding(DefaultParameterSetName = 'Direct')]
    Param
    (
        # A search modifier compliant file search query..
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true,
            Position=0)]
        [string]$Query,

        # VirusToral API Key.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$APIKey,

        # The offset value returned by a previously issued identical query.
        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [int]$OffSet,

        [Parameter(ParameterSetName = 'Direct',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$false,
            ValueFromPipelineByPropertyName=$false)]
        [string]$CertificateThumbprint,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [string]$Proxy,
 
        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Management.Automation.PSCredential]$ProxyCredential,

        [Parameter(ParameterSetName = 'Proxy',
            Mandatory=$true,
            ValueFromPipelineByPropertyName=$true)]
        [Switch]$ProxyUseDefaultCredentials
    
    )

    Begin
    {
        $URI = 'https://www.virustotal.com/vtapi/v2/file/search'
        if (!(Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            Write-Error 'No VirusTotal API Key has been specified or set.'
        }
        elseif ((Test-Path variable:Global:VTAPIKey ) -and !($APIKey))
        {
            $APIKey = $Global:VTAPIKey
        }

        $Body = @{'apikey' = $APIKey
                'query' = $Query}
        # If an offset is provided apply it.
        if ($OffSet)
        {
            $Body.Add('offset',$OffSet)
        }
        
        Write-Verbose 'Verifying the API Key.'
        $KeyInfo = Get-VTAPIKeyInfo -APIKey $APIKey
        if ($KeyInfo.type -ne 'private')
        {
            throw 'The key provided is not a Private API Key'
        }
        Write-Verbose 'Key verifies as a Private API Key.'

    }
    Process
    {
        
        # Start building parameters for REST Method invokation.
        $Params =  @{}
        $Params.add('Body', $Body)
        $Params.add('Method', 'Get')
        $Params.add('Uri',$URI)
        $Params.Add('ErrorVariable', 'RESTError')

        # Check if connection will be made thru a proxy.
        if ($PsCmdlet.ParameterSetName -eq 'Proxy')
        {
            $Params.Add('Proxy', $Proxy)

            if ($ProxyCredential)
            {
                $Params.Add('ProxyCredential', $ProxyCredential)
            }

            if ($ProxyUseDefaultCredentials)
            {
                $Params.Add('ProxyUseDefaultCredentials', $ProxyUseDefaultCredentials)
            }
        }

        # Check if we will be doing certificate pinning by checking the certificate thumprint.
        if ($CertificateThumbprint)
        {
            $Params.Add('CertificateThumbprint', $CertificateThumbprint)
        }

        $OldEAP = $ErrorActionPreference
        $ErrorActionPreference = 'SilentlyContinue'
        
        $Response = Invoke-RestMethod @Params

        $ErrorActionPreference = $OldEAP

        if ($RESTError)
        {
            if ($RESTError.Message.Contains('403'))
            {
                Write-Error 'API key is not valid.' -ErrorAction Stop
            }
            elseif ($RESTError.Message -like '*204*')
            {
                Write-Error 'API key rate has been reached.' -ErrorAction Stop
            }
            else
            {
                Write-Error $RESTError[0]
            }
        }

        $Response.pstypenames.insert(0,'VirusTotal.Search')
        $Response

    }
    End
    {
    }
}