C# Reversing - MSIL Patching [Part 1]

Hey mates!

Maybe some of the elder members remember my series about C# CrackMe Challenges. After a little break where I focussed on other stuff I’m now back with an introduction to MSIL patching. Before you start with this post I recommend you to have a look at my other parts first :wink:. They teach some fundamentals which I won’t cover here.

Moreover you shouldn’t expect a typical tutorial. There are great tutorials out there written by more experienced reverse engineers. I just want to give you an insight into the topic and teach you some basic things which will help you out when you move further on :slight_smile:.


MSIL

The Microsoft Intermediate Language is the representation of .Net code ready for being executed by a Virtual Machine or to be compiled into Native Code. It reminds of Assembler instructions due to it’s bytecode-style but is not as low-level. All we have to know is that it’s the code we can find when we get a .Net-executable. So when you want to reverse a .Net-application, MSIL is your new best friend :grin:. For more information have a look at WikiPedia.


Why Don’t Just Decompile?

If you’ve read my other series, you probably wonder why we aren’t just decompiling into source code and working with it. Yep, good objection. Maybe it seems to be the easiest solution but sometimes a decompiled Visual Studio project produces errors. Or it’s just too easy and not 1337 enough for us :grin:. Anyway, I recommend you to know your enemy, so if you prefer working with the source code it’s okay but you should know how you could do it without it :wink:.


Preparing The Environment

For decompiling I usually prefer dotPeek but this time we’ll need ILSpy and as plugin Reflexil. Please download both of them before we continue. Reflexil can be easily installed by copying the .dll into ILSpys directory.


Our Target

As a target I’ve found a crypter and a binder. They were both obfuscated with CliSecure but that’s an easy challenge for de4dot :wink:. See my previous series for a tutorial on using it. This time I already cleaned both of them for you :slight_smile:. If you cracked one of them, the other one’s pretty futile but maybe you want to test it out more than one time :grin:.

At this point I highly recommend you to spot the license-checking on your own. You won’t need much experience to know how it can be circumvented… Come back when you’ve got a plan how you’d change the source to bypass it!


Description Of My Patch

Have you found a way on your own? Okay, I trust you :wink:. The patch in this case is pretty easy. First we have to spot the place where the license checking is done. I use Binder_Load() but you could also patch the checking in other parts of the code. Maybe you want to do that as homework?

        private void Binder_Load(object sender, System.EventArgs e)
        {
            try
            {
                this.class1_0.method_0();
                string text = System.IO.File.ReadAllText(System.Windows.Forms.Application.StartupPath + "\\License\\binder.license");

                if (text.Length > 0)
                {
                    string[] array = this.class1_0.method_1(text);
                    this.kryptonLabel2.Text = string.Concat(new string[]
                    {
                        array[0],
                        " - ",
                        array[1],
                        " - ",
                        array[2]
                    });

                    this.bool_0 = true;
                }
            }
            catch
            {
                KryptonMessageBox.Show("Invalid license file!", "License Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
            }
        }

I think there’s not much to explain. The first function class1_0.method_0() uses some anti-debugger stuff. Not interesting for us but maybe you want to have a look at it? In our case it never triggers so we can just ignore it. After that it tries to read a license file. Of course we haven’t such a file so the catch-block is triggered which tells us that our version is unlicensed. If everything would run fine a boolean at the end would be set to true. Mmh… Could that be something like bIsLicensed = true? I shorten it here a bit up with telling you that it’s the boolean which is used for identifying whether the program is licensed or not.

What to do now? Again there are different ways of solving the problem. You could just comment everything except the boolean out, set the boolean already in the beginning of the method to true, etc… I decided to use the second method because it’s more interesting than just commenting some stuff out :wink:.

How will the function look like when we’re finished? Because we just copy the line in front of the other code it’ll look like this:

        private void Binder_Load(object sender, System.EventArgs e)
        {
            try
            {
                this.bool_0 = true;  // Here we add our little one-line patch

                this.class1_0.method_0();
                string text = System.IO.File.ReadAllText(System.Windows.Forms.Application.StartupPath + "\\License\\binder.license");

                if (text.Length > 0)
                {
                    string[] array = this.class1_0.method_1(text);
                    this.kryptonLabel2.Text = string.Concat(new string[]
                    {
                        array[0],
                        " - ",
                        array[1],
                        " - ",
                        array[2]
                    });

                    this.bool_0 = true;
                }
            }
            catch
            {
                KryptonMessageBox.Show("Invalid license file!", "License Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
            }
        }

I hope you understood our devious plan :smile:.


Using Reflexil

Now that we’ve got an aim to achieve, we can start with patching the MSIL code. Start ILSpy, open the Binder/Crypter (Both work the same) and go to the Binder(or crypter)_load() method. Then click on View at the top bar and select Reflexil. If everything worked fine, you should see a new window at the bottom.

Reflexil is very intuitive so I think you won’t have any problems with it. Just select the method we’re going to patch on the left navigation bar and it’ll automatically show us the MSIL code.

Now scroll through the code and search for something interesting. Reflexil already commented on some of the lines, so that you don’t even have to read the OpCodes :grin:. In my case I’ve saw on line 53 how the bool is activated.

To patch the program just copy these 3 lines to the beginning of the method:

If you want to save the patched crypter/binder now, just rightclick on it in the left navigation bar and chose Save As.

Finished!


Conclusion

When you want to make a fast inline patch, MSIL is essential. I highly recommend you to have a look at it and Reflexil when you got hooked :wink:.

|-TheDoctor-|

6 Likes

There are a few things in this world that are very underrated. Your proficiency in C# is one of them.

Good job as usual.

-Phoenix750

1 Like

I usually use dnSpy, it’s an upgraded version of ILSpy

1 Like

Glad to here that from you :slight_smile:. I’m excited for your next hardware posts :wink:.

Never heard of it before but it seems to be really cool :grin:. I’ll have a look at it within the next few days!