functions/Get-XdrEndpointDeviceLiveResponseLibraryFile.ps1
|
function Get-XdrEndpointDeviceLiveResponseLibraryFile { <# .SYNOPSIS Downloads a script file from the Live Response library. .DESCRIPTION Retrieves the content of a specific file from the Microsoft Defender XDR Live Response library. Accepts pipeline input from Get-XdrEndpointDeviceLiveResponseLibrary. If -OutputPath is specified, the file is saved to disk. Otherwise the decoded content is returned as a string. .PARAMETER FileName The name of the file to download from the library (e.g. 'PasskeyLogin.ps1'). Accepts ValueFromPipelineByPropertyName, so objects from Get-XdrEndpointDeviceLiveResponseLibrary pipe directly using the file_name property. .PARAMETER OutputPath Optional file path to save the downloaded content. If omitted, the content is returned as a string. .EXAMPLE Get-XdrEndpointDeviceLiveResponseLibraryFile -FileName 'PasskeyLogin.ps1' Returns the content of PasskeyLogin.ps1 as a string. .EXAMPLE Get-XdrEndpointDeviceLiveResponseLibraryFile -FileName 'PasskeyLogin.ps1' -OutputPath 'C:\Temp\PasskeyLogin.ps1' Downloads and saves the file to disk. .EXAMPLE Get-XdrEndpointDeviceLiveResponseLibrary | Where-Object file_name -eq 'PasskeyLogin.ps1' | Get-XdrEndpointDeviceLiveResponseLibraryFile Downloads a library file using pipeline input. .OUTPUTS System.String Returns the file content as a string when no OutputPath is specified. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('file_name')] [string]$FileName, [Parameter()] [string]$OutputPath ) begin { Update-XdrConnectionSettings } process { try { $Uri = "https://security.microsoft.com/apiproxy/mtp/liveResponseApi/library/download_file?file_name=$([System.Uri]::EscapeDataString($FileName))" Write-Verbose "Downloading '$FileName' from Live Response library" $response = Invoke-WebRequest -Uri $Uri -Method Get -WebSession $script:session -Headers $script:headers # Read raw bytes from the response stream; the API serves files as application/octet-stream $responseBytes = $response.RawContentStream.ToArray() # Try base64 decode first (HAR shows the proxy may return base64-encoded content); # fall back to treating the raw bytes directly as UTF-8 text $content = $null try { $rawString = [System.Text.Encoding]::ASCII.GetString($responseBytes).Trim() $decodedBytes = [System.Convert]::FromBase64String($rawString) $content = [System.Text.Encoding]::UTF8.GetString($decodedBytes) } catch { # Not base64 — raw bytes are the file content (e.g. text served directly) $content = [System.Text.Encoding]::UTF8.GetString($responseBytes) } if ($OutputPath) { [System.IO.File]::WriteAllText($OutputPath, $content, [System.Text.Encoding]::UTF8) Write-Verbose "Saved '$FileName' to '$OutputPath'" } else { return $content } } catch { Write-Error "Failed to download '$FileName' from Live Response library: $_" } } end { } } |