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.

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
    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.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:

  1. 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.
  2. From C:\Demo\TaxCalculator\bin\Debug, execute ILDASM C:\Demo\TaxCalculator\bin\Debug\TaxCalculator.exe / This will disassemble the TaxCalculator.exe assembly into CIL, storing in the output file specified ("").
  3. From the command prompt, enter notepad.exe 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).
  4. 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.
  5. From the same command prompt, execute ILASM /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:

  1. Users would get incorrect results, eventually causing them problems with the IRS due to insufficient taxes paid.
  2. Current users of this product would lose confidence in the maker of TaxCalculator and future sales would decrease.
  3. Once the media was informed of this incident, potential customers would be lost due to bad publicity.
  4. 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:

  1. SN.exe to generate a strong-named assembly
  2. Dotfuscator
  3. 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):

  1. 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.
  2. 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.

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:

  1. 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.
  2. 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.
  3. 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.

Obfuscation changes the structure of the assembly. If the assembly is signed, it needs to be re-signed after obfuscation. The CE will require re-signing as a post-build step in Dotfuscator. The Professional Edition, however, supports the re-signing of assemblies. Learn more about techniques for automating obfuscation here.

SignTool.exe is another security tool available free of charge with the .NET Framework. It's a command-line utility used for digitally signing files and assemblies for use with Authenticode technology.

This technology ensures the user is using the application as intended by the publisher. By using a certificate provider, the software publisher can sign the assembly with the provided certificate. When the user attempts to download the application, the signature is verified with the certificate provider to ensure the origins of the application. It also confirms that it hasn't been tampered with before users download an application to their PC.

The syntax for the command is signtool [command] [options] [file_name | ...], where "command" could be one of the following four options:

  1. catdb -- This command utilizes a catalog database where catalog files are stored and identified by a GUID. Catalog files can be added or removed from the catalog database as desired. Catalog databases are used for automatic lookup of catalog files. By default, the catdb command adds the files, whose names are specified by the FileName argument, to the system component (driver) catalog database.
  2. sign -- The sign command digitally signs files or assemblies. This includes .exe, .dll, .cab, .ocx, .stl and .cat files. A digital signature protects files from tampering, and allows users to confirm the signer based on a signing certificate. Certificates can be issued from a third-party vendor or created using a .NET Framework utility called Makecert.exe. Certificates can be issued to a user, computer, corporation, URL and more.
  3. Timestamp -- This command is used to add a timestamp to a previously signed file.
  4. Verify -- Use the verify command to confirm the signature used on the catalog or files. This process determines if the signing certificate was issued by a trusted source, or revoked. It can also be used to determine if the certificate is valid under a specific policy.

All commands pertaining to the signtool.exe utility offer options, which you can learn more about here.

SignTool.exe Demo
Digitally signing a file essentially involves two steps:

  1. Obtaining a code-signing certificate, either via a third-party vendor or by creating one using Makecert.exe.
  2. Running signtool.exe on the assembly, using that certificate for signing.

Makecert.exe is a command-line utility that creates certificates on a server. The following example shows the utility being called from a Visual Studio command prompt. The –r and –n switches are for creating a self-signed certificate and a certificate named CN=MyPrivateCert, respectively.

Once the certificate is available, the SignTool command can be executed on the assembly, specifying the name of the certificate with the –n switch. The results are shown here:

C:\Demo>makecert.exe -r  -n CN=MyPrivateCert MyCert.cer

C:\Demo>Signtool sign /n MyPrivateCert C:\Demo\TaxCalculator\bin\Debug\TaxCalculator.exe
Done Adding Additional Store
Successfully signed: C:\Demo\TaxCalculator\bin\Debug\TaxCalculator.exe

Now the assembly is signed with the certificate. Once the user downloads the application, he'll be notified of the certificate's publisher, helping to ensure safe execution.

SignTool.exe vs. SN.exe
Although SignTool.exe and SN.exe each use some type of encryption to embed within the assembly, they're completely separate tools with different benefits. SignTool.exe is used to sign an assembly with a certificate, primarily from a third-party certificate provider. This allows the user to ensure the application is authentic and unchanged, as intended by the publisher.

SN.exe, on the other hand, doesn't use a certificate, but instead a key pair combination (public and private) to encrypt the assembly. Therefore, it can't utilize a third-party certificate provider to ensure authenticity to the user. However, SN.exe does help prevent against malicious changes to the application without the complexities of a certificate. Note the private key needs to remain guarded and protected by the publisher. Without the private key, a hacker can't modify the code and re-sign it.

Lock It Up
Hackers are constantly searching for vulnerabilities in applications. Their motives range from pride to high-dollar theft, with results that vary from disruptive to destructive. Thankfully, the .NET Framework offers many tools for protecting software and users. Each tool, used independently, offers a unique security feature. Combined together, they're used to build a more secure application, protecting both the publisher and user.

comments powered by Disqus


Subscribe on YouTube