Obfuscation is a distinctive mechanism equivalent to hiding, often applied by security developers, to harden or protect the source code (which is deemed as intellectual property of the vendor) from reversing. The goal of such an approach is to transform the source code into new encrypted byzantine source code symbols which have the same computational effect as the original program. By applying effective obfuscation over the source code, it is difficult for a vicious-intentioned person to analyze or subvert the unique functionality of software as per his requirements. Vendors typically seem to be safe by ensuring obfuscation over their intellectual property, but unfortunately, software code is not safe from being modified 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 in order to reverse engineer or alter the inherent functionality of software.
Software de-obfuscation is considered to be one of the complex undertakings in reverse engineering and is achieved by going through numerous phases. First, the researcher is required to have a thorough understanding of coding under .NET CLR because we shall reverse engineer a .NET built software which has source code that is already protected. Moreover, the researcher must know 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 as per their needs. The following list outlines the software that must be installed on his machine:
- Visual Studio 2010 or later
- Reflector or ILSPY
- Reflexil (Add-on)
- CodeSearch (Add-on)
- IL Assembly Language
It is a very difficult and often time-consuming process to reverse engineer a compiler-generated code, especially as things gets even worse when machine code is in 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 has 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 are often obfuscated by employing DRM schemes, which commonly protect certain crucial pieces of information (e.g., protocols and cryptographic keys) using obfuscation.
- Malware— Hackers and reverse engineer criminals practice obfuscation for avoiding the detection of malware signature from anti-virus search engines.
Let’s consider the following sample software, which is typically first asking for a password to enter into the system. This software is responsible for manipulating a sort of classified information of secret agents, and only highly privileged personnel can access such confidential details on behalf of secret keys.
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 option is left to reverse engineer this software for the purpose of revealing password information or identifying another crucial piece of blocks so that we can subvert the authentication mechanism altogether. So, first make sure with 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:
Great!! This software is built and compiled under .NET CLR framework. It is rather easy to decompile .NET assembly by using a couple disassemblers such as ILSPY, Reflector and ILDASM, because such tools are competent enough to decompile the .NET binary into 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 different name using ILASM.exe; however we tried ILDASM here, but it could not save us because IL code is also fool-proof protected, and ILDASM can’t decompile it as follows:
Anyway, Reflector or ILSPY would be truly a rescuer in this situation, because unlike ILDASM, they can decompile the source code in original format along with IL assembly code. But here, we shall have some to confront with some other considerable issue, as the software intellectual property is protected. Reflector would decompile the accompanied classes, methods and property of this assembly, but in encrypted form as follows:
From the aforesaid figure 1.4, the members of this assembly are displaying in some bizarre symbols, whose meanings are almost impossible to comprehend. Let’s expand any of class or namespace, again an inexplicable symbol is found in both panes, and if we select any of the members from the left pane in search of C# code, it does decompile the source code in C# language with obscure symbols, but seems irrelevant altogether with actual functionality as per our speculation.
Perhaps Reflector doesn’t fit in such circumstances. Let’s try another disassembler, such as ILSPY. Same result, it will also decompile or yield C# source code, but in obscure constructs as follows:
So, it is concluded that none of decompilers can assist us when the software code binary is protected by obfuscation to resist from analysis, because such binary is submerged with stubs and inexplicable symbols which connotation can’t translate into original form.
Software Functionality Analysis
We have source code of this software, but in encrypted form, totally useless for further manipulation. We could not get much of a useful description, even from the disassembled C# code. So, we have to take up another effective approach by examining the functionality of this software so that we could get some clues. The moment the user hits the Logon button after entering the password, the system displays an alert message box which says “Password is Incorrect”. Moreover, when user clicks the OK button in the message box, the application unloads automatically. This is the Hack!!!!!
So, there are some interesting points we can assume from this software functionality which might be very helpful while manual tracing of crucial code blocks as follows:
- 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
Up till now, we have a better understanding of code obfuscation; now the question is, how do reverse engineers take up such a challenge? Manual analysis of obfuscated code is such a complex task and almost impossible to achieve, because obfuscated code is in the form of a wide variety of strange symbols whose meaning are incomprehensible or entirely irrelevant to actual functionality. What tools or unique tactics are at their disposal to break into obfuscated code?
Let’s come again over encrypted disassembled code in the reflector. It is showing as members of this assembly in inexplicable symbols forms. As a rule of thumb, just only concentrate over the Pink Brick icons in the reflector, because they contain the real code. The remaining is worthless for reverse engineering as follows:
We have obtained some point of interest earlier from our thorough analysis. Now, we have to perform a search operation in the assembly on the basis of such crucial points by using one the CodeSearch add-on of the reflector. Make sure that the CodeSearch add-on is properly configured in the reflector and open it. Now perform the following searches as:
Locating MessageBox.Show() method
After selecting Deobfus.exe from the left pane, type the MessageBox.Show or MessageBox in CodeSearch and hit enter. It is yielding a single result which points out the method in the left pane, where the implementation is specified as follows:
Locating Environment.Exit() method
Now we search for the Exit Keyword and we find two results. If we click any of them, we can get the method name where its specification is mentioned as follows:
Locating “Password is Incorrect” string
Unfortunately, CodeSearch doesn’t show any results pertaining to this string, because strings are typically encrypted for obsfucation.
Note: CodeSearch is case-sensitive
Locating Exception Handling blocks
It is assumed that programmers would have used the try/catch block to handle unexpected run time while coding. So search these blocks, here we have found some interesting code blocks and it is very relevant to the actual implementation as follows:
Locating Hide() Method
The application is unloaded automatically when the user clicks the OK button in the message box. Again, search on behalf of this keyword produces very significant results, which resembles the previous search as mentioned in figure 1.12.
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 which is responsible for validating a user on behalf of his correct password, as we can notice and assume in the if condition block. Moreover, if the user enters the correct password, the parent form will be unloaded and successful authentication will bring up another window which is responsible for manipulating classified information.
So these code segments contain everything that we are looking for. But there is one more thing we could search to ease reverse engineering. Here, the If condition block is evaluating on behalf of a Boolean value, so it might contain a method definition. However, we have to perform one more search in order to identify that method where actual password authentication code would reside. Hence, search true or false string via CodeSearch again. Bingo!!! It produces the exact method code specification as follows:
Now after, it is time to modify and patch 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 perform IL assembly code modification. Higher level programming, such as C#, gets converted to CIL instructions which will then be JIT compiled into native machine code at run time. Hence, such opcodes are at the heart of CIL and tell the application what to do. In the lower section of the following figure 1.16, Reflexil is showing CIL code to the corresponding C# code mentioned in the upper section.
Looking through the code and CIL, we see an interesting instruction at offset 0 as idc.i4.0, which is actually setting the flagvalue to false. In the next instruction set, the passed argument is compared with a predefined value (which is the password but in hash form), and finally this method returns a Boolean value.
So, here are two hacks to subvert this authentication. Either we permanently configure the flag value to true at offset 0, or force the if condition block to always evaluate true at offset 18. Hence, in both of cases, flag value would be true no matter what argument is compared in the if condition block. We have to do something:
- brfalse.s brtrue.s at offset 18
- ldc.i4.0 ldc.i4.1 offset 0
In order to modify the brture.s IL instruction, first go to offset 18 and right click, then hit the edit option. Finally, you find the following windows whereby you can modify that particular instruction as follows:
And to change the flag Boolean value to always true, first select and perform the same operation like earlier. Finally, make sure with the following changes:
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 the user via a text box, which is passed as an argument in the method this.STX(…); Once that function return values either True or False, the expression the condition is getting evaluates further and determine that either a new window will be loaded or a Password Incorrect message reflects. If we delete that particular section highlighted in figure 1.19, then this.STX(…) will never ever be called or evaluated, and we should be free from entering the password in order to login. So delete the following line mentioned in the right side of the following image 1.19.
Finally, we are done with all CIL code modification, now right click on the exeselect Reflexil Save as. This operation makes such a change permanently into a new patch version of this software, which is free from authentication limitation.
Now, run this patched exe file, as usual, an authentication mechanism is opened and it asks to enter the password. Don’t worry, enter any raw value and hit the Logon button. Bingoooooo!!!! We have bypassed the password limitation, now we can access the classified information which was supposed to available only for authenticated users. So, this is how we can 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.
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 which source code protects from being analyzed and reverse engineered. In this article, we have performed reverse engineering over a protected binary by deep analysis of both obfuscated source code and MSIL assembly code. We’ve successfully modified the application to subvert authentication, even with not having the password. So, this how we can modify any software executable whose source code is even obfuscated, in case its license is expired, we have lost the password, or we are subverting another functionality.