PURPOSE:
- Automated discovery and analysis of Widevine DRM services
- TLS certificate inspection and validation
- Service endpoint mapping and probing
- Security configuration assessment
FEATURES:
• Certificate chain analysis (Subject, Issuer, Expiry, Thumbprint)
• TLS version support testing (TLS 1.0-1.3, SSL 3.0)
• Service endpoint discovery (License, Provisioning, Status)
• Binary protocol handshake testing
• Comprehensive JSON output format
USAGE:
# Basic discovery scan
$results = Invoke-WidevineDiscovery -TargetIP "192.168.1.100" -Port 8443
# Export results to file
$results | ConvertTo-Json -Depth 5 | Out-File "widevine_scan.json"
REQUIREMENTS:
• PowerShell 5.1+
• Network access to target service
• No additional dependencies
Show ContentSpoiler:
Code:
function Invoke-WidevineDiscovery {
param([string]$TargetIP, [int]$Port = 8443)
$results = @{}
$certInfo = Get-WidevineCertificate -TargetIP $TargetIP -Port $Port
$tlsInfo = Test-TLSVersions -TargetIP $TargetIP -Port $Port
$serviceProbes = Invoke-ServiceProbes -TargetIP $TargetIP -Port $Port
return @{Certificate = $certInfo; TLS = $tlsInfo; Probes = $serviceProbes}
}
function Get-WidevineCertificate {
param($TargetIP, $Port)
try {
$tcpClient = New-Object System.Net.Sockets.TcpClient($TargetIP, $Port)
$sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream(), $false, {$true})
$sslStream.AuthenticateAsClient($TargetIP)
$cert = $sslStream.RemoteCertificate
$certObj = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($cert)
$sslStream.Close()
$tcpClient.Close()
return @{
Subject = $certObj.Subject
Issuer = $certObj.Issuer
Thumbprint = $certObj.Thumbprint
Expiry = $certObj.NotAfter
}
}
catch {
return @{Error = $_.Exception.Message}
}
}
function Test-TLSVersions {
param($TargetIP, $Port)
$tlsResults = @{}
$versions = @("Tls12", "Tls11", "Tls", "Ssl3")
foreach ($version in $versions) {
try {
$tcpClient = New-Object System.Net.Sockets.TcpClient($TargetIP, $Port)
$sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream(), $false, {$true})
$sslProtocol = [System.Security.Authentication.SslProtocols]::$version
$sslStream.AuthenticateAsClient($TargetIP, $null, $sslProtocol, $false)
$tlsResults[$version] = @{
Supported = $true
Cipher = $sslStream.CipherAlgorithm
Strength = $sslStream.CipherStrength
}
$sslStream.Close()
$tcpClient.Close()
}
catch {
$tlsResults[$version] = @{Supported = $false}
}
}
return $tlsResults
}
function Invoke-ServiceProbes {
param($TargetIP, $Port)
$probeResults = @{}
$probes = @(
@{Name = "LicenseEndpoint"; Data = "GET /license HTTP/1.1`r`nHost: $TargetIP`r`nConnection: close`r`n`r`n"},
@{Name = "Provisioning"; Data = "GET /provisioning HTTP/1.1`r`nHost: $TargetIP`r`nConnection: close`r`n`r`n"},
@{Name = "BinaryHandshake"; Data = [byte[]]@(0x00,0x00,0x00,0x08,0x57,0x56,0x00,0x01)}
)
foreach ($probe in $probes) {
try {
$tcpClient = New-Object System.Net.Sockets.TcpClient($TargetIP, $Port)
$sslStream = New-Object System.Net.Security.SslStream($tcpClient.GetStream(), $false, {$true})
$sslStream.AuthenticateAsClient($TargetIP)
if ($probe.Data -is [string]) {
$data = [System.Text.Encoding]::ASCII.GetBytes($probe.Data)
} else {
$data = $probe.Data
}
$sslStream.Write($data, 0, $data.Length)
$sslStream.Flush()
Start-Sleep -Milliseconds 1000
$buffer = New-Object byte[] 4096
if ($sslStream.DataAvailable) {
$bytesRead = $sslStream.Read($buffer, 0, $buffer.Length)
$probeResults[$probe.Name] = @{Response = $bytesRead; Data = $buffer[0..($bytesRead-1)]}
} else {
$probeResults[$probe.Name] = @{Response = "NoData"}
}
$sslStream.Close()
$tcpClient.Close()
}
catch {
$probeResults[$probe.Name] = @{Error = $_.Exception.Message}
}
}
return $probeResults
}
SAMPLE OUTPUT:
Show ContentSpoiler:
{
"Certificate": {
"Subject": "CN=Widevine_Service",
"Issuer": "CN=Google_Widevine_CA",
"Expiry": "2024-03-06T17:28:06",
"Thumbprint": "A03CA1510E1444A3E4751BF23B631A223B95E827"
},
"TLS": {
"Tls12": {"Supported": true, "Cipher": "Aes128", "Strength": 128}
},
"Probes": {
"LicenseEndpoint": {"Response": "NoData"},
"BinaryHandshake": {"Response": 1024}
}
}