powershellssldecodeencode

Convert packet bytes in powershell


I'm using tshark to get packet data from pcap. I want to know the website url that the tcp.stream is connected to. The only place I can see that will have that is the certificate. If there's another place let me know, but I do now want to solve this for academic reasons.

I can manually export the certificate within wireshark following http://darenmatthews.com/blog/?p=2036 "Right-click on the on the certificate that you wish to obtain then choose “Export selected packet bytes…” and name the file with a .der extension."

From https://www.c-amie.co.uk/technical/powershell-convert-der-encoded-certificate-file-into-a-base64-cer/ I modified to just present the details. No need to automate writing files just to read them with -Encoding Byte.

function CertTextDetail ($certtext=$null) {
  if($certtext -ne $null) {
  $bytes = [System.Text.Encoding]::UTF8.GetBytes($certtext)
  $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($bytes)
  $cert |select * ; $cert.Dispose()
}}

CertTextDetail $content
    
Subject      : CN=go.microsoft.com, O=Microsoft Corporation, L=Redmond, S=WA, C=US
Issuer       : CN=Microsoft Azure RSA TLS Issuing CA 04, O=Microsoft Corporation, C=US
Thumbprint   : 770170500D521B1E6647DF0949BDC0480613ED80
FriendlyName :
NotBefore    : 9/25/2023 12:26:11 PM
NotAfter     : 9/19/2024 12:26:11 PM
Extensions   : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid,
               System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...}

I see that tshark's first certificate (separated by a comma from intermediate and root certs) tls.handshake.certificate is in raw format and is the exact same data as I see within wireshark's view packet data. I even did a copy packet bytes into CertTextDetail function and got results. Originally was in ansii encoding. Show packet bytes

.\tshark.exe -r "C:\Users\kirt_\Downloads\packetCapture1.pcapng" -T fields -E separator="," -E header='y' -E quote=d -e ip.src -e ip.dst -e _ws.col.Protocol -e frame.time -e frame.number -e _ws.col.Info -e tcp.stream -e frame.time_relative -e frame.len -e tls.handshake.certificate |foreach {$_.replace(' "',' `').replace('" ','` ')}  | convertfrom-csv | where frame.number -eq 1464  | foreach { $_.'tls.handshake.certificate' -split(',') | select -First 1}

308208a53082068da003020......

(note: You have to clean up any quotes within _ws.col.Info or the csv will have bad data from frames with embedded double quotes before convertfrom-csv)

I need to properly convert, encode or decode tshark's tls.handshake.certificate from raw to ansii to match the .DER file so I can use the [System.Security.Cryptography.X509Certificates.X509Certificate2]::new function and retrieve the cert details.

I spent hours looking for a [system..]::method to do this, but if not done right it doesn't produce the MII... we all know and love.

-----BEGIN CERTIFICATE-----
MIIIpTCCBo..

Please help me with the proper method to alter, encode, decode the raw format to ansii.


Solution

  • The output from tshark is hexadecimally encoded - interpret each 2 chars as a byte and you'll get the value you're looking for:

    $rawCertHexString = "308208a53082068da00302" # truncated for this demonstration
    
    [byte[]]$certData = for ($i = 0; $i -lt $rawCertHexString.Length; $i += 2) {
      $byteString = $rawCertHexString.Substring($i, 2)
      # let powershell re-parse number as hexadecimal numeric literal
      +"0x$byteString"
    }
    

    Converting the resulting byte stream to base64 reveals the certificate structure is already encoded correctly:

    PS ~> [convert]::ToBase64String($certData)
    MIIIpTCCBo2gAwI=
    

    But there's no need to convert it to base64 if you intend to use the certificate data from within PowerShell - you can pass the raw certificate data directly to the [X509Certificate2] constructor:

    $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($certData)