Tuesday, 21 August 2007

Protecting .Net Assemblies Part 2

In my last article, we looked at techniques for obfuscating the string and meta data inside our assemblies so that they could not be easily understood.

In this article, I would like to explore another technique which I came across the other day, which basically involves hiding a compiled assembly from disassembler tools so that it cannot be disassembled easily.

The way it worked is, in my opinion, fairly clever and although the technique has been around since long before .Net was released, and is not specifically used to prevent disassembly, it is still a very effective way of deterring casuals attempts to reverse engineer one's code.
Basically, the way in which this works is to produce a program in two assemblies.
The first assembly consists of the public face to the program. The second assembly consists of all of the actual functionality for the program.
In the first assembly (lets call it A), we create an Interface, which I will call IRunApp for sake of argument. The second assembly (B) references the public assembly (A), and implements the IRunApp Interface in class RunApp
The IRunApp Interface has a single parameterless void method which I will call Start.

Now we compile B so that it becomes a .Net IL assembly file. We make a note of it's size (say 32K exactly for sake of argument).
In A, in the main startup code, we add some lines that will do the following:
- Get the currently executing Assembly (A)
- Get the loaded Module of this Assembly
- Read the bytes from the total length of the Module - 32K to the end of the Module
- Load these bytes into an Assembly (B)
- Using Reflection, create an instance of the IRunApp Interface via the class RunApp in B
- Execute the Start method of IRunApp in B
We then compile A so that it also becomes a .Net IL assembly. We then take the entire content of the file B and append it to the end of the file A (using a hex-editor or perhaps a tool you have written yourself).
Then we run A, and see that the the code in B has been successfully executed. If we examine the code using ILDASM, we see that only assmelby A is visible - we can see that A does something to load some code by Reflection but we do not actually have access to the code in B.

I have produced two demos that show this functionality:
Demo A
In Demo A, there are two assemblies - the main program executable (A) and the library that will eventually become the hidden assembly (B).
In this demo, A loads the file content of B directly, and then invokes the IRunApp.Start() method using Reflection. This sample is there just to give you an example of how reflection works.
You should also examine the assemblies using ILDASM or another disassembly tool, just to see how visible the IL is in both cases (particularly in B).

Demo B
In Demo B, there is a single assembly which is the program executable. This contains the main assembly and also contains the embedded assembly B, which has been embedded using the technique described above.
In this demo, A loads the assembly B using the technique I described in HIDING ASSEMBLIES above. B is then invoked using Reflection.
If you open the executable in ILDASM you will see the code disassembled that carries out the work to load and execute B but, importantly, you will not see the actual code for B.

The samples are available by clicking the links below:
- Demo A
- Demo B

Well assuming that you have implemented an assembly hiding method now, you are probably wondering what is to stop someone who understands the technique from simply using a hex-editor and cutting and pasting your embedded assemblies out to separate files.
Well the truth of the matter is that it is highly unlikely that you will ever stop someone who knows what they are doing from accessing your .Net code in this way, but you can still use a few more methods to make it more difficult:
- Add fake libraries into the file
You can add some fake assemblies to the end of the file, and make one of these your valid assembly. This will not make it impossible to access the real assembly but it will make it more difficult.
- Encrypt your libraries
You can encrypt the libraries that are embedded in the file so that they cannot just be extracted using a hex-editor. A compiled assembly has a distinctive layout, which will be completely hidden by encryption.
- Use remoting or a WebService for sensitive business logic
If you are able to, you can use .Net Remoting or a WebService to host your business logic and other sensitive code. You can invoke the service from your application code.

There isn't a lot more to say on the technique for hiding assemblies, other than you should make the effort to protect your source code in every way possible. People are often flippant about security, but you should not forget that your source code is your intellectual property - do you really want others to see how you do things in your applications, particularly if you are providing an application that is unique or satisfies a niche demand.

If you have any suggestions or queries about this article, just drop me an e-mail.

Have fun!

No comments: