Expert Texture Home Contact me About Subscribe Digipede Connect on LinkedIn rwandering on Twitter rwandering on FriendFeed

rwandering.net

The blogged wandering of Robert W. Anderson

2.0 Port Update: Finished (for now)

Now that I am finished with the port to VS2005 / .NET 2.0, I wanted to point out a few final issues I came across. Note that we use the Preemptive Dotfuscator v3.0 here, but the obfuscation issues likely apply to other obfuscators as well:

New files in ASP.NET 2.0

As the compilation model for ASP.NET has changed a great deal, there are also some new files that you must deploy. Of course, this is not an issue if you use VS2005 to deploy directory to a web site, but if you are packaging up all of your files into an installer then make sure you include these new files:

  • *.resx
  • *.compiled
  • PrecompiledApp.config

In particular, I have found that if the *.compiled and PrecompiledApp.config file are not in place, your global events will not get raised.

Obfuscation Issue #1: Don’t rename __ASP

Exclude the __ASP namespace from the renamed. This is a new namespace that is generated by the compiler, so you need to exclude this in your Dotfuscator project file:

  <renaming>
    <excludelist>
        . . .
        <namespace name="__ASP" regex="false" />
        . . .
    </excludelist>
  </renaming>

Note that there is also a new ASP namespace, but I did not have to exclude this one because I was already excluding class names that are automatically placed under this namespace. Obfuscation Issue #2: Don’t obfuscate multiple Web projects at once

Before ASP.NET 2.0, it was possible to obfuscate multiple Web projects at the same time (as long as all of the namespaces are unique across projects). The new namespaces that are generated by the compiler (i.e., ASP and __ASP) will cause a conflict during obfuscation. To solve this problem, you need to break up your obfuscations into multiple projects.

This last part is somewhat non-trivial (or at least a real hassle). I have written many nant scripts that take build output and assemble them into a directory for obfuscation, breaks up the Dotfuscator configuration file, runs multiple obfuscation runs, and finally reassembles the files into individual folders for release.

I am not going to blog on those specifics, but if you are interested in my solutions to these problems, feel free to contact me.

Tags: , , ,

Removing a hanging assembly reference

I don’t know if many people have run into this problem: a .NET assembly referencing another assembly in its manifest, though the referenced assembly isn’t used at all.

I don’t believe this is possible under normal conditions, but it is possible with an application that post-processes the assembly. Specifically, this can happen when using Dotfuscator 3.0. When obfuscating .NET 1.1 assemblies, it supports custom obfuscation attributes defined in a .NET library that they ship. Depending on the way you configure Dotfuscator, these attributes can be stripped from your obfuscated assembly. This is reasonable as the attributes have already served their purpose. There is a confirmed bug (that I’m sure they’ll fix soon) that leaves a reference in the manifest though all the attributes have been removed.

In most cases this doesn’t effect the use of your assembly. The CLR won’t try to load the referenced assembly (as there are no actual references to any types in that assembly). The one problem that I have found, though, is if your assembly is a library that others (e.g., your customers) will reference in their own projects. The assembly still functions properly, but undesirable warnings will be emitted by the compiler. And of course, this only applies if you are not shipping the unreferenced assembly.

As an interim solution, they (i.e., Preemptive support staff) suggest disassembling to il with ildasm, manually editing the il, and then reassembling with ilasm. Of course, this approach doesn’t work in an automated release environment. Understandably, they leave that as an exercise for the reader.

Here is what we did. Since all of our release builds are done with nant,
we made use of the built-in ildasm and ilasm tasks. Then we added a custom task that removes the reference from the il. The following code shows an example target assuming that the name of the library is ‘MyLibrary.dll’:

<?xml version="1.0" ?>
<project name="Hanging reference Example" default="rebuild" xmlns="http://nant.sf.net/release/0.85-rc3/nant.xsd">
    <target name="assembleobf">
        <!-- fix the Preemptive.ObfuscationAttributes.dll hanging reference bug -->
        <ildasm rebuild="true" output="MyLibrary.dll.il" rawexceptionhandling="true" quoteallnames="true"
            utf8="true" linenumbers="true" input="MyLibrary.dll" />
        <!-- define a task that takes an IL file as an input, removes the Preemptive.ObfuscationAttributes.dll, and
             writes the file out again -->
        <script language="C#">
            <imports>
                <import namespace="System" />
                <import namespace="System.IO" />
                <import namespace="System.Text" />
            </imports>
            <code>
            <![CDATA[
                [TaskName("removeRef")]
                public class RemoveRefTask : Task {
                    private string _obfuscatedLibrary;
                    [TaskAttribute("obfuscatedLibrary", Required=true)]
                    public string SomeProperty {
                        get { return _obfuscatedLibrary; }
                        set { _obfuscatedLibrary = value; }
                    }
                                                       
                    protected override void ExecuteTask() {
                        StreamReader inFile = new StreamReader(_obfuscatedLibrary + ".il");
                        string inContents = inFile.ReadToEnd();
                        inFile.Close();
                   
                        StringBuilder sb = new StringBuilder(inContents.Length);
                        StringReader stringReader = new StringReader(inContents);
                        string line;
                        while ((line = stringReader.ReadLine()) != null) {
                            if (line != @".assembly extern 'PreEmptive.ObfuscationAttributes'") {
                                sb.Append(line + '
');
                            } else {
                                for (int i=0; i < 4; i++) {
                                    stringReader.ReadLine();
                                }
                                sb.Append(stringReader.ReadToEnd());
                            }
                        }
                   
                        StreamWriter outFile = new StreamWriter(_obfuscatedLibrary + ".il");
                        outFile.Write(sb.ToString());
                        outFile.Close();
                    }
                }
            ]]>
            </code>
        </script>
        <removeRef obfuscatedLibrary="MyLibrary.dll" />
        <ilasm rebuild="true" output="MyLibrary.dll" resourcefile="MyLibrary.dll.res" target="dll">
            <sources>
                <include name="MyLibrary.dll.il"></include>
            </sources>
        </ilasm>
    </target>
</project>

They’ll fix it soon, I’m sure — but for now this will work just fine.

Tags: , ,