Code Focused

Creating Secure .NET Applications

An overview of the Microsoft .NET Framework application security utilities SN.exe, Dotfuscator and SignTool.exe.

Application security is always an important topic in day-to-day development, but it doesn't always get the attention it deserves. There are many reasons you should be concerned with security. Over the years the value of data -- to corporations and hackers alike -- has increased significantly. Corporations of all sizes have much at risk, including customer credit-card numbers, Social Security numbers and patient information.

However, hackers aren't always trying to steal information. Hackers of religious and political organizations often attempt to deface a site in the hopes of giving an organization negative publicity. Other times the intent is to cripple the site and take it offline, or completely take over the server and use it to attack other servers. Regardless of the scenario, application security is a necessity for every organization.

Application security is a broad topic, covering all aspects of IT (servers, networking, applications, databases and more). I won't be able to cover all aspects in this article; my goal is to address some utilities in the Microsoft .NET Framework that are often overlooked. The primary utilities I'll discuss are SN.exe, Dotfuscator and SignTool.exe. To demonstrate these tools, I'll create a sample application that will serve as the basis for demonstrating all three utilities.

TaxCalculator

For the sample app, I'll create a desktop application for calculating personal income tax. This is not a production app, but a simplified version of popular tax software programs, as seen in Figure 1.

[Click on image for larger view.] Figure 1. TaxCalculator functioning correctly.

When a user specifies the annual income and clicks Calculate Taxes, the application will produce an estimate of taxes owed, depending on the income level. The code listing for the Calculate Taxes button is shown in Listing 1.

Listing 1. Event handler for the Calculate Taxes button.

Private Sub btnCalcTax_Click(sender As System.Object, e As System.EventArgs) Handles btnCalcTax.Click Try Dim Salary As Double = Convert.ToDouble(txtSalary.Text) Dim TaxRate As Double = 0.0 If Salary <= 100000 Then TaxRate = 0.37 ElseIf (Salary >= 100001) AndAlso (Salary <= 250000) Then TaxRate = 0.44 ElseIf Salary >= 250001 Then TaxRate = 0.51 End If Dim TaxDue As Double = Salary * TaxRate TaxDue = Math.Round(TaxDue) txtTaxDue.Text = TaxDue.ToString() Catch ex As Exception Dim errMsg As String = "Error: {0} " & vbLf & "Please contact customer support at 800-111-2100 for assistance." errMsg = String.Format(errMsg, ex.Message) MessageBox.Show(errMsg, "Application Error", MessageBoxButtons.OK) End Try End Sub

If the user were to experience an error, a user-friendly message would appear, as seen in Figure 2.

[Click on image for larger view.] Figure 2. A user-friendly error message.

If this application is left unprotected, a hacker could potentially penetrate the server and alter the app. Once altered, unsuspecting users could use it and suffer from the malicious changes.

The purpose of the following demonstration is to show how an application can be hijacked by a hacker, altered for malicious use, and then placed back in to be used by an unsuspecting user. (Please note the malicious activity demonstrated here is strictly for educational purposes. The intent is to show what could happen to an unprotected application. Such activity is punishable by law; penalties can include a jail sentence and financial restitution.)

ILDASM/ILASM

ILDASM.EXE and ILASM.EXE are free command-line utilities that come with the .NET Framework. The names are acronyms for Intermediate Language Disassembler and Intermediate Language Assembler. The purpose of ILDASM is to disassemble an assembly (.exe, .dll) file into a Common Intermediate Language (CIL) .il file. This was formerly called Microsoft Intermediate Language (MSIL). The counterpart of ILDASM is ILASM, which will do the opposite by processing CIL code into an assembly.

Once the .exe and .dll files are accessed by a hacker, they can be changed with the following procedure:

Open a Visual Studio command prompt. This differs from a traditional command prompt window because it executes vcvarsall.bat, loading settings for using Visual Studio utilities. From C:\Demo\TaxCalculator\bin\Debug, execute ILDASM C:\Demo\TaxCalculator\bin\Debug\TaxCalculator.exe /out=myfile.il. This will disassemble the TaxCalculator.exe assembly into CIL, storing in the output file specified ("myfile.il"). From the command prompt, enter notepad.exe myfile.il. As you may know, Notepad.exe is installed by default on all Windows OSes. This utility will allow the file to be edited without using Visual Studio. Browsing through the .il file, you'll notice that Microsoft CIL appears to be a mix of assembler- and C#-like code. However, it's a proprietary language developed by Microsoft (learn more about CIL here). A developer knowledgeable in CIL can identify which code segments perform certain tasks in the application. However, even with no knowledge of CIL, you can see hardcoded strings such as, "Please contact customer support at 800-111-2100 for assistance." In addition, you can see the values .37, .44 and .51 elsewhere in the code. These correspond to the values used for tax rates, as seen in Listing 1. For the sake of the demo, search the code for ".37" and change it to .11. Also change the 800-111-2100 number to "800-BADD-TAX." After making these changes, save and exit Notepad. From the same command prompt, execute ILASM myfile.il /output=calcBonus.exe. This will re-assemble, building a new .exe with malicious code.

Notice Visual Studio was not used at all during this procedure -- only a command prompt and a few command-line applications were used.

Results of a Hacked Application

At this stage, the application has been successfully altered. New users downloading this application will not suspect it has been hacked, and continue to use it. Now, when the application is executed, the amount of tax due in Figure 3 is drastically less than that in Figure 1.

[Click on image for larger view.] Figure 3. TaxCalculator with incorrect results after being hacked.

In addition, the verbiage appearing in the error message was altered, directing users to an incorrect phone number, as seen in Figure 4.

[Click on image for larger view.] Figure 4. An altered customer support phone number.

Had this been a real scenario, the results from this attack would have been numerous. For example:

Users would get incorrect results, eventually causing them problems with the IRS due to insufficient taxes paid. Current users of this product would lose confidence in the maker of TaxCalculator and future sales would decrease. Once the media was informed of this incident, potential customers would be lost due to bad publicity. A class action lawsuit could be filed against the software publisher for not taking appropriate measures to defend against a hacker.

Now I'll take a look at how this security vulnerability could be resolved using one of the following utilities:

SN.exe to generate a strong-named assembly Dotfuscator SignTool.exe

Using SN.exe

Strong-named assemblies are files that are digitally signed using a unique key pair. This key pair is generated using SN.exe, a free utility available with the all versions of the .NET Framework.

Like most other .NET utilities, SN.exe is accessed from the Visual Studio command prompt. It's a command-line tool used for generating pairs of digital keys, one public and one private, in a single key file. The key file is then referenced as an attribute in the project, either in AssemblyInfo file or project settings, depending on the .NET language used in the project. Once the solution is built, the final assembly will be digitally signed. A digitally signed assembly will help safeguard against an assembly being disassembled or reassembled with malicious code.

The procedure for digitally signing an assembly is outlined here (the command-line operations will be executed from a Visual Studio command prompt):

First, execute sn.exe –k private.snk. The –k switch specifies generating a new RSACryptoServiceProvider key and writes it to the specified file. This will be known as the key file. Move the private.snk file to the same directory as the project. Because the demo application is written in Visual Basic .NET, the name of the key file is referenced in the Signing tab of the project settings. This can be seen in Figure 5.

[Click on image for larger view.] Figure 5. The Signing tab of the project settings.

This is one way to sign an assembly, but the SN utility allows for other options. Learn more about signing assemblies here. Once the file is signed, it won't appear or function any different from an unsigned file. The only difference is it can't run, if reassembled, without the private key. Therefore, it's vitally important to keep the private key from falling into the wrong hands.

Should a hacker attempt to modify a signed assembly as described here, one of two things will occur. Either an error message will be displayed to the user indicating the assembly is corrupted, or it won't run at all. In either case, the application won't function or produce malicious results for the intended user.

Dotfuscator

Another method of protecting an assembly is by using Dotfuscator Software Services. This is a tool that encrypts, or obfuscates, the assembly. It replaces meaningful method and field names with generic ones. For example, looking at Figure 6, you'll see a side-by-side comparison (using the same source code) of non-obfuscated code versus obfuscated code. Names such as btnCalcTax_Click and btnExit_Click are now named a and b. Both assemblies are displayed using the ILDASM utility.

[Click on image for larger view.] Figure 6. Non-obfuscated versus obfuscated assemblies.

The intention of obfuscating the code is to make it more difficult for a hacker to reverse-engineer the assembly.

Dotfuscator Demo

Here's the procedure for running Dotfuscator:

In Visual Studio, click Tools | DotFuscator Software Services. This will launch the UI for Dotfuscator, as seen in Figure 7, with the start page as the default. The start page will list instructions on getting started to obfuscate the code. Begin by right-clicking the project name (Dotfuscator1 is the default) and select Add Assemblies. When prompted, select the path of the assembly (.dll or .exe) to be obfuscated. Click the Build Project button in the Dotfuscator window to create a new obfuscated assembly. Prior to obfuscation, the project must be saved. For this example, I used default names and paths. Once the project is saved, obfuscation will execute to completion.

[Click on image for larger view.] Figure 7. The Dotfuscator start window.

When finished, several items will be created in the path specified in step 3:

The ~\Dotfuscated folder, containing the obfuscated assembly and a "map.xml" file

The ~\Dotfuscator1.xml file, which serves as the project file containing all relevant settings for the obfuscation

The ~\Dotfuscated\map.xml file, which maps the original method and field names to the new generic names (such as a, b and so on). This file, seen in Figure 8, is required if the assembly is to be disassembled with the original method names.

[Click on image for larger view.] Figure 8. The map.xml file.

The Dotfuscator Software Services Community Edition (CE) comes free with every version of Visual Studio .NET. It's accessible from the Tools dropdown menu. Dotfuscator is also available in a Professional Edition, allowing encryption of hardcoded strings and other features. You can view the full list of capabilities in each edition here.