Recently I was digging in Strong naming and signing in .net. I have found an interesting article on code project
Building Security Awareness in .NET Assemblies
which describe how the strong name can be easily removed and beaked from an executing assembly. I would like to present the approach that can be used with library assemblies in .net.
What is a strong name (also called strong name key) and how does it work?
The strong name mechanism is greatly described here. Generally it assures the assembly receiver that the assembly comes from trusted source. It assigns an unique encrypted identifier in the assembly.
I always prefer learning with examples so lets consider concrete usage.
Generally signing the assembly is described in following steps:
- Generate strong name key pair with use of sn.exe tool
- Sign assembly by assigning the strong name key pair (public/private)
- The crucial part of the assembly is hashed and encrypted with private key
- The encrypted hash and a public key is delivered to the user (program)
- User again creates the hash of the assembly and encrypt it with public key, if the result value match this received the assembly is treated as came from trusted source.
Lets see how it works. This is an simple console application named Program that includes library named SignedLibrary.
1: class Program
3: static void Main(string args)
5: var lib = new LibraryClass();
1: public class LibraryClass
3: public string GetTextValue()
5: return "I am from library!";
As you can see the library has only one method which returns simple string message. Main program creates the instance of library and writes the content of its method to the console.
To sign the library we need to generate a strong name key. To do that we open the Visual Studio console and change main directory to main library project directory and use sn.exe tool provided with Microsoft.
Next we go to the project, and include the key.snk into the library project
Then we go to the library project properties and on tab Signing we choose the key.
Now we can rebuild the solution. The reference in the Program will be automatically updated with new public key and encrypted hash of the library. We get the result as a string coming from the library.
Now lets go with the disassembler and try to crack the library a little ;-) For the convenient I have created separate directory and put there the Program.exe and the SignedLibrary.dll which are the result of compilation in Release mode.
We now point the console to that directory and disassemble the library (strong name signed) using ildasm disassembler.
Edit the output file as described on code project and change the result of the library method as follows
and assemble the library back to the .dll format
Notice that we have to use switch /dll to inform the assembler that the output is an library.
Now if we try to run our program with such prepared library it crashes. Strong naming works!
Ok, lets try to do some more modifications in our disassembled library. We remove the public key…
reassemble the library and try again.
Unfortunately we get same result, program does not want to start. It is because it still contains some information about the public key and assembly. Lets disassemble the Program.exe and see what we can do.
1: ildasm Program.exe /out=Program.il
The generated Intermediate Language file contains some interesting information
What is that public key token associated with our library? Wikipedia says:
Ok so as long as we have removed the public key from our library we must remove it from here also. Just delete the line with .publickeytoken, save and reassemble the the program.
1: ilasm Program.il
Then we can run our program.
We have already remove the strong name from the SignedLibrary.dll and the Program.exe which is using it. As you can see it was not to hard .
The conclusion of this article is that the Strong-Name is for sure not a mechanism to assure the security of the assembly. As we proved, anyone who has access to the executing assembly and linked libraries can easily remove the Strong-Name key and further replace the library with self prepared version. This is a security issue indeed.
Some kind of solution for above problem is obfuscation. The obfuscated library can be disassembled into the il but is not readable and after change can not be reassembled back into the dll file. The same applies for executables.
More about obfuscation you can find on wikipedia.
Full source code for this article can be found in attachement.