Einzelnen Beitrag anzeigen

Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.680 Beiträge
 
Delphi 5 Professional
 
#1

Digitale Signaturen (Authenticode) von Dateien auslesen

  Alt 12. Feb 2023, 15:43
Hallo Leute, ich brauch mal wieder eure Hilfe und euren Sachverstand .

Aktuell bin ich damit beschäftigt, digitale Signaturen von Dateien auszulesen (EXE, CAT, SYS, MSI, MSU usw.). Erst konnte ich nur die erste Signatur lesen, fand dann aber bei StackOverflow den entscheidenden Hinweis:
Zitat:
Authenticode stores secondary signatures in the UnauthenticatedAttributes of primary signer (index 0), instead of additional PKCS 7 signer.

From the primary signature, search the UnauthenticatedAttribue for below:
[...]
szOID_NESTED_SIGNATURE
Mithilfe dieser Informationen konnte ich den folgenden Code zusammenschreiben:
Delphi-Quellcode:
procedure TSignatureContainer.FindAllEmbeddedSignatures(const ASignerInfo: PCMSG_SIGNER_INFO; const ACertStore: HCERTSTORE);
var i: integer;
    { Nested signatures }
    LUnauthAttr: PCRYPT_ATTRIBUTE;
    LNestedMsg: HCRYPTMSG;
    LNestedSignerInfo: PCMSG_SIGNER_INFO;
    LNestedSignerInfoSize: DWORD;
    LNestedMsgCertStore: HCERTSTORE;
begin
    LUnauthAttr:= ASignerInfo.UnauthAttrs.rgAttr;

    { Geht ASignerInfo.AuthAttr durch }
    AddSignatureFromSignerInfo(ASignerInfo, ACertStore);

    for i:= 1 to ASignerInfo.UnauthAttrs.cAttr do begin
        if AnsiString(LUnauthAttr.pszObjId) = szOID_NESTED_SIGNATURE then begin
            FNestedSignature:= True;
            LNestedMsg:= CryptMsgOpenToDecode(X509_OR_PKCS7_ENCODING, 0, 0, 0, nil, nil);
            if NOT Assigned(LNestedMsg) then
                Exit;
            try
                if NOT CryptMsgUpdate(LNestedMsg, LUnauthAttr.rgValue.pbData, LUnauthAttr.rgValue.cbData, True) then
                    Exit;
                if NOT CryptMsgGetParam(LNestedMsg, CMSG_SIGNER_INFO_PARAM, 0, nil, LNestedSignerInfoSize) then
                    Exit;
                GetMem(LNestedSignerInfo, LNestedSignerInfoSize);
                try
                    if NOT CryptMsgGetParam(LNestedMsg, CMSG_SIGNER_INFO_PARAM, 0, LNestedSignerInfo, LNestedSignerInfoSize) then
                        Exit;
                    LNestedMsgCertStore:= CertOpenStore(CERT_STORE_PROV_MSG, X509_OR_PKCS7_ENCODING, 0, 0, LNestedMsg);
                    try
                        FindAllEmbeddedSignatures(LNestedSignerInfo, LNestedMsgCertStore);
                    finally
                        CertCloseStore(LNestedMsgCertStore, 0);
                    end;
                finally
                    FreeMem(LNestedSignerInfo);
                end;
            finally
                CryptMsgClose(LNestedMsg);
            end;
        end;
        Inc(LUnauthAttr);
    end;
end;
Wie man im Code sehen kann, werden die Attribute sowohl rekursiv als auch iterativ durchsucht. Dennoch sind so nicht mehr als zwei Signaturen auszulesen. Also hab ich weitergesucht und bin auf diesen C++-Code gestoßen, von dem der Autor behauptet, der Code könne alle geschachtelten Signaturen (Nested Signatures) auslesen.

Da sind wir beim eigentlichen Punkt: Kann mir jemand erklären, warum das so umständlich gemacht wird, warum diese Kopfstände mit Umwandlung Big Endian in Little Endian (Zeile 198), Vergleich einzelner Bytes (Zeile 175), Byte Alignment (Zeile 201) und einigen anderen Dingen gemacht werden? Gibt's dafür nicht fertige Funktionen in der Windows API, die das Ganze "in schön" tun? Wie macht man es richtig? Oder geht das tatsächlich nur so umständlich? Und wenn ja, wie würde man diesen C++-Code nach Delphi übersetzen, vor allem die Makros?


Wer eine Datei mit mehr als zwei Signaturen braucht, kann einen Link zu einer solchen z.B. in diesem Issue bei Github finden.

Grüße
Dalai
  Mit Zitat antworten Zitat