====== xcert.rb : Print certificate chain for all SSL connections in capture file ====== Scans the // Server Certificate // sent as part of the SSL/TLS handshake and prints the certificate chain. This sample script demonstrates - Working with the Ruby Enumerable [[unsniff:objectref:collectionobj|wrapper]] - Searching for subfields - Working with name value pair fields ===== Sample output ===== C:\Users\Tom Wilson\Documents\unsniff>ruby xcert.rb may1112S2.usnf Certificate chain for 212.149.50.181 to 192.168.1.5 www.commerzbanking.de (Commerzbank AG) TC TrustCenter Class 4 Extended Validation CA II (TC TrustCenter GmbH) TC TrustCenter Class 4 Extended Validation CA II (TC TrustCenter GmbH) Cybertrust Global Root (Cybertrust, Inc) Cybertrust Global Root (Cybertrust, Inc) GTE CyberTrust Global Root (GTE Corporation) Certificate chain for 174.137.42.65 to 192.168.1.5 www.wireshark.org () PositiveSSL CA (Comodo CA Limited) PositiveSSL CA (Comodo CA Limited) UTN-USERFirst-Hardware (The USERTRUST Network) UTN-USERFirst-Hardware (The USERTRUST Network) AddTrust External CA Root (AddTrust AB) ===== Ruby code ===== #---------------------------------------------------------- # xcert - Cert stacks of all TLS sessions in capture file # # usage: xcert # #--------------------------------------------------------- require 'win32ole' raise "xcert " unless ARGV.length ==1 UnsniffDB = WIN32OLE.new("Unsniff.Database") UnsniffDB.OpenForRead(ARGV[0]) # enumerable helper class UWrap include Enumerable def initialize(w) @wrapped=w end def each(&block) @wrapped.each { |m| block.call(m) } end end # print cert stack of each cerficate pdu UnsniffDB.PDUIndex.each do |pdu| next unless pdu.Description =~ /Server Certificate/ print "\nCertificate chain for " + pdu.SenderAddress + " to " + pdu.ReceiverAddress + "\n" handshake = UWrap.new(pdu.Fields).find do |f| hst = f.FindField("Handshake Type") hst and hst.Value() == "11 (certificate)" end next unless handshake certstack = handshake.FindField("Certificate") certs = UWrap.new(certstack.SubFields).select { |f| f.Name == "ASN.1Cert" } indent = 4 certs.each do |cert| subject = cert.FindField("subject") issuer = cert.FindField("issuer") sub,iss = {},{} [ [subject, sub], [issuer, iss] ].each do |a| a[0].SubFields.each do |rdn| case rdn.FindField("type").Value when /commonName/ a[1][:cn]=rdn.FindField("DirectoryString").Value ; when /organizationName/ a[1][:on]=rdn.FindField("DirectoryString").Value ; end end end print " "*indent + "#{sub[:cn]} (#{sub[:on]})\n" print " "*(indent+1) + "#{iss[:cn]} (#{iss[:on]})\n" indent = indent + 1 end end UnsniffDB.Close