Executive Summary
One of important characteristics of commercial software is ability to trust the software manufacturer by validating authenticity of the software components. Such functionality can be achieved by digital signing of the released code. Another feature usually implemented at the final stage of the development cycle is code obfuscation which is protecting compiled code from unauthorized disassembly. This document describes three security measures / protection levels that should be implemented as last steps of the release build: code obfuscation, .NET strong name signing and Authenticode signing.
Introduction
.NET Application Security Vulnerabilities Due To Unobfuscated and Unsigned Code
Confidentiality of the compiled code can be compromised because it is so easy to restore the source code using disassembling, aka reverse engineering, techniques to look almost the same as original code which provides ability to analize (and then modify) the source code by unauthorized persons. Based on retrieved information, unauthorized users can make malicious changes to the original software as well as obtain confidential information such as hard coded default values of some parameters (for example, default values of initialization vectors and salt values which are not changed by customers) and other sensitive information. Another security threat for commercial software and its creators is reusing proprietary code by other people or competitors (loss of
intellectual property). Obfuscation protects compiled code released to the customers from disassembling (reverse engineering), while code signing protects it from unauthorized changes.
Integrity and Authenticity of the compiled code can be compromised if the build is not signed and therefore there is no way to ensure the originality of the code when customer receives new version release or patch, as well as there is no way to ensure at runtime that currently installed and running code was not altered or corrupted by malicious software installed by hacker.
Additional Benefits of Strong Name Signing
In addition to avoiding security threats described in previous section, signing of .NET assemblies is required in order to meet security policies of IT Departments of some customers who raised security level by allowing only signed .NET assemblies to be installed on their servers.Another usage is strong naming, which requires singing, as evidence in .NET CAS - see .NET Code Access Security documentation for details.Finally, applications that use strong named assemblies are very explicit about which versions of other assemblies they require to run meaning assembly signing provides additional version control.
Additional Benefits of Authenticode Signing
The limitation of .NET signing is that it can sign only .NET .exe and .dll. Authenticode is Microsoft technology that provides ability to sign any .exe, .dll and some additional binary file formats regardless whether it is produced by .NET or other tools (for example, it is useful to sign .exe files of the install package produced by InstallShield or MSI).In addition, newer versions of Windows can be configured to allow only signed applications to run.Finally, using Authenticode is one of requirements for Microsoft certified partner program.
Implementing Obfuscation and Strong Name Signing
Obfuscation Tool
There are several commercial products (obfuscators) that can be used as obfuscation tools. We will review one of them - SmartAssembly.
See SmartAssembly documentation for implementation details.
Obfuscation Project and Strong Name Signing
SmartAssembly project should be created and customized for each .NET project. See SmartAssembly documentation for more details.
Strong name signing is performed by SmartAssembly as last action of the obfuscation sequence. The obfuscation project should be launched through command line as last operation of the automated build process because an assembly must be signed after any changes (including obfuscation) of its binary content are finalized. In order for developers to be able to operate with unsigned unobfuscated code, which simplifies debug process, delayed singing option should be used on each .NET project being obfuscated. Thus, the assembly will not be obfuscated while compiled locally.
The picture below illustrates necessary singing settings in VS.NET project properties. The Sign the assembly and Delay Sign Only checkbox should be checked in order to enable delayed signing. The strong name key file parameter should point to public key portion of the strong name key (only public key is needed for delayed signing). The pointer to the private key portion of the string name key should be defined in obfuscation project as private key is required in order to sign assembly during automatic build process.

Example of Obfuscation Project (XML file format)
<SmartAssemblyProject ProjectID="{65b91823-492f-46f9-bd3b-c1e92f223f9d}" Version="2.0">
<MainAssemblyFileName>..\Tools\Bin\App.exe</MainAssemblyFileName>
<Configuration Name="Release">
<ApplicationName />
<Destination DestinationFileName="..\Exe\{smartassembly}\App.exe" />
<Assemblies>
<Assembly AssemblyName="App.API, Culture=neutral, PublicKeyToken=b076106437b046b5" HintPath="..\Exe\App.API.dll">
<Merging />
<Embedding />
</Assembly>
<Assembly AssemblyName="App.Common, Culture=neutral, PublicKeyToken=b076106437b046b5">
<Merging />
<Embedding />
</Assembly>
<Assembly AssemblyName="log4net, Culture=neutral, PublicKeyToken=1b44e1d426115821">
<Merging />
<Embedding />
</Assembly>
<Assembly AssemblyName="Castle.Windsor, Culture=neutral, PublicKeyToken=407dd0808d44fbdc" HintPath="..\Exe\Castle.Windsor.dll">
<Merging />
<Embedding />
</Assembly>
<Assembly AssemblyName="Castle.MicroKernel, Culture=neutral, PublicKeyToken=407dd0808d44fbdc" HintPath="..\Exe\Castle.MicroKernel.dll">
<Merging />
<Embedding />
</Assembly>
<Assembly AssemblyName="Castle.Core, Culture=neutral, PublicKeyToken=407dd0808d44fbdc" HintPath="..\Exe\Castle.Core.dll">
<Merging />
<Embedding />
</Assembly>
<Assembly AssemblyName="Castle.DynamicProxy2, Culture=neutral, PublicKeyToken=407dd0808d44fbdc" HintPath="..\Exe\Castle.DynamicProxy2.dll">
<Merging />
<Embedding />
</Assembly>
<Assembly AssemblyName="App, Culture=neutral, PublicKeyToken=b076106437b046b5">
<Merging>
<MemberRefsProxy />
<Pruning />
<Obfuscation Obfuscate="1">
<Exclusion />
</Obfuscation>
<ControlFlow Obfuscate="1" ObfuscationLevel="3" />
</Merging>
</Assembly>
</Assemblies>
<Options>
<Obfuscation FieldsNameMangling="3" NameMangling="3" />
<ExceptionReporting />
<StrongNameSigning KeyFileName="C:\Snkey\App.snk" Sign="1" />
<StringsEncoding Encode="1" />
<OtherProtections AddIncorrectMetadata="1" AddMetadataStream="1" SuppressIldasm="1" />
<OtherOptimizations />
<Debugging CreatePDB="0" />
</Options>
</Configuration>
</SmartAssemblyProject>
Obfuscation and Strong Name Signing from Command Line
Obfuscation process (including strong name signing) should be launched automatically from command line as last step (more precisely – one step before the last one – see Authenticode for details) of the automated project build. Here is example of one of obfuscation command lines included in automatic build batch file:
"C:\Program Files\{smartassembly}\{smartassembly}.com" /build "App.{sa}proj"
Implementing Authenticode Signing
Authenticode
Authenticode consists of programs for digitally signing code files as well as programs for checking that the code files were successfully signed. Currently, Authenticode allows software vendors to sign:
.cab files
.cat files
.ctl files
.dll files
.exe files
.ocx and
Code Signing Certificate
Code Signing Certificate issued by public CA (Certification Authority) is required in order to perform valid signing process. Such certificate should be installed on build server in order to establish automated build process with automatic signing of the release builds.
Obtaining Code Signing Certificate
Code Signing Certificate can be obtained from one of well known Certification Authorities such as VeriSign. Follow instructions provided by your CA in order to obtain the certificate.
Installing Code Signing Certificate on Build Server
The certificate, which is originally received from CA as a file in .pfx format, should be imported into the local certificate store of the build server under the user account of the build process. Click on this file in order to launch certificate import wizard and follow instruction. Make sure that “Mark this key exportable” option is unchecked in order to preserve the security of private key. Only specially designated system account of build server should access to the private key of the signing certificate. After certificate is installed, it can be retrieved by build process using its sha1 thumbprint.

SignTool
The Sign Tool is a command-line tool that digitally signs files, verifies signatures in files, or time stamps files.
Installing SignTool
SignTool can be installed as part of Windows SDK for Windows Server 2008 and .NET Framework 3.5 from following link:
http://www.microsoft.com/downloads/details.aspx?FamilyId=E6E1C3DF-A74F-4207-8586-711EBE331CDC&displaylang=en
Launch setup and select only tools as shown below:

SignTool will be installed in C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin
You may also need to manually register the latest version of capicom.dll:
RegSvr32 /r C:\Program Files\Microsoft SDKs\Windows\v6.1\Bin\capicom.dll
Using SignTool
SignTool command line format:
signtool [command] [options] [file_name | ...]
Authenticode process should be launched automatically from command line as last step (after obfuscation – this is important!) of the automated project build. Here is example of one of Authenticode signing command line included in automatic build batch file:
signtool sign /sha1 3627f74724ba013c03875b861c6478b43026437f App.API.dll"
Validation and Testing
Validating Obfuscation
Disassembling tools such as .NET Reflector ( http://www.red-gate.com/products/reflector ) can be used to validate obfuscation. After obfuscation is performed, any disassembling tool won’t be able to open obfuscated assembly and shoe its source code.
Validating Strong Name Signatures
Strong Name Signature can be validated using .NET command line tool:
sn.exe –v <assembly name>
Validating Authenticode Signatures
Validating Authenticode using Windows Explorer
Windows Explorer can check any file for a valid digital signature as described in
[1]
Validating Authenticode using signtool utility
signtool.exe verify /pa /v myinstall.exe
References
[1] Code Signing for Developers