Confessions of a Design Pattern Junkie

§ April 25, 2008 16:28 by beefarino |

Me: "Hello, my name is Jim, and I'm a pattern junkie."

Group: "Hello. Jim."

Yes, I humbly admit it.  I read this book, that book, and this other one too, and now I'm pattern-tastically pattern-smitten with a pattern-obsession.  I'm that guy on the team - the one who starts the design with strategies and factories and commands and decorators before a lick of code is compiled.  The one who creates decorator and composite base classes for every interface because "I'll prolly need 'em."  The one who, at the end of the project, has produced Faulknerean code for lolcat functionality.  

But I confess: I am not the least bit ashamed.  I acknowledge my approach has been overbearing and self-indulgent. I know I need to change to be a better engineer.  Spending time as Scrum Master has shown me what pattern hysteria looks like from the outside.  It's WTFBBQ smothered in bloat sauce.

But the experience of being a pattern junkie has been irreplaceable, for a number of reasons.  Patterns are valuable to know, for reasons I'll expound on in a bit.  Taking the time to (over-)apply them to real projects has been the best way for me to learn how they work and interact.  My biggest problem is that I want to apply them as much as possible at the design stage of a project. I've come to terms with the fact that it's a bad idea, which has given me the chance to learn something and improve myself.

So, in the words of the good witch: "What have you learned Dorothy?"

First, let's talk about how misusing patterns has inhibited me.

Bad: Using a pattern leads me to using another. 

Using a strategy pattern precipitates the use of decorators and adapters on the strategy.  Using commands leads to the use of composites, iterators, and chain of responsibility.  The complexity of managing the patterns and dependency injection leads to the use of facades, factories, builders, and singletons.  Things become extraordinarily convoluted very quickly.  When I design against patterns a priori, when they don't service an existing need, the code I have to write explodes, and once it's written, maintaining it becomes a real chore.

Bad: Thinking in patterns makes me lose focus of the problem.

Using patterns makes me itch to break down problems into very atomic units, which is generally good, but I take it to the point of comedy.  Consider this example, which is an actual approach I used because I thought it was a good idea at the time.  I was working on an object that operates on an XML document. To supply the XML document to my object, I chose to define the IXMLDocumentProvider interface as an abstraction for loading the XML.  Why?  Because I was thinking about patterns and not the problem I was trying to solve.  My logic was roughly  this: if I use another strategy to manage the load behavior the XML source could be a file at runtime and an in-memory document in my unit tests, and I could use a decorator on the strategy to validate an XMLDSIG on the document in production if I need to.  In the end, all the program needed was the XML, which could have easily been supplied in a constructor or parameter.  There is but one instance of IXMLDocumentProvider in the project, and all it does is hand out an instance of an XML document supplied to its constructor.  I filled a non-existent need because I was focusing on the pattern and not the problem.

It isn't all bad; let's look at how using patterns has helped me.

Good: Using patterns yields testable code.

Using patterns extensively has helped me write highly testable code.  Patterns and dependency injection go together like peanut butter and chocolate.  Having patterns peppered throughout the design, my code is highly decoupled.  Unit testing is a breeze in such a scenario, and unit tests are good.

Good: Using patterns makes complex code understandable.

Patterns isolate concerns.  This makes large codebases more digestible, and it tends to break complex relationships into lots of smaller objects.  I know many people would disagree with me here, but I find it easier to work with 50 small class definitions that a) follow well-understood patterns and b) adhere to the single responsibility principle than 5 classes that have been incrementally expanded to 20,000+ lines of code containing a succotash of concerns.  A coherent class diagram will tell me more about a system than a list of 200+ method names.

Good: Using patterns makes complex systems extensible.

Again, patterns isolate concerns, which makes extending a system very simple once you are familiar with the system design.  For example, adding a decorator is easier, in my opinion, to altering the behavior of an existing class.  Folding new features into a well-designed strategy, command, or visitor pattern is cake.  Patterns help you grow a system by extending it, not altering it, which is a good idea.

My two-step program to better pattern application

I've learned from my mistakes.  I've come to the conclusion that patterns are a tool best applied to existing working and testable code.  My personal commitment is to stop using patterns at the design phase, but continue employing patterns when they make sense.  How will I do this?

My two steps are simple - when I work on a software feature, I promise to do the following:

  1. Design and code the feature to a working state as quickly and simply as possible.  At this phase I promise not employ patterns a priori, although I may employ Dependency Injection to make testing easier.
  2. Refactor my code to separate concerns, remove duplication, and improve readability.  At this phase, I will employ patterns NOT wherever possible, but only as necessary to meet my goal.  That means I'll pull them in when I need to separate concerns, when I need to untangle spaghetti code, when I need to make the code understandable.  

I'll let you know how the rehab goes.  Until then, there's no place like code ... there's no place like code .... there's no place like code .....

String Theories

§ April 22, 2008 15:55 by beefarino |

Yesterday morning, my colleagues and I we were having a discussion about all the different string representations and abstractions we've had to work with over the course of our lives as programmers.  Here's the list I came up with, in rough chronological order of my exposure to them:

  1. TRS-80 BASIC - I have no idea how they were represented in memory because I've never gone back to that platform, but I assume it was just another character array.  If someone knows the specifics I'd LOVE to learn about it.
  2. Borland Turbo PASCAL character arrays
  3. C/C++ char* / char[]
  4. Win32 LPSTR, LPCSTR, and all the other constructs from the Win32 API that I had to learn about because Owen and Michael would insist on leaving STRICT defined (thanks guys!).
  5. MFC CString
  6. Javascript string objects 
  7. Perl $scalars - a string, a number, a reference, or all three, or perhaps none of those.  I once dug deep into Perl internals; I could tell you more than you care to know about scalars, memory management, type conversion inside of the Perl interpreter; of course, show me some of the perl I hacked up a few years ago and I won't be able to tell you what it does...
  8. C/C++ wchar* / wchar[]
  9. Win32 TCHAR* / TCHAR[] - yes, technically the same as either char* or wchar*, thanks for not commenting about it.
  10. BSTR -  WTFBBQ?!  OIC - its a pointer to the MIDDLE OF THE FRACKING STRING STRUCTURE so I have to do pointer calculus to determine the length of the string and suck out the relevant bytes....  well, thank goodness there's:
  11. __bstr_t - ok, a bit friendlier, but I'm still glad that there's: 
  12. CComBSTR - ah, a Length() method!  
  13. VARIANT - *sigh* .... the lengths to which I went to pacify OLE Automation lust.  
  14. __variant_t - ignored in favor of:
  15. CComVariant - use only when necessary, follow each use with a thorough handwashing.
  16. PHP strings - never learned the internals of PHP.  I assume it operates on the same type of abstraction as the Perl scalar - anyone know for sure?
  17. Java string objects - took some getting used to.  Why can I + two strings, but not two Matrices?  How does it make sense that a base Object return an instance of a derived type String in Object.toString()?  See what happens when an active mind is no longer consumed with memory and pointer management?
  18. .NET string objects

That's what I came up with in about 5 minutes of gazing longingly over my geek life.  I'm sure there are others - my list doesn't include all of the one-off custom implementations I've made, or the third-party tools we used to use for cross-platform application development, or stuff like XML tokens, entities, etc.

I created the list for fun, but it's got some pretty interesting aspects to it.  For one, the same basic string construct that I learned on that TRS-80 never really changed.  Sure, they're immutable objects now, but really their representation and purpose have persisted since my dad brought home that fat grey box with the tape drive and keyboard that sounded like a hole punch. 

Second, it's made me realize that I take a lot of stuff for granted these days.  Here's some code from somewhere between #8 and 9 on my list:

TCHAR *psz = new TCHAR[ iStringSize ]; if( NULL == psz ) {     return E_OUTOFMEMORY; } // ...
delete[] psz; psz = NULL; 

Even writing this as an example makes me very nervous.  A few years ago I wouldn't have batted an eye, but these days it feels like a lot of work to pull all of the allocation, pointer management, and deallocation together.  And this example really doesn't account for all the things that could go wrong...  

So I have to say that, all strings considered (*groan*), I'm pretty content with the state of the art.

Managing App.Config Integrity using Xml Digital Signatures

§ February 20, 2008 18:25 by beefarino |

Maintaining the integrity of your binaries is important.  After all, we've seen how simple it is for someone to crack open your assemblies and start muddling around, making your binaries do terrible ... unspeakable things.  Strong names help in this regard, as they are treated as a form of load-time validation.  But what about your application configuration file?  It's just sitting there, plain ol' XML, just begging to be tampered with.  Obviously we don't want to store any super-secrets in the app.config (and if we do, we certainly want to encrypt them), but there are times when the data in our app.config dramatically affects program behavior, and we just want to make sure the app.config can be trusted before we make any drastic decisions.

It is surprising to me that the .NET framework doesn't provide canned support for such app.config validation, especialy when there is a readily accessible solution...

XML Digital Signatures

The .NET framework provides a limited implementation of the XMLDSIG  (XML Digital Signature) specification.  In a nutshell, XMLDSIG specifies a procedure for calculating the digital signature of an XML node tree, and also provisions different ways of including the signature either with or external to the XML node tree.  The process can be summed up as follows:

  1. An XML node set is selected for signing.
  2. The XML node set is then canonicalized, which is a fancy way of saying that the node set is put into a standard representation.  For example, redundant XML namespace references are removed, and attributes are placed in alphabetic order.
  3. The canonical XML representation is then hashed using a standard hashing algorithm like SHA1 or MD5.
  4. The hash is signed using standard private/public key cryptographic techniques, resulting in the XML digital signature of the node set.
  5. The digital signature is either embedded in the document as a new XML element, or left out-of-band as a detached signature.  The signature can be validated by repeating the hash calculation process and comparing the result against the decrypted signature value.  If the node set is altered in any way, the hash will vary from the signature and anyone can figure out that the XML has been altered.

There are some big words and concepts in there, but taken in small bites none of it is very difficult to digest; it doesn't matter anyway because the .NET Framework does most of the heavy lifting for us.

Applying XMLDSIG to App.Config Files

Since app.configs are just XML files, XMLDSIG seems like a good choice for ensuring the integrity of those files.  Here are the things we need to accomplish:

  1. massage our app.config file to be able to contain the XML digital signature without breaking the standard .NET configuration subsystem;
  2. finalize our app.config contents;
  3. generate the XML digital signature of our app.config and embed it in the app.config file;
  4. have our program validate the app.config digital signature before it attempts to load any configuration values;

Since any one of these three things can be a post unto itself, I'm going to focus on the how.  If there is enough interest, I can elaborate on some of the whys in future posts.  If you just can't wait, Rick Strahl has a good example available, and InfoMosaic has a nice backgrounder

Let's get started.

Preparing the App.Config for the XMLDSIG Signature Element 

When an XML document contains its own digital signature, the signature is described as "enveloped," meaning that the document element surrounds the signature XML like an envelope surrounds a letter.  After our app config is signed, the root <configuration> element will contain a new child element; it will look something like this (all detail removed for brevity):


<configuration>   ...   <Signature xmlns="">     <SignedInfo>       <CanonicalizationMethod Algorithm="" />       <SignatureMethod Algorithm="" />       <Reference URI="">...</Reference>     </SignedInfo>     <SignatureValue>...</SignatureValue>     <KeyInfo>...</KeyInfo>   </Signature> </configuration>


We can't just plop this new element in the app.config and expect the .NET configuration manager to process it without knowing what it is; this will cause failure during application startup.  No special tricks here, we simply need to instruct the configuration system to ignore this element by adding the following to the top of the config file:


<configSections>     <section name="Signature" type="System.Configuration.IgnoreSectionHandler" />     </configSections> ...

The app.config is almost ready to accept the XML digital signature...

Finalizing the App.Config Contents

Once we apply the signature to the app.config, we won't be able to alter the app.config contents without invalidating the signature.  For our example, we need to make sure our application settings are set properly:


<configuration>     <configSections>         <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089">             <section name="XMLDSIGValidate.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089" />         </sectionGroup>         <section name="Signature" type="System.Configuration.IgnoreSectionHandler" />     </configSections>     <applicationSettings>         <XMLDSIGValidate.Settings1>             <setting name="ReallyImportantSetting" serializeAs="String">                 <value>if this value is altered, the application should not run</value>             </setting>         </XMLDSIGValidate.Settings1>     </applicationSettings> </configuration>

The only setting in this mess is on lines 12-13.  I set the value to something obnoxious, then move on to signing the file.

Generating the XML Digital Signature

There is no tool in the .NET SDK for applying XMLDSIG to a file, so we need to create one.  Here's the code, explanation of important stuff follows:

using System; using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Security.Cryptography.Xml;
using System.Security.Cryptography;
using System.IO;
namespace AppConfigSigner
    class Program
        static void Main( string[] args )
            // load the app config as an XmlDocument
            XmlDocument config = new XmlDocument();
            config.Load( args[ 0 ] );

            /* build up the XMLDSIG processor
             * we'll use the following elements in our signature:
             * - an enveloped signature transform; this will remove the
             *      actual Signature element from the document tree during
             *      XMLDSIG validation
             * - an empty Reference URI; this will indicate that the signature is applied
             *      to the entire containing document
             * - a default RSA signature key pair
            XmlDsigEnvelopedSignatureTransform transform = new XmlDsigEnvelopedSignatureTransform();
            Reference reference = new Reference();
            reference.Uri = "";
            reference.AddTransform( transform );
            // create the XMLDSIG processor
            SignedXml xmldsig = new SignedXml( config );
            xmldsig.AddReference( reference );
            // set the signature key
            xmldsig.SigningKey = new RSACryptoServiceProvider();
            /* configure the key info elements of the signature;
             * this will instruct the XMLSIG validator on how to
             * obtain the public key to validate the signature.
             * in our case, we're simply dumping the public key
             * right into the Signature element.  in production
             * this is a REALLY BAD idea, but it keeps the example
             * simple
            xmldsig.KeyInfo = new KeyInfo();
                new RSAKeyValue( ( RSA )xmldsig.SigningKey )
            XmlElement signature = xmldsig.GetXml();
            XmlNode signatureNode = config.ImportNode( signature, true );
            config.DocumentElement.AppendChild( signatureNode );
            /* save the config file
             * note that we need to retain control over the file encoding
             * and the XML formatting to keep the signature valid.
             * if you try this:
             * config.Save( args[ 0 ] );
             * you may never get a valid signature because the XmlDocument class
             * will pretty-up the XML with whitespace that wasn't there during
             * signature generation
            using( FileStream fs = File.OpenWrite( args[ 0 ] ) )
                using( XmlTextWriter writer = new XmlTextWriter( fs, Encoding.UTF8 ) )
                    config.WriteTo( writer );

The program does three things:

  1. Load an XML file specified on the command line;
  2. Sign the XML;
  3. Save the XML file back to its original location.

To calculate the XML digital signature, we need to specify few items; minimally:

  • what XML is being signed - this is called a Reference in XMLDSIG speak;
  • the private/public key pair to use for signing operations;

In addition, we may also want to include information that the signature validator can use to find the appropriate public key during signature validation.  This is referred to as the XML digital signature KeyInfo, or sometimes the KeyInfo clause.

Creating the Signature 

The signature generation begins on line 30 with the creation of our Reference.  The XMLDSIG spec allows an XML digital signature to apply to all or part of an XML node set; the reference object is the way we identify what XML is being signed.  By supplying an empty URI value on line 32, we are indicating that the signature applies to the containing XML document.

On line 36, the SignedXml instance is created.  This is the class that will do the XMLDSIG heavy lifting.  Line 37 adds our Reference to the XMLDSIG processor.

Line 40 supplies the XMLDSIG processor with the signature key pair.  In this example, I'm using a randomly generated key set each time the config is signed; in production, you will likely want to use a specific key set every time.  

Lines 52-55 add key information to the XML digital signature.  Whoever will be verifying the app.config integrity will need to know what public key will validate the XML digital signature.  There are a plethora of options as to how to communicate public key information between two parties, enough best practices to fill a book.  To keep things simple (vs. secure), line 53 merely dumps the entire public key BLOB right into the XML digial signature.  No prizes for realizing this is a VERY BAD IDEA; there should be a very formal mechanism of public key exchange between the app.config signer and the app.config validator.  That's another post, let's get this working for now.

Line 57 calculates the signature of the app.config, and 59-62 add the XML digital signature to the app.config. 

Save the XML Delicately

The rest of the program saves the signed app.config.  This can be tricky business, as ANY significant alteration of the XML will result in the signature becoming invalid.  What's a significant alteration you ask?  Well, the addition of any whitespace for one, element ordering, text node changes of course, or the encoding of the XML.  I find that you cannot simply call the Save method of the XmlDocument class; the resulting XML is somehow invalidated during the write due to the addition of whitespace.  Your mileage may vary; if you find a better way, let the world know.

Validating the App.Config Digital Signature

The application in question will need to validate the digital signature of its app.config before it attempts to load any configuration values.  If the app.config is validated against its signature, then the application can merrily load up any values it needs, fully trusting that the configuration file is in a proper state.  If the file fails validation, the application knows that the configuration file has been tampered with and cannot be trusted.

Let's look at a sample program: 

using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography.Xml;
using System.Xml;
using System.Configuration;
using System.Security.Cryptography;

namespace My
    static class Program
        static void Main(string[] args)
            // discover the path to the app config
            string configFilePath = ConfigurationManager.OpenExeConfiguration( ConfigurationUserLevel.None ).FilePath;

            * load the app config as an XmlDocument
            * it is vitally important to preserve any whitespace in
            * the original document, as the XMLDSIG spec defines ALL
            * whitespace as SIGNIFICANT
            XmlDocument config = new XmlDocument();
            config.PreserveWhitespace = true;
            config.Load( configFilePath );

            // Create and initialize the XMLDSIG processor from our app config XmlDocument
            SignedXml xmldsig = new SignedXml( config );

            // find the XMLDSIG element
            XmlElement signature = ( XmlElement )config.GetElementsByTagName( "Signature" )[ 0 ];

            // load the XMLDSIG element into the XMLDSIG processor
            xmldsig.LoadXml( signature );

            // check the result of the signature
            bool result = xmldsig.CheckSignature();

            Console.WriteLine( result );

All this program does is validate the signature on its app.config and write the result of that validation to the console.

On line 26, the configuration XML document is told to preserve whitespace during load.  This is vital to proper XMLDSIG processing.  Normally the XmlDocument class will ignore "pretty-print" whitespace that exists between element nodes, but XMLDSIG considers this whitespace significant, so we need to make sure it gets into the XML node tree.

Line 30 initializes the XMLDSIG processor with the configuration XML document.  This is the document we need to validate.

Line 33 locates the XML digital signature element embedded in our app.config.  This element was added by our signer application.  The signature is fed to the XMLSDIG processor in line 36.

Line 39 is the money: the XMLDSIG processor is instructed to validate the app.config XML document against the digital signature by invoking the CheckSignature method.

The remainder of the program outputs the state of the app.config: True if the file is valid, False if it isn't. 

Do I Really Need to do This?

I tend to use DI/IoC a lot, and I tend to use one or more frameworks for configuring IoC containers, and they tend to like to read their configuration from my application configuration file, and I tend to wrinkle at the possibility of someone being able to modify my well-planned object graph with a little text file tinkering.  I've seen projects with configuration settings named "DisableSecurity" and "EnablePremiumFeatures" and yes the settings do exactly what you think they do.  In these cases I think this technique is valuable.

The question you need to ask yourself is: what could happen to my application if I can't trust my configuration file?  Consider the possibilities, and you'll have your answer.

Tune In 

I think this is a pretty kewl technique, if you think so too then grab the code and play around with the possibilities.  If there's interest and I get some time, I'd like to expand on some of the ideas started in this post. (8.43 kb)

Exposing your privates the IL way!

§ February 10, 2008 15:55 by beefarino |

Here's a quick hack you can use to pry open those pesky closed types in a .NET assembly, even if you don't have the source code.  It also demonstrates the openness of managed platforms like .NET and Java.

NOTE: The procedure involves some simple decompilation techniques, so be sure you have legal hudspa to reverse whatever you're reversing.

The hack is quite simple:

  1. disassemble the .NET assembly using the ILDASM disassembler available in the .NET SDK;
  2. modify the disassembled IL code, changing private types / methods / properties / fields to public as necessary;
  3. reassembly the .NET assembly using the ILASM assembler, also available in the .NET SDK.

I'll walk through the technique using a simple example.  Take a quick look at the source code for a simple console application named myprogram.exe:

 namespace My
    static class Program
        static void Main(string[] args)
            Console.WriteLine( Message );

        static string Message
                return "this message is top secret";

The code defines one class, with one method and one property, and everything is private.  Our goal for today will be to make all of these things publically accessible without accessing this original source code.

Step 0: Create the Assembly ...

Build the sample code into an assembly named myprogram.exe using your favorite C# compiler.  If you want, try to referece the Program class in another assembly or project, and you'll notice that there are no publically visible types exposed by the myprogram.exe assembly.

If you have a flair for the dramatic, then you can delete the source code at this point since we don't need it anymore.

Step 1: Disassemble ...

The first step is to disassemble the .NET assembly using ILDASM:

ILDASM <assmebly-file> /nobar /out=<output-file> 

where <assembly-file> is the file name you want to disassemble, the /nobar switch supresses a UI progress bar, and the /out argument specifies the <output-file> that will contain the disassembly code.

The result of the above command is usually two new files, an IL file containing the disassembly, and a RES file containing the compiled resources from the assembly. 

For our purposes, we'll dump the IL into a temporary code file:

ILDASM myprogram.exe /nobar /

Step 2: Modify the IL ...

Step two is the nut of the hack.  If you've ever worked in assembler, but have never seen IL, you're in for a real treat (if you've never seen assembler and prefer not to dwell into such lands, you may want to skip the next section).

Sidebar to IL-town

Many of the CLI constructs that occur in the C# language appear almost verbatim in IL, making our current task excessively simple.  Crack open the file in your favorite code editor and gaze upon the IL rendition of myprogram.exe:

// note: assembly metadata removed for brevity

.class private abstract auto ansi sealed beforefieldinit My.Program extends [mscorlib]System.Object
  .method private hidebysig static void  Main(string[] args) cil managed
    // Code size       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  call       string My.Program::get_Message()
    IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ret
  } // end of method Program::Main

 .method private hidebysig specialname static string  get_Message() cil managed
    // Code size       11 (0xb)
    .maxstack  1
    .locals init ([0] string CS$1$0000)
    IL_0000:  nop
    IL_0001:  ldstr      "this message is top secret"
    IL_0006:  stloc.0
    IL_0007:  br.s       IL_0009

    IL_0009:  ldloc.0
    IL_000a:  ret
  } // end of method Program::get_Message

  .property string Message()
    .get string My.Program::get_Message()
  } // end of property Program::Message
} // end of class My.Program


Ignore all of the stuff that looks like gibberish for now - what I want you to note is that the class, method, and property-get accessor definitions are recognizable and follow predictable patterns.  Note also that they are each explicitly marked as being "private."  Sorry, but no prizes for guessing what comes next...

Modify the IL using simple text processing

The IL is just text, so we can do a simple search-and-replace with our favorite editor to make the modifications we need.  If we need to get fancy or specific, the signatures adhere to patterns well-suited for simple regular expression matching.  Whatever our scope, we simply need to change the declarations of interest from "private" to "public" (changes hilited):

.class public abstract auto ansi sealed beforefieldinit My.Program extends [mscorlib]System.Object
  .method public hidebysig static void  Main(string[] args) cil managed
  // ...
  .method public hidebysig specialname static string  get_Message() cil managed
  // ...
} // end of class My.Program


Step 3: Reassemble ... 

The IL doesn't do us any good in text form - we need the binary the IL describes.  Thanks to ILASM, the binary just a command line away...

ILASM /exe /output=<assembly-file> /res=<res-file> <source-file>

where /exe means we want to build an executable assembly, /output identifies the <assembly-file> we want to create, /res identifies a <res-file> referenced within the assembly.  Let's reassemble the open version of myprogram.exe:

ILASM /exe /output=open.myprogram.exe /res:temp.res 

This will produce a new executable named open.myprogram.exe that behaves identically to the original.  Granted, the final result of this effort may not appear terribly impressive, until you try to reference this new assembly in another project.  You'll find that the My.Program class and its members are all publically visible usable in your new project.

So ... What?

How often will you really need to expose hidden members and types without access to the original source?  Granted it will be infrequent, if ever.  I've done it enough times in the arcane projects I end up on to script the process in powershell.

And I'm not trying to prove that access modifiers fail to constitute a security platform.

The thing I find really interesting about this technique is the breadth of things you can accomplish with little to no background in reversing (the author being a case-in-point).  With a little effort and some googling on IL you can use the same basic technique to accomplish all of the following:

  • alter the behavior of a sealed type;
  • virtualize type members at whim;
  • remove the strong name from an assembly, or replace the existing strong name with another;
  • add or remove metadata to the assembly, types, or type members;
  • intercept and forward all calls from one method or type to another, as in a man-in-the-middle attack;
  • etc.

Accomplishing these kinds of things used to require specialized and esoteric knowledge, like "e9 is the machine code for an absolute jump on an x86 processor".  But in .NET and other managed platforms like Java, these things become so accessible you can practially leverage the original code during the reversing process.

... I'm not sure whether to stop grinning or shivering ...