Bypassing Obfuscation: Ciphered Code Reverse Engineering

Abstract

Obfuscation is a distinctive mechanism equivalent to hiding, often applied by security developers, to harden or protect the source code (that is deemed as intellectual property of the vendor) from reversing. The goal of such approach is to transform the source code into new encrypted byzantine source code symbols that have the same computational effect as the original program. By applying effective obfuscation over source code, it is difficult for a person with vicious intent to analyze or subvert the unique functionality of software depending on his requirements. Vendors typically seems to be safe by ensuring obfuscation over their intellectual property but unfortunately, software code is not safe from being modification even after applying obfuscation, it still can be cracked. However, this phenomenon can be illustrated by applying sort of rare tactics to bypass the obfuscation mechanism to reverse engineer or alter the inherent functionality of software.

Essentials

Software de-obfuscation is considered to be one of the complex undertakings in reverse engineering and done by going through numerous phases. First, the researcher required to have a thorough understanding of coding under .NET CLR because we shall reverse engineer a .NET built software which source code is already protected. Moreover, the personals must understand how to obfuscate a source code as well as have a comprehensive knowledge of IL assembly language to alter the .NET software binary instructions sets depending on their needs. The following list outlines the software that must be installed on his machine as;

  • Visual Studio 2010 or later
  • Reflector or ILSPY
  • Reflexil (Add-on)
  • CodeSearch (Add-on)
  • IL Assembly Language

Obfuscation Analysis

It is very difficult and often a time consuming process to reverse engineer compiler generated code, especially when things get even worse when the machine code is in an encrypted or obfuscated form. Such compiler generated code is deliberately constructed in encrypted form to resist analysis from reverse engineers. Some examples of situations in which obfuscation might be applied are as follows:

  • Protection of intellectual property: Commercial software typically have protection against unauthorized duplication by employing further obfuscation for the purpose of obscuring the implementation particulars of certain crucial segments of the mechanism.

  • Digital Rights Management: leading contemporary applications is often obfuscated by employing DRM schemes that commonly protect certain crucial pieces of information (for example, protocols and cryptographic keys) using obfuscation.

  • Malware: Hackers and reverse engineering criminals practice obfuscation for avoiding the detection of malware signature from anti-virus search engines.

Let's consider the following sample software that is typically first asking for a password to enter into the system. This software is responsible for manipulating the sort of classified information of secret agents and high-privilege personel that can only access such confidential details on behalf of secret keys.

user authontication
                                       Figure 1.1

Fortunately, we somehow obtain this software from a disgruntled employee but the problem is that we don't have the list of access keys to log-in into the system. Hence, the only remaining option is to reverse engineer this software for the purpose of revealing password information or identifying other crucial pieces of blocks so that we can subvert the authentication mechanism altogether. So, first ensure the platform origin of the software on which it is actually built, actually determine the type of executable we are dealing with. CFF explorer might assist to extract such details as follows:

portable executable
                                                                                 Figure 1.2

Great! This software is built and compiled under the .NET CLR framework. It is rather easy to decompile .NET assembly using a couple of disassemblers such as ILSPY, Reflector and ILDASM because such tools are competent enough to decompile the .NET binary into the actual source code. As we stated in earlier articles, ILDASM can decompile IL assembly code of an executable, moreover it is possible to recompile that modified IL code with a different name using ILASM.exe; however try ILDASM here, but it could not save us because the IL code is also full-proof protected and ILDASM can't decompile it as follows:

error
                                                Figure 1.3

Anyway, Reflector or ILSPY would truly be the rescuer in this situation because unlike ILDASM, they can decompile the source code in original format along with IL assembly code. But here, we are confronted with some other considerable issues since the software intellectual property is protected. Even though, reflector would decompile the accompanied classes, methods and property of this assembly but in encrypted form as in the following:

deobfus
                     Figure 1.4

From the previous Figure 1.4, the members of this assembly is displaying some bizarre symbols and the meanings are nearly impossible to comprehend. Let's expand any class or namespace, again the inexplicable symbol are found in both panes and if any of the members are selected from the left pane in the search of C# code to be obtained, it does decompile the source code in the C# language with obscure symbols but seems irrelevant altogether with actual functionality depending on our speculation.

fnction
                                                                              Figure 1.5

Perhaps Reflector doesn't fit-in such circumstances, let's try another disassembler as ILSPY. The result is the same, it will also decompile or yield C# source code but in an obscure construct as in the following:

resources
                                                                              Figure 1.6

So, it is stermined that none of the decompilers can assist us when the software code binary is protected by obfuscation to resist analysis because such binary is submerged with stubs and inexplicable symbols that the connotation can't be translated back into original form.

Software Functionality Analysis

We have the source code of this software but in encrypted form, totally useless for further manipulation. We cannot get much of a useful description even from the disassembled C# code. So, we need to take another effective approach by examining the functionality of this software to get some clues. The moment the user hits the Logon button after entering the password, the system displays an alert message box that says “Password is Incorrect”. Moreover, when the user clicks the OK button in the message box, the application is unloaded automatically. This is the hack!

access denied
                                                            Figure 1.7

So, there are some interesting points we can assume from this software functionality that might be very helpful when crucial code blocks are manually traced as in the following:

  • Locate MessageBox.Show implementation.
  • Locate Environment.Exit() method implementation.
  • Locate Exception Handling blocks.
  • Locate Hide() method implantation.
  • Search string Password is Incorrect.
  • Search string Access Denied.
  • Locate Text Box and Buttons implementation.

Interested Code Block Disassembling

We now have a better understanding of code obfuscation. The question now is how do reverse engineers take up such a challenge? Manual analysis of obfuscated code is such a complex task and nearly impossible to do. Because obfuscated code is in the form of a wide variety of strange symbols of which the meaning is incomprehensible or entirely irrelevant to the actual functionality. What tools or unique tactics are at their disposal to break into obfuscated code?

Let's return to the encrypted disassembled code in the reflector. It is showing the members of this assembly in an inexplicable symbols format. As a rule of thumb, just concentrate on the Pink Brick icons in the reflector because they contain the real code, the remaining is worthless for reverse engineering as in the following:

fous over bricks only
                           Figure 1.8

We have obtained a point of interest earlier from our thorough analysis. Now, we need to do a search operation in the assembly on the basis of such crucial points using one of the CodeSearch Add-ons of the reflector. Be sure that the CodeSearch add-on is properly configured in the reflector; open it. Now do the following searches.

Locating MessageBox.Show() method

After selecting Deobfus.exe from the left pane, type the MessageBox.Show or MessageBox in the codesearch and hit Enter. It yields a single result pointing to the method in the left pane where the implementation is specified as in the following:

message box show
                                                                                 Figure 1.9

Locating Environment.Exit() method

Now search for the Exit Keyword and we find two results. If we click any of them, we can get the method name of where its specification is specified as in the following:

exit code
                                                                           Figure 1.10

Locating “Password is Incorrect” string

Unfortunately, codesearch doesn't show any result that pertains to this string because strings are typically encrypted by obfuscation.

Password is Incorrect string
                                 Figure 1.11

Note: Code Search is case sensitive.

Locating Exception Handling blocks

It is assumed that programmers have used try/catch blocks to handle unexpected run time in the code. So search these blocks, here we have found some interesting code blocks and it is very relevant to the actual implementation as in the following:

Exception Handling blocks
                                                Figure 1.12

Locating Hide() Method

The application is unloaded automatically when the user clicks the OK button in the message box. Again, a search on behalf of this keyword produces a very significant result that resembles a previous search as shown in Figure 1.12.

Hide Method
                                                   Figure 1.13

So we can easily conclude from our search analysis that this is the only method where the password authentication functionality would be code. Even if the software code is obfuscated, hopefully identifying an item of interest will lead us to the code we want to reverse or bypass.

Cracking Obfuscated Code

Until now, we have gathered sufficient information from disassembled code analysis to subvert the inherent functionality of this software. We have found this code block that is responsible for validating a user on behalf of his correct password as we can see and assume in the if condition block. Moreover, if the user enters the correct password, the parent form will be unloaded and successful authentication brings up another window that is responsible for manipulating classified information.

Cracking Obfuscated Code
                                                               Figure 1.14

So this code segments contains everything that we are seeking for. But one more thing is we could search to assist the reverse engineering and make it easier. Here, the If condition block is evaluated on behalf of a Boolean value, so it might contain a method definition. However, we need to do one more search to identify that method where the actual password authentication code would exist. Hence the search for a true or false string via code search again. Bingo! It produces the exact method code specification as in the following.

string via code search
                                                                           Figure 1.15

It is now time to patch modify the crucial identified code corresponding to the IL code instructions to subvert the mechanism. Such IL modification could not be done by reflector alone. Instead, one of its add-ons, Reflexil, shall do IL assembly code modification. Higher-level programming, such as C#, gets converted to CIL instructions that will then be JIT compiled into native machine code at run time. Hence, such opcodes are at the heart of the CIL and tell the application what to do. In the lower section of the following Figure 1.16 Reflexil shows the CIL code to the corresponding C# code specified in the upper section.

Looking through the code and the CIL, we see an interesting instruction at offset 0 as idc.i4.0, that actually sets the flag value to false. In the next instruction set, the passed argument is compared to a predefined value (that is the password but in hash form), and finally this method returns a Boolean value.

CIL
                                                                           Figure 1.16

So, here are two hacks to subvert this authentication. If we either permanently configure the flag value to true at offset 0 or force the if condition block to always be evaluated to true at offset 18 then in both cases the flag value would be true no matter what argument is compared in the if condition block. We need to do something as in the following:

  • brfalse.s --> brtrue.s at offset 18
  • ldc.i4.0 --> ldc.i4.1 offset 0

To modify the brture.s IL instruction, first go offset 18 and right-click then hit the edit option. Finally, you found the following Windows whereby you can modify that specific instruction as in the following:

edit existing instruction
                                                                                    Figure 1.17

And to change the flag Boolean value to always true, first select and do the same operation such as earlier. Finally ensure the following changes:

OpCode
                                                                  Figure 1.18

There is one more option to subvert this authentication. As we can see these three lines are more than likely responsible for getting input from a user via a text box that is passed as an argument in the method this.STX(…); Once that function returns values, either True or False, the expression condition getting evaluates further and determines either a new window will be loaded or Password Incorrect message reflects. If we delete that specific section highlighted in Figure 1.19, then this. STX(…) is never ever called evaluated and we should be free from entering a password to login. So delete the following line specified in the right side of the following Figure 1.19:

authentication code
                                                                                 Figure 1.19

Finally, we are done with all the CIL code modification, now right-click on the exe then select Reflexil --> Save as. This operation makes the change permanently into a new patch version of this software, that is free from authentication requirements.

Reflexil
                                                               Figure 1.20

Now, run this patched exe file. As usual, the authentication mechanism is opened and asks to enter the password. Don't worry, enter any raw value and hit the Logon button. Bingoooooo!!!! We have bypassed the password requirement, now we can access the classified information that was supposed to be available only for authenticated users. So, this is how to reverse engineer an obfuscated executable by applying an effective analysis approach, even if we don't know the password, or the source code of this exe is obfuscated.

enter password
                                 Figure 1.21

classified information
                                                            Figure 1.22

Final Note

It is relatively easy to reverse-engineer a .NET executable when its source code is not in hash form but deemed very complicated to decompile the source code, especially the commercial software that source code protect from being analyzws and further reverse-engineered. In this article, we have done Reverse Engineering over a protected binary by deep analysis of both the obfuscated source code and MSIL assembly code. We've successfully modified the application to subvert authentication even without the password. So, this how to modify any software executable even if the source code is obfuscated, or if its license is expired, we have lost the password or to subvert other functionality.