We shall explore round-trip engineering, which is one of the most advanced tactics to disassemble IL code in order to manipulate reverse engineering in the context of existing NET-built software applications. The .NET round-trip engineering requires a thorough understanding of MSIL grammar, which we have already confronted in the previous articles because all we have to do is to play with IL code. After getting entirely competent in round-trip engineering, we can bypass serial keys and user authentication mechanisms and fix inherent bugs that are shipped into existing applications without having source code.

Round-Trip Engineering

Round-trip engineering refers to disassembling the IL code of an existing application. This sophisticated process first re-manipulates the IL code, modifying it as per our requirement, and finally re-assembles the code without peeping into the actual source code of an application. Formally speaking, this technique can be useful under a number of circumstances; for example, sometimes we need to modify an assembly in case of bug fixing for which you no longer have access to the source code. Some trail software expires after completing their specific grass period and we can no longer use them. Finally, we can change numerous stipulated conditions such as 15 days or 1-month trial duration by applying round-tripping or we can enter into software interface without having relevant password. This tactics can also be useful during COM interoperability in which we can recover lost COM IDL attributes. The following image illustrates the life-cycle of round-tripping process as:

The process of round-trip engineering in the case of managed PE files includes two steps. The first step is to disassemble the existing PE file (assembly) into an ILASM source file and the managed and unmanaged resource files:

ildasm test.dll /out:testNew.il

The second step of round-tripping is to invoke the ILASM compiler to produce a new PE file from the results of the disassembler’s activities:

ilasm /dll testNew.il /out:Final.dll

Bug Fixing

At the production site, application software won’t work properly or it might produce some strange implications. The programmer typically left sort of subtle run-time bugs in the final software version inadvertently. Reasons for software failure might be numerous, such as not conducting unit testing properly at the development site or the developers are in hurry to launch the application due to the pressure of a deadline from client side. The client typically does not have access to the actual source code of the software. They are provided only the final executable bundle of the software because most of the clients are laymen about technology; they are only proficient enough to operate from the front-end user interface. What is happening at the back-end side is entirely rocket science to understand for them. There could be another scenario in which the organization that developed the software no longer exists, which might cause a huge problem because now the client has no one to ask in order to fix the bugs.

Note: Reverse Engineering can be executed with both offensive and defensive purposes and this article aims to get the knowledge of reverse engineering for the defensive reading and testing point of view.

Now the question is how to fix the bugs despite not having the source code of the software. The answer is round-trip reverse engineering. The final shipped bundle includes the executable of the software with its dependent library files. If the client still insists on relying on software that is full of bugs, the client has the option of approaching some ardent reverse engineer so they can try to fix the bugs in order to produce desired result without having access to source code.

Memory Overflow Bug

The following sample illustrates the simple addition of two-byte type variables and displays the calculated output on the screen. The operation seems very simple, superficially. But the programmer doesn’t have an idea that this application can lead to failure if he didn’t apply the proper precaution of operation logics related to byte data types.

Once this code is compiled, it can be tested by passing two data as 200 and 70 at the command line to be added together. This program produces a bizarre result, 14 rather than 270.

The problem with that code is that the byte data type only goes up to 255 and we are adding variable for which the result is beyond its capacity (270). The programmer forgot to validate the memory overflow run-time exception. We can fix this bug by modifying the IL code by putting exception overflow check (ovf) without peeping into source code:

Thereafter, save this file and re-compile it using the ILASM utility, which yields another fixed version of this application. This time the compiler echoes an alert in the case of adding values that have a result beyond the byte data capacity, as shown in the following:

It is good programming practice to include a try/catch block to handling run-time error occurrences, as we will see later in the article.

Array Index Out of Range Bug

The following sample demystifies arrays in which the index out of range exception normally occurs. Here we are declaring a string type array with length of 3 and we initialize each of its elements with some hard-coded string values. Later, we enumerate array elements using a for loop construct in order to display them as following:

After running this program, we notice that the application encounters an exception of index out of range after displaying three elements. This happens because the for loop iterates one time extra by placing the equal sign in the condition block and compiler throws an exception as follows:

We can fix this bug by manipulating IL code implicitly. The ceg opcode is responsible for specifying the equal sign, so all we have to do is to replace clt opcode with ceg, which stipulates the less then condition and eradicate the ldc opcode value. Now the loop construct will iterate three times rather than four times, as shown here:

Finally, save this file again and compile it by using ILASM, which produces bug-free executable file, as follows;

Divide by Zero Exception Bug

The following program simply divides a number by another value; the logic implementation is very easy but the programmer must not forget to validate the denominator value, which should not be zero. Our application will crash and throw a DivideByZeroExcpetion alert. Here is the IL code implementation:

After running this program, it asks the user to input the denominator value. Unfortunately, we entered it as 0 and now the application yields the following output:

Such trivial logic implementation should be handled at the time of coding by placing the sensitive code into a try/catch block, so the application won’t interrupt the execution and throw an alert to user if they enter wrong values. We put the try/catch block here, as follows:

After running this program, if the user inputs 0 as the denominator value again, the compiler echoes an alert:

Summary

I hope you have enjoyed this article a lot. We have learned couple of advance operations related to round-trip engineering by modifying IL opcode explicitly without manipulating the source code. We have seen how to handle run-time occurrences of exceptions, such as divide by zero, index out of range, etc., by altering the corresponding IL opcodes. In the next article, we shall explorer how to crack the user authentications mechanism, bypassing serial keys conditions.

Ajay Yadav is an author, Cyber Security Specialist, SME, Software Engineer, and System Programmer with more than eight years of work experience. He earned a Master and Bachelor Degree in Computer Science, along with abundant premier professional certifications. For several years, he has been researching Reverse Engineering, Secure Source Coding, Advance Software Debugging, Vulnerability Assessment, System Programming and Exploit Development.
He is a regular contributor to programming journal and assistance developer community with blogs, research articles, tutorials, training material and books on sophisticated technology. His spare time activity includes tourism, movies and meditation. He can be reached at om.ajay007[at]gmail[dot]com

Your email address will not be published. Required fields are marked *

Comment

Name *

Email *

Website

Save my name, email, and website in this browser for the next time I comment.

× nine = eighty one

About InfoSec

At Infosec, we believe knowledge is the most powerful tool in the fight against cybercrime. We provide the best certification and skills development training for IT and security professionals, as well as employee security awareness training and phishing simulations. Learn more at infosecinstitute.com.

Connect with us

Join our newsletter

File download

First Name

Last Name

Work Phone Number

Work Email Address

Job Title

Why Take This Training?

How will you fund your training?

What is your training budget?

InfoSec institute respects your privacy and will never use your personal information for anything other than to notify you of your requested course pricing. We will never sell your information to third parties. You will not be spammed.

Comments

What is Skillset?

Skillset

Practice tests & assessments.

Practice for certification success with the Skillset library of over 100,000 practice test questions. We analyze your responses and can determine when you are ready to sit for the test. Along your journey to exam readiness, we will:

1. Determine which required skills your knowledge is sufficient
2. Which required skills you need to work on
3. Recommend specific skills to practice on next
4. Track your progress towards a certification exam