2

This method, while "documented", just doesn't seem to work for me. I'm trying to verify the signature of the currently running executable. Used GetModuleHandle as the first param (base address) and GetModuleInformation to find the size. I keep getting back CORSEC_E_INVALID_IMAGE_FORMAT. I also thought maybe the method expects the address of the manifest, so I use FindResource etc to get that address, but it didn't work either. Has anyone successfully used this method?

Sample code:

HMODULE modHandle = GetModuleHandle(NULL);
MODULEINFO modInfo;
GetModuleInformation(GetCurrentProcess(), modHandle, &modInfo, sizeof(MODULEINFO));
DWORD temp;
BOOL valid = StrongNameSignatureVerificationFromImage((BYTE*)modHandle, modInfo.SizeOfImage, 0, &temp);
DWORD res = StrongNameErrorInfo(); // returns CORSEC_E_INVALID_IMAGE_FORMAT
Dandan
  • 519
  • 2
  • 9
  • this method is deprecated as per documentation. See http://msdn.microsoft.com/en-us/library/ms231929%28v=vs.100%29.aspx. Also I think the method needs the assembly to be already mapped into the application's memory. What exactly do you want to do? – Ganesh R. May 03 '14 at 07:01
  • I tried the new version of this method as well. Same result. The assembly I'm trying to verify is that of the executing process. It's obviously mapped into memory. I'm writing a library that needs to verify it's being executed from a process with a signed assembly. – Dandan May 03 '14 at 07:06
  • Digitally signed or strong named? – Ganesh R. May 03 '14 at 07:07
  • Strong named. Also see this article: http://blogs.msdn.com/b/shawnfa/archive/2004/06/07/150378.aspx Same idea, only I want to use the memory mapped image as opposed to accessing the assembly from disk. – Dandan May 03 '14 at 07:09
  • Try this : http://stackoverflow.com/questions/308756/checking-an-assembly-for-a-strong-name and this http://social.msdn.microsoft.com/Forums/vstudio/en-US/27a5b126-bdb4-4d67-8cdb-f6601e171e73/how-to-verify-strong-name-programmatically-in-cnet-4?forum=clr. Did not try them, but they seem helpful – Ganesh R. May 03 '14 at 07:11
  • Thanks, but that doesn't answer my question. I'd like to use this method because: 1. It verifies the signature (as opposed to just reading the public key). 2. It can (supposedly) do that without file system access. If that wasn't a requirement I would have just used StrongNameSignatureVerificationEx as demonstrated in the MSDN blog post. – Dandan May 03 '14 at 07:14
  • Do you have a sample code reproducing your problem? – Simon Mourier May 03 '14 at 07:24
  • @Mike Just so that I understand, is the above code C++ / C++ CLI? If yes, what is the hosting executable C# or C++ or C++ CLI? – Ganesh R. May 03 '14 at 10:32
  • C++ CLI. Hosting executable is a C# WPF app. – Dandan May 03 '14 at 20:00

1 Answers1

1

Here is what I was able to come up with regarding to Assembly, using the AutoPiner class from this answer (https://stackoverflow.com/a/23838643/6694311) :

var fileStream= assembly.GetFile( assembly.ManifestModule.Name );
var byteArray = new byte[]{};
using(var ms = new MemoryStream()){
    fileStream.CopyTo(ms);
    byteArray = ms.ToArray();
}
var result = false;
using( var gcPinned = new AutoPinner( byteArray ) ) {
    try {
        int outFlags;
        result = HResult.S_OK == (HResult)ICLRStrongName.StrongNameSignatureVerificationFromImage( gcPinned, byteArray.Length, NativeMethods.SN_INFLAG_FORCE_VER, out outFlags )
                   && ( outFlags & NativeMethods.SN_OUTFLAG_WAS_VERIFIED ) == NativeMethods.SN_OUTFLAG_WAS_VERIFIED;
    } catch {
        result = false;
    }
}

Where NativeMethods is:

internal static class NativeMethods
{
    /// <summary>
    /// https://msdn.microsoft.com/en-us/library/ff844053(v=vs.110).aspx
    /// ICLRStrongName::StrongNameSignatureVerificationFromImage
    /// </summary>

    //Forces verification even if it is necessary to override registry settings
    public const int SN_INFLAG_FORCE_VER = 0x1;

    //Specifies that this is the first verification performed on this image
    public const int SN_INFLAG_INSTALL = 0x2;

    //Specifies that the cache will allow access only to users who have administrative privileges
    public const int SN_INFLAG_ADMIN_ACCESS = 0x4;

    //Specifies that the assembly will be accessible only to the current user
    public const int SN_INFLAG_USER_ACCESS = 0x8;

    //Specifies that the cache will provide no guarantees of access restriction
    public const int SN_INFLAG_ALL_ACCESS = 0x10;

    //This value is set to false to specify that the verification succeeded due to registry settings
    public const int SN_OUTFLAG_WAS_VERIFIED = 0x1;
}

With a little more catch clauses and some exception message parsing you can have other than bool result.

Community
  • 1
  • 1