Jump to content

Verifying signed files


tkocsir
 Share

Recommended Posts

Dear Everybody,

I am noob to COM and dll call stuff, but I need to create a script which can verify if a file is signed or not.

For this, I have googled this script:

$obj = ObjCreate("Scripting.Signer")
$showui = False
$Signed = $obj.VerifyFile("C:\sample.exe", $showui)
ConsoleWrite($Signed & @CR)

The problem is, that the $Signed variable always will be false (on every file, even on those which are signed for sure). If I set the $showui to true, then a windows appears where I have to click on yes or no. If I click yes, the $signed will be true, otherwise false. So maybe the script I am trying to use is wrong at all... I have to detect if a file is digitally signed or not.

I found these page on the net, but I am not a programmer so I can't use them:

http://msdn.microsoft.com/en-us/library/aa387721%28v=VS.85%29.aspx

http://msdn.microsoft.com/en-us/library/aa388208%28v=VS.85%29.aspx

http://msdn.microsoft.com/en-us/library/wt5f4sta%28VS.85%29.aspx

Is there someone who is familiar with this thing?

Thank you

Thomas

Link to comment
Share on other sites

Thank you for fast reply funkey!

I think this is what I'm looking for, but it looks like it doesn't work for me.

If I try to verify any file, which is signed, the script returns always the error "An unknown error occurred trying to verify the signature of the "%s" file", but for those files it should return "The file "%s" is signed and the signature was verified." So I don't know what is wrong.

Sometimes it returns "CRYPT_E_SECURITY_SETTINGS - The hash representing the subject or the publisher wasn't explicitly trusted by the admin and admin policy has disabled user trust. No signature, publisher or timestamp errors."

Do you have any idea?

Thanks in advance,

Thomas

Link to comment
Share on other sites

I think I know what is the problem on my computer.

Somehow I succesfully "deleted"(?) the list of the signers/certificates (or what) from the system. I don't know how. I was just trying my posted code and yours. Now every verifying program always says that the files are not signed.

I think the problem was already done when I started to check your script, so it's not that script's fault.

How can I restore these certificates?

Thomas

Link to comment
Share on other sites

Are the files you are checking .exe or .vbs files? If not, that may be your problem. To get around that limitation, you can temporarily rename the file before checking it.

Someone gave me this script a couple of years ago. I'd give credit, but can't find the original message.

Hope it helps.

; Initialize error handler
$oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

Const $Debug=False

If $Debug Then
    AutoItSetOption("TrayIconDebug", 1) ;0=no info, 1=debug line info
Else
    AutoItSetOption("TrayIconDebug", 0)
EndIf
Opt("MustDeclareVars", 0)        ;0=no, 1=require pre-declare
Opt("TrayAutoPause", 0)          ;0=no pause, 1=Pause
Opt("TrayIconHide", 0)           ;0=show, 1=hide tray icon

If $CmdLine[0]<1 Then
    MsgBox(0,@ScriptName,"Usage:" & @CRLF & @CRLF & "  " & @ScriptName & " <filename>")
    Exit(1)
EndIf
$TheFile=$CmdLine[1]
If StringRight(StringLower($CmdLine[1]),4)=".au3" Then
    $TheFile=$CmdLine[1] & ".vbs"
    If FileExists($TheFile) Then
        MsgBox(48,"Signer","The file '" & $TheFile & "' exists." & @CRLF & "Unable to check '" & $CmdLine[1] & "'")
        Exit
    EndIf
    FileMove($CmdLine[1],$TheFile)
EndIf

; -------------------------------- Check it ----------------------------------
$objSigner = ObjCreate("Scripting.Signer")

$blnIsSigned = $objSigner.VerifyFile($TheFile, False)

If StringRight(StringLower($CmdLine[1]),4)=".au3" Then
    FileMove($TheFile,$CmdLine[1])
EndIf

If $blnIsSigned then
    MsgBox(0,"","'" & $CmdLine[1] & "' has been signed.")
Else
    MsgBox(0,"","'" & $CmdLine[1] & "' has not been signed.")
EndIf

$oSigner = ""

Func MyErrFunc()
  Local $HexNumber=hex($oMyError.number,8)
  Msgbox(48,@ScriptName,"An error has been encountered"       & @CRLF  & @CRLF & _
             "  description: " & @TAB & $oMyError.description    & @CRLF & _
             "             : " & @TAB & $oMyError.windescription & @CRLF & _
             " error number: " & @TAB & $HexNumber               & @CRLF & _
             "last dllerror: " & @TAB & $oMyError.lastdllerror   & @CRLF & _
             "  line number: " & @TAB & $oMyError.scriptline     & @CRLF & _
             "       source: " & @TAB & $oMyError.source         & @CRLF & _
             "    help file: " & @TAB & $oMyError.helpfile       & @CRLF & _
             "  helpcontext: " & @TAB & $oMyError.helpcontext _
            )
  SetError(1)  ; to check for after this function returns
EndFunc

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;     Signature block follows      ;;;;;;;;
;;;;;;;; Must be removed before compiling ;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Exit
Link to comment
Share on other sites

Thanks for your post willichan! But if you look at the code you posted you can see it is the "same" as mine, but "extended". It still didn't worked for me.

Funkey! Your code seems to work. But I need one more thing. Is it possible to compile into the script Microsoft's certificate? I must not use the certificate stored on the computers where script will be used. Is there a way to do this?

Thank you!

Link to comment
Share on other sites

Again, this is not my code. Someone else did this and gave it to me. I seem to recall seeing similar code in threads here, so credit definitely does not go to me.

This is the code I use to sign.

If $CmdLine[0]<1 Then
    Exit(1)
EndIf

Sleep(1000)

$TheFile=$CmdLine[1]
If StringRight(StringLower($CmdLine[1]),4)=".au3" Then
    $TheFile=$CmdLine[1] & ".vbs"
    If FileExists($TheFile) Then
        MsgBox(48,"Signer","The file '" & $TheFile & "' exists." & @CRLF & "Unable to sign '" & $CmdLine[1] & "'")
        Exit
    EndIf
    FileMove($CmdLine[1],$TheFile)
EndIf

; Initialize error handler
$oMyError = ObjEvent("AutoIt.Error","MyErrFunc")

; --------------------------------- Sign it ----------------------------------
$oSigner = ObjCreate("Scripting.Signer")
$oSigner.SignFile ($TheFile, "***Put the name of your signature here***")
$oSigner = ""

If StringRight(StringLower($CmdLine[1]),4)=".au3" Then
    FileMove($TheFile,$CmdLine[1])
EndIf

Func MyErrFunc()
  Local $HexNumber=hex($oMyError.number,8)
  Msgbox(48,@ScriptName,"An error has been encountered"       & @CRLF  & @CRLF & _
             "  description: " & @TAB & $oMyError.description    & @CRLF & _
             "             : " & @TAB & $oMyError.windescription & @CRLF & _
             " error number: " & @TAB & $HexNumber               & @CRLF & _
             "last dllerror: " & @TAB & $oMyError.lastdllerror   & @CRLF & _
             "  line number: " & @TAB & $oMyError.scriptline     & @CRLF & _
             "       source: " & @TAB & $oMyError.source         & @CRLF & _
             "    help file: " & @TAB & $oMyError.helpfile       & @CRLF & _
             "  helpcontext: " & @TAB & $oMyError.helpcontext _
            )
  SetError(1)  ; to check for after this function returns
EndFunc

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;     Signature block follows      ;;;;;;;;
;;;;;;;; Must be removed before compiling ;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Exit

As far as my code working, but yours not, this method really only works on .exe and .vbs files (and Java, but I have had mixed success there). If you are using any other files extension, it won't work without renaming them (what these scripts do). If that isn't the issue, then I am not sure why yours won't work.

Link to comment
Share on other sites

Interesting topic :)... doing a little google research I found this C-Code sample:

http://groups.google.com/group/microsoft.public.platformsdk.security/browse_frm/thread/e60c801b6d1b7d67/a14576a6c4496ac2?pli=1

which points to this Api function: CryptQueryObject

http://msdn.microsoft.com/en-us/library/aa380264%28v=vs.85%29.aspx

Should be "easy" to port the example to AutoIt... would be a nice addition to SMF... maybe when I get bored ;)...

Edited by KaFu
Link to comment
Share on other sites

willichan: sorry, I forgot to write that I want to verify mostly .exe files (sometimes .dll or .sys, but I would be satisfied if only the .exe thing worked). I know nothing about signatures. For example, if I wanted to sign files and not verify, and I wanted to use the script you provided, I don't know what should I write to ***Put the name of your signature here***. And I don't know if this text is important or not (what does it mean?): Signature block follows, Must be removed before compiling (what? I should remove these comment lines?)

But I don't want to sign files but verify.

KaFu: maybe that C code does what I need, I don't know.:) C is totally unknown for me.

Again, summarized:

I would be very-very happy if there was a script which I can use to verify files with a specified certificate. This certificate must be compiled into the script. I need "Microsoft Corporation" certificate, but I don't know how to get it and what is it like. (Is it a file? Or a hash?)

I hope there will be a solution...

(If something is not clear it is because my english is not perfect:)

Link to comment
Share on other sites

Here is a start ;). Does not work (yet), the CERT_INFO Structure is really bugging me... anyone got a structure definition lying around :) ?

$sFile = @AutoItExe

$h_DLL_Crypt32 = DllOpen("Crypt32.dll")

_Crypt_GetSignerInfo($sFile)

Func _Crypt_GetSignerInfo($sFile)
    If Not FileExists($sFile) Then Return SetError(1)

    Local $iRes

    Local $b_DLL_Crypt32_Opened = False
    If Not IsDeclared("h_DLL_Crypt32") Then
        Local $b_DLL_Crypt32_Opened = True
        Local $h_DLL_Crypt32 = DllOpen("Crypt32.dll")
    EndIf

    Local Const $CERT_QUERY_OBJECT_FILE = 0x1
    Local Const $CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED = 10
    Local Const $CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED = 2 ^ $CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
    Local Const $CERT_QUERY_FORMAT_BINARY = 0x1
    Local Const $CERT_QUERY_FORMAT_FLAG_BINARY = 2 ^ $CERT_QUERY_FORMAT_BINARY
    Local Const $CMSG_SIGNER_INFO_PARAM = 0x6
    Local Const $X509_ASN_ENCODING = 0x00000001
    Local Const $PKCS_7_ASN_ENCODING = 0x00010000
    Local Const $CERT_FIND_SUBJECT_CERT = 720896

    Local $tContentType = DllStructCreate("DWORD")
    Local $tCertStore = DllStructCreate("DWORD")
    Local $tCryptMsg = DllStructCreate("DWORD")
    $iRes = DllCall($h_DLL_Crypt32, "int", "CryptQueryObject", _
            "DWORD", $CERT_QUERY_OBJECT_FILE, _
            "WSTR", $sFile, _
            "DWORD", $CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, _
            "DWORD", $CERT_QUERY_FORMAT_FLAG_BINARY, _
            "DWORD", 0, _
            "DWORD", "", _
            "DWORD", DllStructGetPtr($tContentType), _
            "DWORD", "", _
            "Handle", DllStructGetPtr($tCertStore), _
            "Handle", DllStructGetPtr($tCryptMsg), _
            "PTR", "")

    If Not $iRes[0] Then
        If $b_DLL_Crypt32_Opened Then DllClose($h_DLL_Crypt32)
        Return SetError(2)
    EndIf

    If DllStructGetData($tContentType, 1) <> $CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED Then
        If $b_DLL_Crypt32_Opened Then DllClose($h_DLL_Crypt32)
        Return SetError(3)
    EndIf

    Local $tSignerInfo_Size = DllStructCreate("DWORD")
    ; Call #1 to determine buffer size
    $iRes = DllCall($h_DLL_Crypt32, "BOOL", "CryptMsgGetParam", _
            "Handle", DllStructGetData($tCryptMsg, 1), _
            "DWORD", $CMSG_SIGNER_INFO_PARAM, _
            "DWORD", 0, _
            "PTR", "", _
            "DWORD", DllStructGetPtr($tSignerInfo_Size))
    Local $tSignerInfo = DllStructCreate("BYTE [" & DllStructGetData($tSignerInfo_Size, 1) & "]")
    ; Call #2 to fill buffer
    $iRes = DllCall($h_DLL_Crypt32, "BOOL", "CryptMsgGetParam", _
            "Handle", DllStructGetData($tCryptMsg, 1), _
            "DWORD", $CMSG_SIGNER_INFO_PARAM, _
            "DWORD", 0, _
            "PTR", DllStructGetPtr($tSignerInfo), _
            "DWORD", DllStructGetPtr($tSignerInfo_Size))
    If @error Or Not $iRes[0] Then
        If $b_DLL_Crypt32_Opened Then DllClose($h_DLL_Crypt32)
        Return SetError(4)
    EndIf
    
    Local $tSignerInfo_Extract = DllStructCreate("DWORD dwVersion;DWORD Issuer_Size;PTR Issuer_Ptr;DWORD SerialNumber_Size;PTR SerialNumber_Ptr", DllStructGetPtr($tSignerInfo))
    Local $tSignerInfo_Issuer = DllStructCreate("BYTE [" & DllStructGetData($tSignerInfo_Extract, 2) & "]", DllStructGetData($tSignerInfo_Extract, 3))
    Local $tSignerInfo_SerialNumber = DllStructCreate("BYTE [" & DllStructGetData($tSignerInfo_Extract, 4) & "]", DllStructGetData($tSignerInfo_Extract, 5))

    ; http://msdn.microsoft.com/en-us/library/aa377200(VS.85).aspx
    Local $tCertInfo = DllStructCreate("DWORD dwVersion;BYTE[" & DllStructGetData($tSignerInfo_Extract, 4) & "]

    $iRes = DllCall($h_DLL_Crypt32, "DWORD", "CertFindCertificateInStore", _
            "Handle", DllStructGetData($tCertStore, 1), _
            "DWORD", BitOR($X509_ASN_ENCODING, $PKCS_7_ASN_ENCODING), _
            "DWORD", 0, _
            "DWORD", $CERT_FIND_SUBJECT_CERT, _
            "PTR", DllStructGetPtr($tCertInfo), _
            "PTR", "")

    MsgBox(0, "", $iRes[0] & @CRLF & "")


    If $b_DLL_Crypt32_Opened Then DllClose($h_DLL_Crypt32)
EndFunc   ;==>_Crypt_GetSignerInfo


#cs
    /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++­+
    ++


    This code is provided for illustration purpose only.


    Linked with Crypt32.lib.


    ---------------------------------------------------------------------------­-
    */


    #include <stdio.h>
    #include <crtdbg.h>
    #include <windows.h>
    #include <wincrypt.h>


    int wmain (int argc, LPWSTR argv[])
    {
    int                nRetCode        = 0;
    HCERTSTORE         hCertStore      = NULL;
    HCRYPTMSG          hCryptMsg       = NULL;
    DWORD              dwContentType   = 0;
    DWORD              dwExpectedType  = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED;
    DWORD              cbData          = 0;
    CMSG_SIGNER_INFO * pSignerInfo     = NULL;
    CERT_INFO          CertInfo        = {0};
    PCCERT_CONTEXT     pCertContext    = NULL;
    LPWSTR             pwszSubjectName = NULL;


    __try
    {
    // Check command parameters.
    if (2 != argc)
    {
    nRetCode = E_INVALIDARG;
    printf("Usage: %s AuthenticodeSignedFileName\n", argv[0]);
    __leave;
    }


    // Retrieve the signed executable HCRYPTMSG and HCERTSTORE.
    if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
    (LPCVOID) argv[1],
    dwExpectedType,
    CERT_QUERY_FORMAT_FLAG_BINARY,
    0,
    NULL,
    &dwContentType,
    NULL,
    &hCertStore,
    &hCryptMsg,
    NULL))
    {
    nRetCode = GetLastError();
    printf("Error [%#x]: CryptQueryObject() failed.\n", nRetCode);
    __leave;
    }


    // Sanity check.
    _ASSERT(CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED == dwContentType);


    // Use low level messaging API to retrieve signer's info.
    if (!CryptMsgGetParam(hCryptMsg,
    CMSG_SIGNER_INFO_PARAM,
    0,
    NULL,
    &cbData))
    {
    nRetCode = GetLastError();
    printf("Error [%#x]: CryptMsgGetParam() failed.\n", nRetCode);
    __leave;
    }


    if (!(pSignerInfo = (CMSG_SIGNER_INFO *) malloc(cbData)))
    {
    nRetCode = E_OUTOFMEMORY;
    printf("Error [%#x]: malloc() failed.\n", nRetCode);
    __leave;
    }


    if (!CryptMsgGetParam(hCryptMsg,
    CMSG_SIGNER_INFO_PARAM,
    0,
    pSignerInfo,
    &cbData))
    {
    nRetCode = GetLastError();
    printf("Error [%#x]: CryptMsgGetParam() failed.\n", nRetCode);
    __leave;
    }


    // Find signer's cert in store.
    CertInfo.Issuer = pSignerInfo->Issuer;
    CertInfo.SerialNumber = pSignerInfo->SerialNumber;

    if (!(pCertContext = CertFindCertificateInStore(hCertStore,
    X509_ASN_ENCODING |
    PKCS_7_ASN_ENCODING,
    0,
    CERT_FIND_SUBJECT_CERT,
    (LPVOID) &CertInfo,
    NULL)))
    {
    nRetCode = GetLastError();
    printf("Error [%#x]: CryptMsgGetParam() failed.\n", nRetCode);
    __leave;
    }


    // Retrieve signer's simple name.
    if (!(cbData = CertGetNameStringW(pCertContext,
    CERT_NAME_SIMPLE_DISPLAY_TYPE,
    0,
    NULL,
    NULL,
    0)))
    {
    nRetCode = CRYPT_E_NOT_FOUND;
    printf("Error [%#x]: CertGetNameString() failed.\n", nRetCode);
    __leave;
    }


    if (!(pwszSubjectName = (LPWSTR) malloc(cbData)))
    {
    nRetCode = E_OUTOFMEMORY;
    printf("Error [%#x]: malloc() failed.\n", nRetCode);
    __leave;
    }


    if (!(cbData = CertGetNameStringW(pCertContext,
    CERT_NAME_SIMPLE_DISPLAY_TYPE,
    0,
    NULL,
    pwszSubjectName,
    cbData)))
    {
    nRetCode = CRYPT_E_NOT_FOUND;
    printf("Error [%#x]: CertGetNameString() failed.\n", nRetCode);
    __leave;
    }


    // Display signer's simple name.
    printf("%ls was signed by %ls.\n", argv[1], pwszSubjectName);
    }


    __finally
    {
    // Clean up - left as an exercise for the reader.
    }


    return nRetCode;

    }
#ce
Edited by KaFu
Link to comment
Share on other sites

I don't know what should I write to ***Put the name of your signature here***.

Since that script is for signing, you need to let it know what certificate to sign with. You replace that text with your certificate's name. If you are not going to be signing, then you can just ignore that script altogether.

If all you need to do is check to see if a file has a valid signature, then just use the first script. If you need to know that it was signed by a particular person/organization, then that is a bit beyond me. It looks like KaFu is on track to be able to do that though.

Don't worry about the "Must be removed before compiling" comments. You can leave them or remove them. There used to be a digital signature section after it that would have messed up the compile. It has already been removed.

If you want to understand signing more, you can read these:

http://en.wikipedia.org/wiki/Code_signing

http://blogs.msdn.com/b/secureapps/archive/2007/01/25/code-signing.aspx

http://msdn.microsoft.com/en-us/library/ms537361.aspx

Link to comment
Share on other sites

It looks like credit for the guts of those scripts probably belongs to ptrex. It looks remarkably similar to his scripts. You can take a look at the thread where he discusses it here.

@KaFu:

Local $tCertInfo = DllStructCreate("DWORD dwVersion;BYTE[" & DllStructGetData($tSignerInfo_Extract, 4) & "]

Looks like you might have left line 80 dangling in the middle of a thought. :)

Edited by willichan
Link to comment
Share on other sites

@KaFu:

I don't know if it helps you, but maybe:

Start > Run > mmc > File > Add/remove snap-in > Certificate > OK > open a "folder", then double click on an owner > Details tab.

@willichan:

Thank you for your information and help, I save these scripts for later use.:)

Link to comment
Share on other sites

Looks like you might have left line 80 dangling in the middle of a thought. :)

Yeah, that's a failure on purpose, because the underlying structure is a little... complex ;)?

http://msdn.microsoft.com/en-us/library/aa377200%28VS.85%29.aspx

Link to comment
Share on other sites

Yeah, that's a failure on purpose, because the underlying structure is a little... complex ;)?

I'm glad its you working on it, not me. :)

Link to comment
Share on other sites

What should that function print? Signer only, or what?

On KaFu's...

$sFile = @AutoItExe

_PrintSignerInfo($sFile)

Func _PrintSignerInfo($sFile)
    If Not FileExists($sFile) Then Return SetError(1)

    Local Const $CERT_QUERY_OBJECT_FILE = 0x1
    Local Const $CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED = 10
    Local Const $CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED = 2 ^ $CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
    Local Const $CERT_QUERY_FORMAT_BINARY = 0x1
    Local Const $CERT_QUERY_FORMAT_FLAG_BINARY = 2 ^ $CERT_QUERY_FORMAT_BINARY
    Local Const $CMSG_SIGNER_INFO_PARAM = 0x6
    Local Const $X509_ASN_ENCODING = 0x00000001
    Local Const $PKCS_7_ASN_ENCODING = 0x00010000
    Local Const $CERT_FIND_SUBJECT_CERT = 720896

    Local $aCall = DllCall("Crypt32.dll", "bool", "CryptQueryObject", _
            "dword", $CERT_QUERY_OBJECT_FILE, _
            "wstr", $sFile, _
            "dword", $CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, _
            "dword", $CERT_QUERY_FORMAT_FLAG_BINARY, _
            "dword", 0, _
            "dword*", 0, _
            "dword*", 0, _
            "dword*", 0, _
            "handle*", 0, _
            "handle*", 0, _
            "ptr", 0)

    Local $iMsgAndCertEncodingType = $aCall[6]
    Local $iContentType = $aCall[7]
    Local $iFormatType = $aCall[8]
    Local $hCertStore = $aCall[9]
    Local $hMsg = $aCall[10]

    ConsoleWrite("MsgAndCertEncodingType = " & $iMsgAndCertEncodingType & @CRLF)
    ConsoleWrite("ContentType = " & $iContentType & @CRLF)
    ConsoleWrite("FormatType = " & $iFormatType & @CRLF)
    ConsoleWrite("CertStore = " & $hCertStore & @CRLF)
    ConsoleWrite("Msg = " & $hMsg & @CRLF & @CRLF)

    ; Simple check
    If Not $hMsg Then Return

    $aCall = DllCall("Crypt32.dll", "bool", "CryptMsgGetParam", _
            "handle", $hMsg, _
            "dword", $CMSG_SIGNER_INFO_PARAM, _
            "dword", 0, _
            "ptr", 0, _
            "dword*", 0)

    Local $iSize = $aCall[5]

    Local $tBuffer = DllStructCreate("byte[" & $iSize & "]")

    $aCall = DllCall("Crypt32.dll", "bool", "CryptMsgGetParam", _
            "handle", $hMsg, _
            "dword", $CMSG_SIGNER_INFO_PARAM, _
            "dword", 0, _
            "ptr", DllStructGetPtr($tBuffer), _
            "dword*", DllStructGetSize($tBuffer))

    ; Shorter CMSG_SIGNER_INFO structure (I want Issuer only)
    Local $tCMSG_SIGNER_INFO_MOD = DllStructCreate("dword Version;" & _
            "dword_ptr IssuerSize;" & _
            "ptr Issuer;", _
            DllStructGetPtr($tBuffer))

    $aCall = DllCall("Crypt32.dll", "dword", "CertNameToStrW", _
            "dword", 1, _ ; X509_ASN_ENCODING
            "ptr", DllStructGetPtr($tCMSG_SIGNER_INFO_MOD, "IssuerSize"), _
            "dword", 0x08000003, _ ; CERT_X500_NAME_STR|CERT_NAME_STR_CRLF_FLAG
            "wstr", "", _
            "dword", 65536)

    ConsoleWrite($aCall[4] & @CRLF)

EndFunc
Link to comment
Share on other sites

Nice ;)... so... structures returned by the system are pre-formatted and given the names as in MSDN, you can directly extract data if you know the structure:

Local $tCMSG_SIGNER_INFO_MOD = DllStructCreate("dword Version;" & _
            "dword_ptr IssuerSize;" & _
            "ptr Issuer;", _
            DllStructGetPtr($tBuffer))

Hmmm, thinking about it, this is a nice service by MS. Did not knew that trick before :) , you might have laughed about my efforts to rebuild the CERT_INFO structure :idiot:...

Looking at the result for Autoit I guess Name, Email and Timestamp would be nice too, also the from - to validity timestamps.

Edit: Or did I miss-understood this, is only a little part of CERT_INFO returned by CryptMsgGetParam because of the $CMSG_SIGNER_INFO_PARAM flag?

Edit2: For calculating the Timestamps from the FILETIME elements I think there's a suitable function collection include called _WinTimeFunctions.au3 in Ascend4nt's _WinAPI_FileFind UDF.

Edit3: Here's a MS KB posting describing how to extract relevant data in more detail: http://support.microsoft.com/kb/323809

Edited by KaFu
Link to comment
Share on other sites

What should that function print? Signer only, or what?

I'm thinking on a function that returns only if the specified file is signed or not by Microsoft. And the function must contain the public key for verifying MS signed files.

Link to comment
Share on other sites

And the function must contain the public key for verifying MS signed files.

I don't think you really want to include the public key. There can potentially be several keys. Keys expire, are renewed, get replaced, come from multiple verifiers, etc... Over the life of any MS product, it would not be surprising to see multiple keys used. If a machine has internet access, the keys can easily be polled, however.

What should that function print?

I would want to see both signer and verifier information. There may be situations where there is a verified signature for a signer you are interested in, but it could come from a less than reliable verifier that you may want to ignore.
Link to comment
Share on other sites

I need an AutoIT tool like Sigcheck.exe:

http://technet.microsoft.com/en-us/sysinternals/bb897441

But for me it would be enough if the script could tell me if a Microsoft signed file is valid or not. I know it is free, but due to license limitations I am not allowed to use sigcheck.exe the way I want to.

Using any of the codes above I never could get a result that says that "this MS file is signed and verified". (I ran the scripts on file like shell32.dll, explorer.exe, wintrust.dll,...)

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...