2

I am trying to call StrongNameSignatureVerificationEx on IClrStrongName from Delphi (using Rad Studio Berlin)

My first attempt just used the definition

function StrongNameSignatureVerificationEx(
  wszFilePath : LPCWSTR;
  fForceVerification : boolean;
  var pfWasVerifided : boolean
): BOOL; stdcall; external 'mscoree.dll';

but this calls the .Net 2.0 version (which is not required for the target machines - gives a nice 'Please install .net framework 2.0/3.5 message')

There is a mechanism to create a CLR host and invoke the version of the routine from a specific runtime using TJclClrHost

var
  anHost : TJclClrHost;
  aClsId : TGUID;
  res : Boolean;
  obj : OleVariant;  // ? Not sure about this, copying from another example
begin

    anHost := TJclClrHost.Create('v4.0.30319');
    anHost. Start
    aClsId := StringToGuid('{9280188d-0e8e-4867-b30c-7fa83884e8de}'); 
    res := anHost.GetInterface(aClsId, obj);

    //...

However, I have no Delphi definition for IClrStrongName so once I get the object I don't see how to invoke any methods on it. Importing mscoree.tlb doesn't give one and a websearch revealed to me only a C++ definition from

  1. Is the code above correct (esp. the 'obj' parameter for GetInterface() )?
  2. Do I need an interface definition to invoke the method (is there a way to invoke by name)?
  3. Where can I obtain a Delphi definition for IClrStrongName?,
  4. How can I convert the C++ definition into Delphi?
Arioch 'The
  • 15,799
  • 35
  • 62
AlanT
  • 3,627
  • 20
  • 28
  • "4.How can I convert the C++ definition into Delphi?" - best of all, by hands. Reading C++ definition and converting to correspondent Delphi types and constructions. There is also h2pas util in Lazarus and there was something in JEDI Win API Library. But they may be broken or outdated and to debug their output you would have to be able to understand underlying low-level representations of C++ and Delphi constructs, and that makes you able to manually convert them, back to square one. – Arioch 'The May 30 '17 at 12:34
  • 1
    @Arioch 'The I was afraid of that... but that sounds a lot like work :) It is next on my list but I reckoned I'd post a question first, just on the off chance there was a quicker way or someone else had already done it :? – AlanT May 30 '17 at 12:37
  • That is learning low-level (assembler-level) representations once, then it is not that much, and then translation would be trivial if tedious (but one single method translation is too little a work to be named tedious). Or you can memorize patterns, but in case your memory fails you - you would not be able to spot the problem in Delphi Debug CPU Window. One example of COM (but not .Net) interface conversion https://github.com/the-Arioch/Delphi-XmlLite - and there should be MUCH more examples in JEDI Windows API Library – Arioch 'The May 30 '17 at 12:40
  • Will check those, thanks – AlanT May 30 '17 at 12:41
  • in my version of JCL there is no GetInterface method in JclDotNEt unit. That means this all is recent development of last 3 years. That means you are using a bleeding edge code that few people but developers have any experience with. That means, you better google for JCL developer forums and ask advice there. http://wiki.delphi-jedi.org/wiki/JCL_Contacts – Arioch 'The May 30 '17 at 12:46
  • I can try that, thanks. If there is a non-Jcl mechanism out there (say using COM to create a CLR host and then creating and the object from that) I would be happy enough with that. Any thoughts? Know of where I might find examples of this? – AlanT May 30 '17 at 12:52
  • "say using COM to create a CLR host" I think that is what JCL does - just read its sources – Arioch 'The May 30 '17 at 12:59

1 Answers1

1

The simplest way is to create a .net class library that exports the functionality that you need. Some ways to do that:

  1. Use a mixed mode C++/CLI class library. That allows you to create class unmanaged exports directly. These in turn can call into managed code.
  2. Create a C# class library and use Robert Giesecke's UnmanagedExports library to expose your functionality.

In both cases you end up with a .dll file whose functions you import into Delphi using the external directive.

There are plenty of examples of how to do both these things on the web, and here on Stack Overflow, so I won't attempt to create yet more identical examples.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I'm afraid we already have the C# assembly which we are accessing from Delphi. The concern is that the assembly would be replaced with a fake (long story, not germane here) so I am using the above call (amongst others) from Delphi to check the naming and signing of the C# assembly. Creating a new assembly to check the security on the first one just pushes the problem back one step. I'm afraid that I am not too sure what the first point means but I have the feeling that it involves adding another language to the mix which is probably more than I was hoping to do. – AlanT May 30 '17 at 12:49
  • 1
    What's to stop the faker, faking `IClrStrongName`? Or replacing your executable? Surely you can trust something? – David Heffernan May 30 '17 at 12:52
  • "using the above call (amongst others)" - he uses many methods and hopes that the attacker perhaps would just overlook one or two. However if the attacker would have the access to the EXE and if the EXE is not debug-protected and async'ed - then the attacker would just observe its behavior and learn which methods he forgot. – Arioch 'The May 30 '17 at 12:57
  • 1
    @Arioch'The That makes no sense to me. If no code can be trusted, then the entire exercise is pointless. If some code can be trusted, put the class library in the trusted area. Never mind. It seems we are discussing constraints that are not present in the question. – David Heffernan May 30 '17 at 12:59
  • I am hoping that the CLR will. If not, the goal is not necessarily to make this unbeatable, just to push the bar high enough to make it not worth the effort. Replacing an assembly which has no strong name with a fake is simple enough. My understanding is that spoofing the strong naming on an unsigned assembly is more work but not all that hard (I may have been mis-informed on this) Signing the assembly makes such tampering evident ergo the call to StrongNameSignatureVerificationEx as another layer – AlanT May 30 '17 at 13:04
  • 2
    I think "hope" isn't really a word I'd want to see near a discussion of security. Smells fishy to me! – David Heffernan May 30 '17 at 13:09
  • @AlanT then I would stand for David's "In both cases you end up with a .dll file whose functions you import into Delphi using the external directive." with one exception - you should mark them as "delayed" functions - loaded on first call. You would have to check correct DLL hash as MD5 or SHA1 and hardcode the hash into your Delphi app, and compute-compare the hash before loading DLL and calling those functions. Of course, your EXE should also be protected from debugging. Finding the explicit hash check in your plain EXE and removing it is a work for about an hour or two. – Arioch 'The May 30 '17 at 13:15
  • Ask your vendors to make a mixed mode version of "we already have the C# assembly" if they do not already have. – Arioch 'The May 30 '17 at 13:16
  • 1
    And strong names are not a security feature. They are a means to avoid DLL hell. You are probably giving yourself a false sense of security. Although, reading between the lines of your comments, you already know this and have been forced this way by superiors who won't listen to you! – David Heffernan May 30 '17 at 13:16
  • As to good/bad security practices, I leave that up to the security experts here. I was asked to use 'StrongNameSignatureVerificationEx' to check the signed assembly, truthfully, that is the only thing with which I am concerned at the moment. If I try to invoke the function on a Win 10 machine I get a 'please install .net 2.0' message. It is possible to use the CLRHost to invoke the 4.0 version of the function. Any help on doing this would be much appreciated. – AlanT May 30 '17 at 13:29
  • I answered the question that you asked I think, which was how to call that function. – David Heffernan May 30 '17 at 13:37
  • Perhaps few links to "prior art" discussions would be helping – Arioch 'The May 30 '17 at 13:47