views:

324

answers:

2

Hi, guys. I'm developing a client software for an online community I belong to. In order to let me write a client to it, the owners and webmasters demand my code to be encrypted (not just obfuscated). Most of my project is written in VB.NET (F3.5), and some of it is using SQLite and libcrypt via C++/CLI for performance reasons (so I cannot use /clr:safe). In other words, it would be pointless to write C++/CLI code if /clr:safe were to be used (I'd just write all code in VB which is much easier).

If this was only the VB project, I'd just write a C++ loader, decrypt the code from storage into memory and then use Assembly.Load() to get it running via some public method (e.g., the Main Form). However, some inexplicable policy prevents me from doing that with unverified C++/CLI code. I am at loss, because I can use any "unsafe" DLL without limitations using the normal DLL loading mechanism, but for some reason I cannot do that with Assembly.Load(). I fail to see why that is supposed to be more secure (given that the other option is available). Caspol.exe doesn't help, and even if it do, I couldn't ask everybody in my community to turn off access security in their machines. Directly loading an EXE or DLL from memory doesn't seem to be feasable (UPX does that with regular DLLs but not with .NET DLLs).

So I ask the following:

  • Do you guys can think of any method I could use to encrypt the MISL part of the C++/CLI DLL? (I think the code is intermixed with regular x86 machine code).

  • Is there any way of loading an unverified .NET DLL from bytes, as I tried to do with Assembly.Load?

Alternatively, since CreateProcess() and LoadLibrary() only take paths, I though I could write a temporary EXE image and run it from storage. But I need the image to be inaccessible to the user, so writing it to disk would be just stupid; it should be something volatile like a private ramdisk or something. Anything comes to mind? (Windows 2000 and up).

Thanks a lot,

Guille

+1  A: 

You can load an assenbly from a stream, using an AssemblyResolve method. See this answer for details.

Cheeso
Unfortunately, I cannot get rid of the "Unverifiable code failed policy check" exception with this method either. Although I couldn't use the code just as described, since my resource was not found by using args.Name; I could only use [namespace].[filename] to find the resource. Perhaps I am embedding it the wrong way? i.e.: 'This returns nothing: Dim s As Stream = a1.GetManifestResourceStream(args.Name) 'This gives me a resource, but throws the unwanted exception: Dim s As Stream = a1.GetManifestResourceStream("MyLoader.MyLibrary.dll")
Guillermo Prandi
You're not embedding it "wrong", just differently. It sounded from your post that you had multiple issues going on. I wasn't sure about the verification part, but I did want to contribute an idea on how to load an assembly from a stream of bytes.
Cheeso
I see. Well, my main problem is how to encrypt my mixed code assembly and load it in my executable without decrypting it into disk. By the way, what do you mean differently? I feel you pointed me in the right direction, because the latest release of Cellbi's AppPacker DOES load my code, although my antivirus complains about a "possible virus". It looks like Cellbi's application uses the AssemblyResolve method too, but in a different way and then it succeeds. I cannot find the source for the latest AppPacker version. An older version whos I got the source for fails with the exception problem.
Guillermo Prandi
When you embed a resource into an exe, you can specify a name for it. You use a different name. Different than the name I used.
Cheeso
I correct myself: AppPacker also fails with the policy check exception. :(
Guillermo Prandi
A: 

Assembly.Load(byte[] ...) explicitly disallows unverifiable (mixed mode) assemblies. You can check the issue on Microsoft Connect.

Govert
Yeah, I know it now. It seems Microsoft is trying to make us move to a CLI-only environment in the future, and therefore making it difficult for us working with mixed/native code.
Guillermo Prandi
Oh! Nice link you posted. I especially like the last comment: "We decided to still allow it for v1 assemblies to reduce impact on legacy code. v2 assemblies will be rejected." I may be able to use this. Thanks.
Guillermo Prandi
The Connect entry gives a clear reason why they reject them - because they can make sure that the native part of the code is properly initialized since loading assembly this way bypasses native executable image loader. It has nothing to do with making anyone's life difficult, quite the opposite.
zespri