.NET Is Not a Black Box, Open It Up
Recently I’ve been working with a site that has had a ton of problems. The latest issue was that we needed to configure the Active Directory integration which involved setting up an .exe that handled importing users. Unfortunately, with the cloud hosting of the CMS, the .exe didn’t work.
Complain
I contacted support and they basically said I was shit outta luck! They basically told me I needed to upgrade to the latest version in order to use that feature with their cloud hosting.
Now What?
Better give up and tell the customer… right?
Nope. Screw the CMS vendor, let’s fix it ourselves.
So what does the AD import utility actually do?
- Take SQL Server Credentials
- Take AD Credentials
- Map fields
- Import the data from AD into SQL Server
Sounds simple enough, now what’s the problem? Here is a screenshot of the actual error:
After speaking with support and googling around I figured out that sp_databases
is a system stored procedure in SQL Server that lists out the databases on the server. Since the CMS is using a certain type of cloud hosting, we don’t have access to that stored procedure. But that shouldn’t really matter. We already have all the connection information handy. I’m guessing that the utility is doing an extra call to sp_databases
.
Identify The Issue
Now that we’ve formed a hypothesis about why the error is occurring, how do we actually fix it?
Luckily for us, .NET and things created with .NET are not black boxes. Let’s crack open the .exe and try and find the specific problem with the code.
For examining the assembly (.dll or .exe) we have a myriad of options:
- ILSpy - My goto favorite since it’s open source.
- Telerik JustDecompile - A good free option.
- Red Gate .NET Reflector - Paid product, but supposedly the best.
I think I originally started with ILSpy to identify the issue. However, identifying the issue is only so valuable. Now I needed to fix it.
Fix The Issue
ILSpy will allow you to save the decompiled C# code to disk, but then we would have to manually recompile it. Another option would be to use the IL Dissembler (Ildasm.exe) to decompile the assembly into it’s IL, but that would require a little bit of work too. It’s 2014, let’s take the easy way out.
With a bit more googling I found Reflexil, “The .NET Assembly Editor”. From the homepage:
Reflexil is an assembly editor and runs as a plug-in for Red Gate’s Reflector and Telerik’s JustDecompile. Reflexil is using Mono.Cecil, written by Jb Evain and is able to manipulate IL code and save the modified assemblies to disk. Reflexil also supports C#/VB.NET code injection.
PERFECT.
So I grabbed JustDecompile, opened up the plugin manager, and installed the Reflexil plugin which is labeled as “Assembly Editor” in the plugin list.
Armed with the Reflexil plugin let’s take a look at what I found:
OK that’s a lot of information, let’s dissect the steps needed to follow along:
- Open the Reflexil plugin from the plugin menu.
- Like in any other IL explorer/decompiler, find the code in question.
- Click the method name which causes Reflexil to load the IL just for that method.
- Look for identifiers in the IL. In this case we can see that there is the string
"Step2_ErrorConnectingDB"
in the C# code which appears directly in the IL. - After finding the general are of the code, find the actual code in question. In this case we can see that we’re setting the
connectionResult
tofalse
in C#. In the IL we can see that the variable is being worked with on instruction 081. - Analyze the details. IL does one thing at a time. Instruction 081 is setting up the variable to be worked with. Instruction 082 is setting it to false (0) with
ldarg.0
. - Make the change (shown in the third image). Right-click on the instruction and select “Edit…”. Change it to
ldarg.1
(true, or the value 1). - Save out the updated assembly. In the tree view, right-click on the .exe and select “Save as…” and save the patched assembly.
- Take the rest of the day off.
And there you have it! I prevented having to tell the customer that they would need to upgrade their CMS, all in about 2 hours. The result was that the error message flickers in the step for a split second before the wizard just proceeds to the next step.
Conclusion
While this sort of thing is usually a last resort, it is definitely something you can do, even without deep knowledge of IL and how .NET works. I know next to nothing about actual IL code, I just googled the instructions to find out what they did.
So the next time you encounter a .NET .exe or DLL you don’t have the source for, don’t be afraid to take a peak inside and maybe even change something!