Demystifying dot NET Reverse Engineering: Advanced Round-trip Engineering

M33

[ Verified Seller ]
Staff member
Trusted Seller
Joined
11 yrs. 8 mth. 22 days
Messages
5,010
Reaction score
11,818
Wallet
13,191$
Please, Log in or Register to view URLs content!
January 23, 2013



Before going through this article, I highly advice you to read all previous ones in the series since I will not re-explain some techniques and re-describe some tools previously presented. Here, I will assume that you understood the basics and everything that was presented prior:

Please, Log in or Register to view URLs content!
: Demystifying Dot NET Reverse Engineering- Big Introduction
Please, Log in or Register to view URLs content!
: Demystifying dot NET Reverse Engineering – Introducing Byte Patching
Please, Log in or Register to view URLs content!
: Demystifying dot NET Reverse Engineering- Advanced Byte Patching
Please, Log in or Register to view URLs content!
: Demystifying dot NET Reverse Engineering- Introducing Round-trip Engineering

Summary

This article is only a part of a whole, and it aims to go deeper into IL assembly language exploited in reversing non-obfuscated (until now) dot NET assemblies and modules. (Managed dot NET applications are called assemblies and managed dot NET executables are called modules; a managed dot NET application can be a single module assembly or a multi-module assembly)

As previously presented, disassembling and reassembling a managed executable is called round tripping. Round tripping in our case concerns managed portable executable files and is divided into two main steps:

Disassembling the PE file into an .il file (which contains ILAsm source code) and into managed and unmanaged resource files, done using ILDASM.
Reassembling files gotten in step 1 into a new PE file using ILASM compiler.

Settling for simply disassembling and reassembling is not that interesting a task unless you modifyoralter the ILAsm source code before reassembling it. Round tripping (as most of reverse engineering techniques) is not “breaking software protections” specifically, but we will focus only on this in our upcoming studies as we saw in the article “Demystifying dot NET Reverse Engineering- Introducing Round-trip Engineering.”

The last thing we did was to remove the Crack Me’s nag screen but we still faced serial number protection which we will analyze in upcoming paragraphs.

Serial check analysis

Going back to ILDASM, let’s reconsider the tree structure we’ve got:

012313_1326_Demystifyin1.png


Each node represents a namespace we can explore that has class objects which, once expanded, deliver their methods and properties. Here we have an interesting class name “GenSerial” which contains a very interesting method:

012313_1326_Demystifyin2.png


With this IL assembly content:

Code:
Please, Log in or Register to view codes content!

} // end of method GenSerial::CalculSerial

Things get a bit more complicated here and would need clarification:

.method public instance object CalculSerial() cil managed: As seen in article 4, this is the MethodDef metadata item. The only difference is that this method has a return type which is object.

.maxstack directive is described in article 4 (please refer to background section).

.locals init (object V_0):As in any development language, variables are very important, and ILAsm has its way of declaration; .locals init (object V_0) defines a local variable called objectV_0.The init keyword indicates to the Just-in-Time compiler that it must initialize all local variables to zero on entry to the method.

ldarg.0 is the instruction that loads argument 0 on the stack, but instance methods like the one we have has the “this” (used in high level languages) instance references as the first argument of the method signature, so ldarg.0 here loads instance pointer on the stack.

call class CrackMe3_InfoSecInstitute_dotNET_Reversing.My.MyComputer
CrackMe3_InfoSecInstitute_dotNET_Reversing.My.MyProject::get_Computer(), MyComputer here is inheriting from a base class defined in Microsoft.VisualBasic namespace. Call here invokes the static method get_Computer()which resides in the class MyProject under the namespace “My” and will return an instance of CrackMe3_InfoSecInstitute_dotNET_Reversing.My.MyComputer. This property “get_Computer” (like in most high level languages getters and setters) will access an instance of Microsoft.VisualBasic.Devices.Computer object (including details will multiply the size of this article!).

012313_1326_Demystifyin3.png


callvirt instance class [Microsoft.VisualBasic]Microsoft.VisualBasic.Devices.ComputerInfo [Microsoft.VisualBasic]Microsoft.VisualBasic.Devices.ServerComputer::get_Info() calls the virtual method/property (getter) get_Info() and the use of the keyword instance means that the we are dealing with instance methods instead of static ones. Referring to Microsoft MSDN ComputerInfo class provides properties for getting information about the computer’s memory, loaded assemblies, name, and operating system. ServerComputer class provides properties for manipulating computer components with an inheritance hierarchy like this:

System.Object
Microsoft.VisualBasic.Devices.ServerComputer
Microsoft.VisualBasic.Devices.Computer

callvirt instance string [Microsoft.VisualBasic]Microsoft.VisualBasic.Devices.ComputerInfo::get_OSVersion()calls the virtual method get_OSVersion() from the dot NET Frameworks class library ComputerInfo. As a result of this call, a string is put onto the evaluation stack and from the method name we can guess that our program accesses the operating system version.

The instruction ldstr “.” and ldstr “”creates, respectively,a string object from the string constant “.” (dot) then loads a reference to it onto the stack thendoes the same thing to the string constant “” (empty string).

Call instance string [mscorlib]System.String::Replace(string, string):This instruction calls the Replace(string,string) function from the dot NET Frameworks class library, parameters / method arguments are taken from the stack (“.” And “”) and the result is pushed back onto the stack. This means it takes the computer version, replaces every dot “.” by nothing then puts back the result onto the stack.

stfld string CrackMe3_InfoSecInstitute_dotNET_Reversing.GenSerial::SerialNumber:This instruction sets the result of the function Replace(string, string) on the field SerialNumber which is previously declared as private and is equivalent to a private variable in high level languages.

012313_1326_Demystifyin4.png


ldarg.0loads the reference of the object itself (equivalent to this in high level languages) then using ldfld string CrackMe3_InfoSecInstitute_dotNET_Reversing.GenSerial::SerialNumber takes the instance from the stack and loads the value of the instance field SerialNumber on it.

Ret is, as you probably guessed, the instruction that returns from a called method to a call site and since our method returns an object, one value of type object is on the evaluation stack of the calling method.

At this point we should know that the field SerialNumber contains the version of our operating system without dots. We can then easily retrieve the full OS version which in my case is 6.1.7601.65536, and by applying the Replace() function I get 61760165536,which was a successful serial number:

012313_1326_Demystifyin5.png


This was fun, so let’s now move to serious things because until now we did not alter the code and we did not use the ILASM assembler! We want the Crack Me to tell us the right serial number instead of showing us a “Wrong serial number” message box.

Let’s have a look again into ILDASM then expand the second node:

012313_1326_Demystifyin6.png


By verifying the methods that Form1 class contains, we can easily find the method called once we click on the button “Register”:

012313_1326_Demystifyin7.png



The actual method’s IL code should be (hopefully) clearer soI won’t explain the code again line by line:

Code:
Please, Log in or Register to view codes content!

If you followed all articles aboutDemystifying dot NET Reverse Engineering, you should be able to understand what this method does exactly.And by the way, please remark System.EventArgswhich means that we are under an event which is “click.” Clicking on the button “Register” flags the method reg_Btn_Click(…).

We can split this code into blocks:

First, the Crack Me gets the text we typed as a serial number using method get_text().
Then, it calls an instance of the class which calculates the correct serial number using CalculSerial().
At this point, we have three items on the top of the evaluation stack as expected using the the directive .maxstack 3, which are two objects: the serial number typed by the user retrieved using get_text() method,the correct serial number calculated via the function CalculSerial(), and a four byte zero loaded by the instruction ldc.i4.0 to let the Crack Me correctly use the API ConditionalCompareObjectEqual(…), which represents the overloaded Visual Basic equals (=) operator with a Boolean return type. The loading of zero as TextCompare parameter means that the comparison is not case sensitive, but this is not thatimportant in this case since our serial number is numeric.
If comparison returns false, this means that objects loaded as parameters are not equal and that the serial number given by the user is not correct, so brfalse.sbranches/jumps to IL_0032whichloads a reference to the string “Wrong serial number” and prepares the message box to show after it clears the evaluation stack using pop instruction; otherwise, it prepares the “Serial is correct!” message box and clears the evaluation stack using pop instruction before unconditionally transferring the program to ret instruction (the end of the method) using br.s IL_0044 instruction.

We know what this method does exactly but we have to use some “creative” round tripping to let the Crack Me change its behavior so that it shows the correct serial number instead of showing the wrong serial message box. Basically, we need to change the seportions of the code:

012313_1326_Demystifyin8.png

012313_1326_Demystifyin9.png


And:

012313_1326_Demystifyin10.png


But into what? Obviously, we have to call the function that calculates and returns the correct serial number, remove the “Wrong serial number” message, and show the correct serial number.

Let’s imagine how the evaluation stack should look like after the changes:

0


“The serial number is:”

1


#SERIAL#

2


Message box style

3


Message box title

First thing we should notice is that we are going to load 4 items onto the stack, but the directive .maxstack was previously established to prepare the just in time compiler to reserve only 3 slots for this method. So the first change we have to do is modifythe .maxstack value:

Code:
Please, Log in or Register to view codes content!

The second thing we should do is remove the line IL_0032: ldstr “Wrong serial number” and prepare the string we want to load. The use of labels is optional but we need to use at least one label to mark the offset at which we started modifications:

Code:
Please, Log in or Register to view codes content!

Now we have to call an instance of the class that has the function which calculates the correct serial number. We will simply take the same instructions used by the Crack Me to perform comparison:

Code:
Please, Log in or Register to view codes content!

Technically our serial is “ready” but we cannot show an “object” in a text box. We have to get the string value from the serial number object; in dot NET Frameworks, the method which can return a boxed copy of an object is RuntimeHelpers.GetObjectValueand we have to give its full signature:

Code:
Please, Log in or Register to view codes content!

Now the evaluation stack contains two values: “The serial number is:” string and the serial number string, so we need to concatenate them to produce one value/item. By browsing Microsoft MSDN we find String.Concat (object,…) method, so by giving its full signature we get:

Code:
Please, Log in or Register to view codes content!

012313_1326_Demystifyin11.png


Instead of jumping to the offset at label IL_0032, the Crack Me should go to our patch:

Code:
Please, Log in or Register to view codes content!

Now we are done! After these changes the modified code must look like this:

012313_1326_Demystifyin12.png


Save your .il file and let’s reassemble it using ILASM assembler to test what we did (if you have trouble with this step, please refer to this):

C:\Windows\Microsoft.NET\Framework\v4.0.30319>ilasm C:\Users\Soufiane\Desktop\round-t\crackme3.il -res=C:\Users\Soufiane\Desktop\round-t\crackme3.res

The compilation process was successful:

Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved
Writing PE file
Operation completed successfully

And the result was successful as well:

012313_1326_Demystifyin13.png



We can improve this by customizing this message box to display a better result, such as changing the title and the message box style:

012313_1326_Demystifyin14.png


We can go deeper in our Crack Me tweaking and make changes to the way it writes the correct serial in the text box area instead of showing it in a message box:

Code:
Please, Log in or Register to view codes content!

The result is quite nice:


012313_1326_Demystifyin15.png



By clicking once, Crack Me will write the serial number, but clicking twice will show you a “Serial is correct” message box.

References:

Please, Log in or Register to view URLs content!

Please, Log in or Register to view URLs content!

Please, Log in or Register to view URLs content!



sursa:
Please, Log in or Register to view URLs content!
 
Paid adv. expire in 2 months
CLICK to buy Advertisement !
westernunion carding Verified & Trusted WesternUnion | MoneyGram | Bank - Transferring [299$ BTC for 2000$ WU]
electronics carding Verified & Trusted Electronics Carding, Carding iPhone, Samsung Carding, MacBook Carding, Laptops Carding
Top Bottom