Obtendo programaticamente os detalhes do certificado de um executável

Obtendo programaticamente os detalhes do certificado de um executável

É possível exportar de alguma forma programaticamente o assunto do certificado digital de um arquivo se o certificado em si não estiver instalado na estação de trabalho, mas for usado apenas para assinar aquele arquivo específico?

Preciso extrair de alguma forma essas informações de um arquivo e verificar se estão corretas. De preferência usando Python/CMD/PowerShell

O que eu preciso

EDITAR:

Desculpe pela falta de detalhes.

Atualmente estou usando este script python (que modifiquei para rodar em Python 3.6):http://www.zedwood.com/article/python-openssl-x509-parse-certificatepara analisar um arquivo .cer que extraí do arquivo executável original com esta pequena ferramenta que encontrei (que também modifiquei para funcionar com Python 3):https://blog.didierstevens.com/programs/disitool/mas somente depois de convertê-lo de um binário codificado em DER para uma base 64 com o certutil do Windows.

O problema com o script disitool, porém, é que ele literalmente CORTA um bytearray de 'assinatura' do próprio executável usando o módulo pefile python, o que torna o arquivo .cer extraído inválido, de acordo com o erro python que continuo recebendo ao tentar carregue o certificado com o módulo OpenSSL.crypto:

 [('asn1 encoding routines', 'asn1_check_tlen', 'wrong tag'), ('asn1 encoding routines', 'asn1_item_embed_d2i', 'nested asn1 error'), ('asn1 encoding routines', 'asn1_template_noexp_d2i', 'nested asn1 error'), ('PEM routines', 'PEM_ASN1_read_bio', 'ASN1 lib')] 

Mas analisar um bom certificado extraído (com o primeiro script que postei acima) funciona, como você pode ver aqui:

A análise funciona muito bem]

Então, eu só preciso de uma maneira de extrair o certificado de um executável, eu acho. Ou, se você achou minha solução muito complicada, se você tem alguma ideia de como posso obter aquele texto "Redmond" no campo Assunto do certificado, estou muito aberto a ideias :)

Responder1

No PowerShell:

Get-AuthenticodeSignature C:\Path\TO\File.exe

Então, usando seu exemplo de explorer.exe, isso resultaria em Redmond:

(Get-AuthenticodeSignature C:\Windows\explorer.exe).SignerCertificate.subject.split(',')[2].split('=')[1]

Como você solicitou a elaboração, Get-AuthenticodeSignatureretorna um objeto System.Management.Automation.Signature. Você pode descobrir isso de algumas maneiras. Pessoalmente, prefiro atribuí-lo a uma variável para poder brincar ainda mais com o objeto retornado. Depois de atribuí-lo a uma variável, você poderá aprender coisas sobre ela. Get-Memberdeve ser um dos seus cmdlets no Powershell. Nesse caso:

$foo = Get-AuthenticodeSignature C:\Windows\explorer.exe
Get-Member -InputObject $foo
   TypeName: System.Management.Automation.Signature

Name                   MemberType Definition
----                   ---------- ----------
Equals                 Method     bool Equals(System.Object obj)
GetHashCode            Method     int GetHashCode()
GetType                Method     type GetType()
ToString               Method     string ToString()
IsOSBinary             Property   bool IsOSBinary {get;}
Path                   Property   string Path {get;}
SignatureType          Property   System.Management.Automation.SignatureType SignatureType {get;}
SignerCertificate      Property   System.Security.Cryptography.X509Certificates.X509Certificate2 SignerCertificate {...
Status                 Property   System.Management.Automation.SignatureStatus Status {get;}
StatusMessage          Property   string StatusMessage {get;}
TimeStamperCertificate Property   System.Security.Cryptography.X509Certificates.X509Certificate2 TimeStamperCertific...

Então você pode ver que o objeto tem alguns métodos e algumas propriedades (eu sei, todos os objetos têm). Neste caso os métodos são todos os padrões herdados de System.Object. As propriedades são interessantes. O SignerCertificate se parece com o que você queria, então vamos ver como fica:

$foo.SignerCertificate


Thumbprint                                Subject
----------                                -------
419E77AED546A1A6CF4DC23C1F977542FE289CF7  CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US

A impressão digital é obviamente importante porque é o que identifica o certificado, mas você perguntou sobre o Redmond que está no assunto. Agora sabemos como chegar a isso como uma string:

$foo.SignerCertificate.Subject

Portanto, é apenas uma análise de string direta a partir daqui.

Mais um boato que vou acrescentar, pois parece que você pode estar aprendendo Powershell. Outro cmdlet que você deve tentar regularmente é o Get-Command. Nesse caso eu nem sabia que o cmdlet Get-AuthenticodeSignature existia antes de você fazer a pergunta. Então eu fiz isso:

Get-Command *signature*

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Update-MpSignature                                 1.0        Defender
Cmdlet          Get-AuthenticodeSignature                          3.0.0.0    Microsoft.PowerShell.Security
Cmdlet          Save-VolumeSignatureCatalog                        1.0.0.0    ShieldedVMDataFile
Cmdlet          Set-AuthenticodeSignature                          3.0.0.0    Microsoft.PowerShell.Security

Responder2

no PowerShell: você pode ter vírgula no CN, então funcionou para mim:

(Get-AuthenticodeSignature C:\Windows\explorer.exe).SignerCertificate.subject.split('=')[1].split('"=')[1]

informação relacionada