.NET Applications: How To Hide Assemblies And Unmanaged DLLs

Artem Razin
June 11, 2008

One interesting task I've heard from one of our first customers is hiding assemblies and unmanaged DLLs.
The target language is C#. Let's explore how to solve this task with BoxedApp SDK.


1. Storing the Assembly

In this example, the assembly is stored in a static byte array.
To generate a C# file containing the array, use the following helper program:

using System;
using System.IO;
 
namespace ConvertBinToSharpCode
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] data = File.ReadAllBytes(args[0]);
 
            Console.Write("namespace BinData\n{\n\tpublic class Data1\n\t{\n\t\tpublic static byte[] data = \n{\n");
 
            foreach (byte b in data)
            {
                Console.Write(b.ToString() + ",");
            }
 
            Console.Write("};\n\t}\n}\n");
        }
    }
}

The program takes one argument — the path to an assembly — and outputs the C# code.
Save this output as data.cs, for example:

namespace BinData
{
    public class Data1
    {
        public static byte[] data = 
        {
            77,90,144,0,3,0, ...
        };
    }
}

Include this file in your main project.


2. Creating a Virtual File from the Array

Now, create a virtual file for the assembly and fill it from BinData.Data1.data:

static void CreateAssemblyInMemory(string strVirtualPath, byte[] data)
{
    IntPtr hHandle =
        BoxedAppSDK.NativeMethods.BoxedAppSDK_CreateVirtualFile(
            strVirtualPath,
            BoxedAppSDK.NativeMethods.EFileAccess.GenericWrite,
            BoxedAppSDK.NativeMethods.EFileShare.Read,
            IntPtr.Zero,
            BoxedAppSDK.NativeMethods.ECreationDisposition.New,
            BoxedAppSDK.NativeMethods.EFileAttributes.Normal,
            IntPtr.Zero);
    CloseHandle(hHandle);
 
    using (FileStream VirtualFileStream = new FileStream(strVirtualPath, FileMode.Open))
    {
        VirtualFileStream.Write(data, 0, (int)data.Length);
    }
}

To create the assembly in memory:

CreateAssemblyInMemory(@"Z:\myclass.dll", BinData.Data1.data);
 
Assembly assembly = Assembly.LoadFrom(@"Z:\myclass.dll");
object o = assembly.CreateInstance("myclass.Class1");
o.GetType().GetMethod("SomeMethod").Invoke(o, null);

3. Loading Assemblies Automatically

Another option is to let BoxedApp SDK provide the assembly automatically when your application loads it.
For example:

static class Program
{
    [STAThread]
    static void Main()
    {
        BoxedAppSDK.NativeMethods.BoxedAppSDK_Init();
 
        // Create a virtual file with the assembly before it's used
        CreateAssemblyInMemory(
            Application.StartupPath + @"\Assembly1.dll", 
            BinData.Data1.data);
 
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
 
        // Form1 loads Assembly1.dll, BoxedApp SDK provides it from memory
        Application.Run(new Form1());
    }
}

Summary

Using BoxedApp SDK, you can hide both managed assemblies and unmanaged DLLs, embedding them directly into memory.
Your application can load and use these modules without extracting them to disk, providing better protection and portability.


Related Links