/ cracking c#

Short guide to C#/WPF application cracking

As a software developer I know that it’s almost impossible to keep your application secured from reverse engineering. You can take many approaches to keep it safe like checking CRC’s, preventing application from running if it finds debugger/disassembler settled in the system etc, but no matter what you’ll try to do, you should always end with checking if your methods are good enough. Probably the best way to check if your application is secured in a right way is to try to crack it on your own and see what will happen.
In the following few steps I’ll show you how to crack basic protection in a C# application. Please note that the same will apply also to WPF applications.
THIS GUIDE IS FOR EDUCATIONAL PURPOSES ONLY. REVERSE ENGINEERING IS MOST OFTEN FORBIDDEN BY SOFTWARE LICENSES AND BY DOING THIS YOU MAY BREAK THE LAW. I’M NOT RESPONSIBLE FOR ANY DAMAGE CAUSED BY THIS GUIDE NEITHER FOR ANY ILLEGAL PURPOSES FOR WHICH THIS GUIDE MAY BE USED. YOU’RE DOING EVERYTHING MENTIONED IN THIS TUTORIAL ON YOUR OWN RESPONSIBILITY WITHOUT ANY RIGHT TO BLAME ME. IF YOU DON’T AGREE WITH THESE RULES YOU CAN STOP READING THIS POST. THANKS FOR UNDERSTANDING.
For this tutorial we’ll write simple C# application which will help us to better understand how things work in this language. If you tried your skills in Win32 apps cracking you’ll notice the difference. Our test application will look like that:

using System;
using System.Text;

namespace Cracking_test {
    class Program {
        static void Main(string[] args) { 
            Console.WriteLine("Enter the password:");
            string pass = Console.ReadLine(); 
            if (pass == "secretpass") 
                Console.WriteLine("Password correct!");
            else Console.WriteLine("Wrong password!");
            Console.ReadKey();
        }
    }
}

The application will simply ask the user for a password and check if the one provided by him is equal to "secretpass". If yes he’ll get the information that the password is correct, if not he’ll get “Wrong password!” as a result. What we’ll try to do in this case is to modify the executable of this application, so if the user will provide an incorrect password the system will "think" the password is correct. For this purpose we’ll make use of two tools shipped with .NET Framework (for best effects you should always have all versions of .NET Framework installed): ildasm and ilasm. The first one can be found in:

C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin

It’ll be used to decompile our test application into an IL language which is something similar to Assembler. The second tool (ilasm) can be found in several places in C:\Windows\Microsoft.NET\Framework folder. It’s like that because every framework has its own version of this tool, so if you’ll be dealing with an application compiled against .NET Framework 2.0 you’ll have to use ilasm located in v2.0 folder, because in other way the compilation will be successful, but the executable file will crash at startup. As mentioned previously this tool will be used to build our modified executable file from IL code back to an executable file.
So, if you have all required tools let’s get going:

  1. First what we need to do is to check the behavior of our application before modifications, because we need to know what we want to achieve. Let’s run the executable and try any wrong password. We see that the application is showing us “Wrong password!” message as a result. Write down this message, because we’ll use it in the further part of this guide. Now let’s play with the *.exe file.

  2. We need to decompile our executable file into IL code, so to do that open command prompt, change worging directory to the location of ildasm.exe and decompile your executable with the following command:

ildasm "c:/Cracking test.exe" /OUT="c:/Cracking test.il"

This will result with creation of "Cracking test.il" and "Cracking test.res" files in the directory specified by path given in /OUT parameter.

  1. Open the *.il file with some text editor and start looking for the string which we wrote down in first step ("Wrong password!"). After a few seconds you’ll find the lines looking like that:

    IL_0021: ldloc.1
    IL_0022: brtrue.s
    IL_0031 IL_0024: ldstr "Password correct!"
    IL_0029: call void [mscorlib]System.Console::WriteLine(string)
    IL_002e: nop
    IL_002f: br.s
    IL_003c
    IL_0031: ldstr "Wrong password!"
    IL_0036: call void [mscorlib]System.Console::WriteLine(string)

  2. Let’s analyze this code a little. On the left side you see addresses from IL_0021 to IL_0036, next you see an IL mnemonic similar to Assembler and on the right side you see the operands. Now, we see that in line with address IL_0022 we have a brtrue.s function which is basically some kind of jump function used in IL language. This function takes an address of IL_0031 as a place to which it’ll jump. As we can see the place which is the destination of this jump is the ldstr "Wrong password!" which loads a string, so it can be later used by WriteLine() function. So let’s try to change our jump so it’ll act in the opposite way: change brtrue.s to brfalse.s and write the changes to the *.il file which we’re analysing.

  3. Now we need to compile our modifications to check what we’ve just done. Let’s cd to

C:\Windows\Microsoft.NET\Framework

and then to the framework version which we used while we compiled our application, in my case it’ll be v4.0. There’s an ilasm.exe application which will compile my *.il file against .NET Framework 4.0. Let’s execute the following command:

ilasm "c:/Cracking test.il"

and we should see "Operation completed successfully" message in our command window. So let’s now check our application which has been created in the same place where our *.il file is located. Let’s check whatever password we want, e.g. "aaa" and voila! Our program accepts this password as a correct one! But wait! What with "secretpass" password which is the real correct password for this application? Let’s check it and… BOOM! "Wrong password!". Wow! Do You see this? The application thinks that correct password is incorrect and all incorrect passwords are now correct.

That’s all for this short guide. I hope you enjoyed it and you’ll be able now to protect your application passwords better than with a single "if" statement. You always need to take into account that if more sophisticated method will be used to authenticate/unlock your application, there’ll be fewer people which can break it. Now go ahead and test something more complicated, see how the IL assembly file looks like and if it’s complicated enough.