É 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
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:
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-AuthenticodeSignature
retorna 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-Member
deve 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]