//
you're reading...
.NET, infosec, tech

.NET: Binary Modification Walkthrough

As I kept promising but failing to do, as I am an unregenerate procrastinator, here is a step-by-step of the binary modification I demonstrated during my Summercon, NordicSec, and Brucon talks. I chose Red Gate Reflector for my target app– partly for the “Yo dawg”/ Inception jokes, and partly because, as we’ll see later in this blog post, the folks at Red Gate seem to have a bit of a sense of humor about such things.

As with most binaries you’ll end up working with, Reflector is obfuscated. The obfuscation used here is SmartAssembly– not surprising, since this is Red Gate’s obfuscation product. This is easily confirmed using de4dot deobfuscator:

>de4dot.exe -d "C:\Program Files(x86)\Red Gate\.NET Reflector\Desktop 8.0\Reflector.exe"
de4dot v2.0.3.3405 Copyright (C) 2011-2013 de4dot@gmail.com
Latest version and source code: https://bitbucket.org/0xd4d/de4dot
Detected SmartAssembly 6.6.0.147 (C:\Program Files (x86)\Red Gate\.NET Reflector\Desktop 8.0\Reflector.exe)

Opening the binary in Reflector in its original state, we can clearly see signs of obfuscation. Symbols have been renamed to garbage characters and methods cannot be displayed.

obfucation

Some, however, have their original names. Well played, Red Gate. I dub this the “RedRoll.”

redroll

Running the app through de4dot improves the readability somewhat and reverts the binary enough that methods can be resolved. However, since the original symbol data has not been stored, the deobfuscator is forced to assign generic names:

deobfuscated

Now that we have a deobfuscated binary, we can start to analyze and modify it. I’ve been relying on two add-ons to make this easier: CodeSearch (as Red Gate’s native search functionality is somewhat lacking,) and Reflexil (for assembly modification.)

For this demonstration, I decided to modify Reflector to add some functionality that I felt was sorely lacking. My goal is to introduce new code into the binary and add a toolbar icon to launch it. Since we mostly have generic symbols to work with, it’s going to be a bit more of a challenge to identify where existing functionality is implemented as well as where to inject our own code.

When analyzing a binary, it helps start with a list of goals, or at the very least touchpoints that you wish to reach. This list will undoubtedly change as you become more familiar with the app; however, it will help provide structure to your analysis. This especially helps if, like me, you tend to jump around haphazardly as new ideas pop in your head. For this particular undertaking, I fleshed out the following steps:

  • Identify where toolbar icons are created and add icon representing the new functionality I’ll add
  • Identify where toolbar icons are linked to the functionality/functions they invoke
  • Insert an assembly reference to a DLL I’ve created into the application
  • Create a new function inside Reflector invoking the functionality implemented in my DLL
  • Link my tool icon to my own function

Because symbol renaming was one of the obfuscation techniques performed on this binary, locating the toolbar implementation will require a little digging, but not much. By searching for one of the strings displayed when mousing over a toolbar icon, “Assembly Source Code…,” I was able to determine the toolbar is implemented in Class269.method_26().

finding_toolbar

Making an educated guess from the code above, the toolbar is created by various calls to Class269.method_29(), passing in the toolBar, the image icon, the mouse over text, keybindings, and a string referring to the function invoked when the icon is clicked.

In order to add my own toolbar icon, I’ll need to add another of these calls. This can be done using Reflexil to inject the IL code equivalent, as seen below:

adding_IL

The IL written to add the appropriate call is:

 IL_01ae: ldarg.0
 IL_01af: ldarg.1
 IL_01b0: call class [System.Drawing]System.Drawing.Image ns36.Class476::get_Nyan()
 IL_01b5: ldstr "Nyan!"
 IL_01ba: ldc.i4.0
 IL_01bb: ldstr "Application.Nyan"
 IL_01c0: call instance void ns30.Class269::method_29(class Reflector.ICommandBar, class [System.Drawing]System.Drawing.Image, string, valuetype [System.Windows.Forms]System.Windows.Forms.Keys, string)
 IL_01c5: ldarg.1
 IL_01c6: callvirt instance class Reflector.ICommandBarItemCollection Reflector.ICommandBar::get_Items()
 IL_01cb: callvirt instance class Reflector.ICommandBarSeparator Reflector.ICommandBarItemCollection::AddSeparator()
 IL_01d0: pop

PROTIP: If you’re lost on what IL instructions to add, try writing a test app in C# or VB .NET, then use the Disassembly Window in Visual Studio or the IL view in Reflector to see the equivalent IL.

You can see that in this IL, I make a call to ns36.Class476::get_Nyan(). This is a function that I’ll create that returns a System.Drawing.Image object representing the icon to be displayed in the toolbar. I’ll also need to find out where to associate the “Application.Nyan” string with the function that actually calls the functionality I wish to invoke.

Doing a bit of digging into the Class476 functions, I end up determining that they are returning the images by slicing off 16×16 portions of CommandBar16.png. This means that I can add my toolbar icon to this image, which lives in the Resources section of the binary, and carve it off as well:

toolbar

I can then add the get_Nyan() function, modeling it off of the other image-carving functions in Class476.

.method public hidebysig specialname static class [System.Drawing]System.Drawing.Image get_Nyan()cilmanaged
{
    .maxstack 2
    .locals init (
        [0] class [System.Drawing]System.Drawing.Image image)
    L_0000: ldsfld class [System.Drawing]System.Drawing.Image[] ns36.Class476::image_0
    L_0005: ldc.i4.s 40
    L_0007: ldelem.ref 
    L_0008: stloc.0 
    L_0009: leave.s L_000b
    L_000b: ldloc.0 
    L_000c: ret 
}

With that done, I need to find where those pesky strings are linked to actual function calls. By searching for one of the strings (“Application.OpenFile,”) I find it referenced in two functions that look promising– Execute() and QueryStatus()

finding_calls

Looking inside Class269.Execute, I see that this function creates a dictionary mapping these strings to function calls.

public void Execute(string commandName) 
{ 
    string key = commandName; 
    if (key != null) 
    { 
    int num; 
    if (Class722.dictionary_4 == null) 
    { 
        Dictionary<string, int> dictionary1 = new Dictionary<string, int>(0x10); 

        dictionary1.Add("Application.OpenFile", 0); 
        dictionary1.Add("Application.OpenCache", 1); 
        dictionary1.Add("Application.OpenList", 2); 
        dictionary1.Add("Application.CloseFile", 3); 
…
        Class722.dictionary_4 = dictionary1; 
    } 

    if (Class722.dictionary_4.TryGetValue(key, out num)) 
    { 
        switch (num) { 
        case 0: this.method_45(); break; 
        case 1: this.method_46(); break; 
        case 2: this.method_47(); break; 
…

 }

QueryStatus() is structured in much the same way. I add my own dictionary entry mapping “Application.Nyan” to the function nyan() with the following IL to add the dictionary key…

IL_00d5: dup    
IL_00d6: ldstr "Application.Nyan"    
IL_00db: ldc.i4.s 16    
IL_00dd: call instance void class [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1)

…and the function mapping:

IL_01c0: ldarg.0    
IL_01c1: call instance void ns30.Class269::nyan()    
IL_01c6: leave.s IL_01c8

You’ll notice above that I reference a function called nyan(). This is the function I’ll use that will implement the functionality the icon click will invoke. I could write this functionality entirely in IL, but I’m actually not much of a masochist. What I decided to do instead was to write a DLL containing the functionality I wanted. This assembly, derp.dll, was added as an assembly reference as follows:

adding_assembly

I can then insert IL for the nyan() function into Class269:

.method private hidebysig instance void nyan() cil managed
{
    .maxstack 8
    L_0000: newobj instance void [derp]derp.hurr::.ctor()
    L_0005: callvirt instance void [derp]derp.hurr::showForm()
    L_000a: ret 
}


This is about all the modification needed. If you’re modifying an assembly that is a dependency, you’ll need to address the
Strong Name Signing on the binary. There are various tutorials on this subject, but if you’re only running your code locally, you can simply enable Strong Name bypass using the command SN -Vr AssemblyName. Reflexil will also allow you to do this upon saving the modified binary.

With the binary saved, I can now launch it. Now, if anything has been done incorrectly, your application will crash with a .NET runtime error either when you launch it or when trying to invoke the new functionality. For this reason, I saved my work and checked that it executed properly periodically throughout the process above. Below shows my new toolbar icon and the result of clicking it:

nyanmode

I feel that Nyan mode greatly enhances the Reflector user experience and hope that RedGate will consider adding it to a future release.

Discussion

One thought on “.NET: Binary Modification Walkthrough

  1. something of note if one doesn’t want to rely on only proprietary tools to do modifications and wants to remain an opensource whor^Wpurist.

    ilasm.exe and ildasm.exe which come with the .net sdk allow you to fully disassemble and reassemble a .net assembly. one plugs into the other which is kind of neat. this allows you to use a real text-editor to monkeypatch your target .net code and also to rip entire snippets out of another assembly you’ve built. plus, there’s already existing functionality in link.exe which can provide you tools for dealing with manipulating assets in your exe. lastly, ilspy.exe is a free tool that isn’t mentioned nearly enough as an alternative to reflector for dealing with decompilation and navigation for pinpointing your cares. and fuck red gate for making their .net reflector setup delete the original installer and any older ones.

    Posted by Ali Rizvi-Santiago | November 1, 2013, 02:48

the twitters

Follow

Get every new post delivered to your Inbox.

Join 5,982 other followers

%d bloggers like this: