Jump to content
Nytro

.NET: Binary Modification Walkthrough

Recommended Posts

.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.png?w=614&h=184

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

redroll.png?w=614

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:

deobfuscated1.png?w=614

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.png?w=614&h=363

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.png?w=614&h=233

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.png?w=614&h=344

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.png?w=614

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.png?w=614&h=362

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, but now I need to address the Strong Name Signing on the binary, otherwise I will not be able to save and execute these changes. There are various tutorials on this subject, but for the purposes of this project I simply enabled Strong Name bypass for this application, as is described here. 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.png?w=614&h=380

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

Sursa: .NET: Binary Modification Walkthrough | I am not interesting enough to have a blog.

Edited by Nytro
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...