Reverse engineering of Visual Basic .NET or C # code
Release Date: 09/02/2004
| Update Date: 09/02/2004
Gabriel Torok and Bill Leach
This article assumes that you are familiar with .NET and C #
Abstract The advantage of the .NET architecture is that the assembly that uses it constructs contains many useful information that can be recovered using ILDASM and the intermediate language disassembler. Although there is a negative impact, you can access your binary code that is very close to the original source code. The procedure provided by the author here is a method of preventing reverse engineering. In addition, they also discussed the available different types of fuzzy treatment techniques and illustrate new fuzzy treatment tools contained in Visual Studio .NET 2003.
So far, you may be familiar with the benefits of metadata-rich Microsoft®.NET Framework architecture, from the rich IDE function enabled by mitigating deployment and version controls to self-descriptive binary . You may not know that the simple availability of all metadata has introduced a problem until the current concerns have not been concerned by most developers. Writing applications for universal language runtime (CLR) is more and more simple to reverse engineering. Any errors are not allowed in .NET Framework, it is just a ready-made intermediate compile language (Java language application exhibits the same characteristics). Both Java and .NET Framework use rich metadata embedded inside the executable code: in Java is byte code, in the .NET is the Microsoft Intermediate Language (MSIL). A high-grade executable than the binary machine code contains information that can be easily decipherous.
Using tools such as ILDASM (MSIL disassembler included with ILDASM) or anti-compiler such as Anakrino and Reflector for .NET, anyone can easily study your assembly and use reverse projects. Convert to readable source code. Hackers can search for security vulnerabilities, stealing unique ideas, and even crack the program. This is enough to let you hesitate.
However, please don't worry. There is a solution that is blurred, which will help you prevent reverse works. Fuzzy treatment is a technique that provides seamless renamed symbols in the program and other techniques to prevent anti-compilers. Once the technology is applied correctly, fuzzy treatment can greatly increase the protection of anti-anti-anti-compilation, but make the application unreasonable. Fuzzy treatment is usually used in the Java environment, has been used in the company's knowledge-based products based on Java-based products.
Many third parties have created a fuzzy handler for .NET code as needed. Microsoft In the cooperation with our company Preemptive Solutions, Microsoft Include Dotfuscator Community Edition included in Visual Studio®.Net 2003, and our company offers a variety of fuzzy processing packages.
Using Dotfuscator Community Edition, this article will teach you all knowledge about fuzzy treatment (and some of the impact of anti-compilation knowledge), usually available fuzzy processing types, and some issues you need to pay attention to when using a fuzzy handler.
To illustrate anti-compilation and fuzzy processing, we will implement an open source code of a classic VEXED game. Vexed.net is written by RoEy Ben-Amotz, located at http://vexedddotnet.benamotz.com. This is a intellectual game, your goal is to move similar blocks together, then they will disappear. Below is a simple way from vexed.net source code:
Public void undo () {
IF (Numofmoves> 0) {
Numofmoves -
IF (_USERMOVES.LENGTH> = 2) _USERMOVES = _USERMOVES.SUBSTRING (0, _usermoves.length02);
this.loadboard (this.Movehistory [Numofmmoves)
(NUMOFMOVES / 50) * 50]);
this.drawboard (this.gr);
}
}
Disassembly
The .NET Framework SDK is available named ILDASM's dislapped utility, allowing you to compile the .NET Framework program set into an IL assembly language statement. To start ILDASM, you must make sure the .NET Framework SDK is installed, and type ILDASM on the command line, follow the name of the anti-compilation. In our example, you will type "ildasm vexed.net.exe". This will start the ILDASM UI, which can be used to browse the structure of any .NET Framework's application. Figure 1 shows an anti-assessment UNDO method.
Back to top
Anticipation
If you think that only those who really understand the IL assembly language will view and understand your source code, remember that the anti-compilation is not stopped here. We can use the anti-compiler to recreate the actual source code. These utilities can directly refine the .NET assembly back into advanced languages, such as C #, Visual Basic®.NET or C . Let's take a look at the undo method generated by an ANAKRINO anti-compilation program:
Public void undo () {
IF (this.numofmoves> 0) {
this.numofmoves =
THIS.NUMOFMOVES - 1;
IF (this._usermoves.length> = 2)
THIS._USERMOVES =
THIS._USERMOVES.SUBSTRING (0, this._usermoves.length - 2);
this.loadboard
THIS.MOVEHISTORY [this.numofmoves -
THIS.NUMOFMOVES / 50 * 50]);
this.drawboard (this.gr);
}
}
As you can see, the result is almost the same as the original code. Later, we will return to this example to view the results after using fuzzy treatment.
Back to top
In-depth fuzzy treatment
Fuzzy treatment is done using a set of related technologies. Its goal is to hide the intent of the program without changing its runtime behavior. It is not encrypted, but in the context of .NET code, it may be better. You can encrypt the .NET assembly to make them completely unreadable. However, this method faces the situation of two difficulties - because the runtime must perform an undueed code, and the encryption key must be saved in the encrypted program. Therefore, an automated utility can be created to restore the key, decrypt the code, and then write IL in its original format. As long as this happens, the program is fully exposed to anti-compilation.
For a metaphor, encryption is like locking six dishes into a box. Only those who want to eat (in this example is CLR), there is a key, we don't want anyone else to know what he or she wants to eat. Unfortunately, food will be disconnected by all bystanders. Fuzzy treatment work is like adding six dishes into the stirrer and then put it into a plastic bag to guers. Of course, everyone can see the food in the delivery, but in addition to lucky peas or some beef-colored paste, they don't know what the original dish is. The meals still have wanted dishes, and the dishes provide with the same nutritional value as previous (fortunately, the CLR does not score the taste of the taste). The fuzzy treatment program is to make the observer confused while still providing the same product for CLR. Of course, fuzzy treatment (or encryption) is not 100% security. Even compiled C can also be disassembled. If the hacker is sufficient enough, she can regenerate your code.
Figure 2 Fuzzy treatment process
Fuzzy treatment is a process applied to the compiled .NET assembly rather than the source code. The fuzzy handler does not read or change your source code. Figure 2 shows the flow of the fuzzy treatment process. The output of the fuzzy handler is another set of assemblies, which is functionally in the same way, just changing the way the reverse engineering is changed. Now, we will consider two basic techniques used by Dotfuscator Community Edition to reach this target: rename and delete unnecessary metadata.
Back to top
Rename the metadata
The first spinning line of fuzzy treatment is a meaningful name to rename meaningful names. As you know, you have a very big value after careful names. They help your code self-explanatory and can be used as valuable clues to reveal the purpose of the items they represent. The CLR does not mind how the name is illustrative, so the fuzzy handler can make it more without restrictions, usually change it to a character name, such as "A".
Obviously, there will be many restrictions on the number of renames on a particular application. Generally, there are three universal renamed regimens.
If your application consists of one or more independent assemblies (ie, the code that does not have unfunctional processes depends on any assembly), then the fuzzy handler can rename an assembly without restrictions, no need to take care of the name. Visual effects, as long as their names and references are consistent in the assembly collection. Windows®form applications is a good example. In the opposite extreme, if your application is designed to be used by unfurious processing, the fuzzy handler cannot change the name of the type or a member visible to those clients. This type of application is an example of a shared class library, reusable components and others. In some locations, it is to insert an application in an existing unflavible processing framework. In this example, the fuzzy handler can rename anything that is not accessed by the fuzzy handling of a particular environment (the fuzzy handler in it), without considering visibility. ASP.NET applications are typical examples of this type of application.
Dotfuscator Community Edition uses a patent rename technology named "overloaded", which adds a conversion to the rename. After thorough role analysis, the method identifier will maximize overload. No longer replacing each old name with the new name, and the heavy-duty restriction technology is renamed as the same name as much as possible, and then trying to understand anyone who is trying to understand the reciprocal code.
In addition, there is a good attached effect, the size of the application will be reduced accordingly due to the reduction in the string of the string of the program. For example, if you have a name that is 20 characters, rename it "A" will save 19 characters. In addition, the reuse of the name will save space due to the saving string stack. Rename all names "a" means that "A" is stored only once, and each method or field renamed "a" can point to it. The overload is increasing to enhance this effect because the shortest identifier can be reused continuously. Typically, a project with an overloaded summary can rename up to 35% of the method to "a". To see the impact on the renaming of the anti-compile code, study the undo method after renaming the process:
Public void c () {
IF (THIS.P> 0) {
THIS.P = THIS.P - 1;
IF (this.R.Length> = 2)
THIS.R = this.r.substring (0, this.r.length - 2);
THIS.A (THIS.Q [this.p - this.p / 50 * 50]);
THIS.A (this.e);
}
}
You can find that this method is very difficult to understand if there is no other type of fuzzy treatment.
Back to top
Delete unnecessary metadata
Not all metadata in the compiled .NET-based application is used by the runtime. Some of them are used by other tools such as design programs, IDEs, and debuggers. For example, if you define an attribute called "size" on a type in C #, the compiler ignores metadata named "size", and operates the name with the implementation GET and SET (respectively The method of "get_size" and "set_size") is associated. When you write the code for setting the size property, the compiler will always generate a call to the method "set_size" itself, and will not reference this property through its name. In fact, the attribute name here is used for IDE and developers who use your code; it will not be accessed by CLR.
If your application wants to use only by running, the fuzzy handler deletes this type of metadata is secure. In addition to the attribute name, event name and method parameter names also belong to this category. When DotFuscator Community Edition is considered to delete all of these types of metadata, it will do this.
Back to top
Other technology
Dotfuscator Community Edition provides good fuzzy treatment using the technologies we just introduced, but you should notice that other fuzzy processing technologies that provide stronger protection may prevent reverse engineering. Dotfuscator Professional Edition implements many other technologies, including control flow fuzzy processing, string encryption, incremental fuzzy processing, and size reduction.
The control flow is a powerful fuzzy treatment technology that is the purpose of hiding the command results without changing logic. More importantly, it is used to delete the anti-compiler to find clues to faithfully regenerate the advanced source code statement (for example, if-kilse statements, and loop). In fact, this technique tends to terminate the anti-compiler.
To see the effect of this operation, check again in the application rename and control the flow of blurred processes, then view the anti-compiled UNDO method (see Figure 3). You can see that replacing the original nested IF statement, the anti-compiler generates an IF statement, two nested While loops, and some of them together. The label I1 is referenced, but it is not generated by the anti-compiler (we think this is an anti-compiler error).
String encryption is a technique that applies a simple encryption algorithm to character text embedded in the application. As mentioned earlier, any encryption (or especially decryption) performed at runtime is inherently unsafe. That is, smart hackers can finally crack it, but for the string in the application code, this is worth it. Let us face it, if hackers have to enter your code, they don't blindly start searching to search for renamed types. They may do search for "Invalid License Key", which will guide the code where the execution license is handled. Search for unexpected simple simply in strings; string encryption builds obstacles because encrypted versions only appear in compiled code. Incremental fuzzy processing helps release a patch in a fuzzy process to repair customer issues. Errors in the repair code typically create or delete classes, methods, or fields. Changing code (such as adding or removing methods) may cause subsequent fuzzy processing running renaming transactions slightly different. A transaction called "a" in front may now be called "B". Unfortunately, renaming different ways and different content are a mystery.
Incremental fuzzy treatment can solve this problem. The fuzzy handler creates a mapping file to inform you how it performs renaming. However, this same mapping file can be used as an input to a fuzzy handler in subsequent runs, thereby specifying the renamed renames that should be used as much as possible. If you release your product, then introduce a patch for some classes, the fuzzy handler can operate in this way to simulate it previous rename scheme. This way, you can only issue a patched class for our customers.
The size reduction is not strictly prevented from reverse engineering, but it is worth discussing because the fuzzy handler must almost always perform dependencies on the input assembly collection. This fuzzy handler can make fuzzy processing well, and some of the better fuzzy handles will use their code to delete the program without using the program. Delete the code that doesn't use it looks a bit, but it does implement a certain purpose - isn't someone does not use the code you write? Ok, this is all our answered. Also, the library and classes we use are written by others for repeated use.
Reused code represents a temporary code that can handle many cases; however, for any given application, usually you only use one or both of these cases. Advanced fuzzy handles can determine this, and can strip all unused code (in the same, from the compiled program, not from the source code). The result is that the output is accurately included in the type and method needed to apply - there is no excess. The advantage of smaller applications is to save computing resources and reduce loading time. This is especially important for applications running on .NET Compact Framework or distributed applications.
Back to top
Use dotfuscator community edition
Now let's use Dotfuscator Community Edition to fuzzy to process the VEXED app. Dotfuscator Community Edition uses a configuration file that specifies the fuzzy processing settings for special applications. It has GUI to help you simply create and maintain profiles and run a fuzzy handler and check out. In addition, the command line interface of Dotfuscator Community Edition allows you to easily integrate fuzzy processing into the automated build process. You can start the GUI from the Tools menu of Visual Studio .NET 2003.
To configure Vexed for fuzzy processing, you need to specify three items in Dotfuscator Community Edition GUI: Enter an assembly, mapping file location, and output directory. Specify the input assembly on the "Trigger" tab (the fuzzy handler is called "trigger assemblies"). You can add any more you here, but for the Vexed application, you only need to add one. Specify a mapped file location on the "Rename | Options" tab (see Figure 4). The mapping file is the basic information block, which contains a clear name mapping between the original and unflagous processing names. It is very important to save this file after fuzzy processing applications. If there is no, you will not be able to simply exploit the problem of applying applications. Because of its importance, by default, the fuzzy handler will not overwrite existing mapping files unless you are explicitly selecting the "Overwrite Map File" checkbox.
Finally, the "Build" tab allows you to specify the directory where you want to place the fuzzy handling application. Once this is completed, you can start the fuzzy processing application. You can save your profile for future use, then press the "Build" button on the "Build" tab or use the "Play" button on the toolbar. During the construction process, the fuzzy handler displays progress information in the GUI's output pane. You can control the amount of information displayed here by selecting "Quiet" or "Verbose" on the "Options" tab.
After the build is complete, you can browse the results on the "Output" tab, as shown in Figure 5. As you can see, the fuzzy handler displays a graphical view of the application, similar to an object browser. The new name immediately appears below the original name in the view. In this chart, you can see that the class named "Board" is named "H", and two methods with different signatures (init and toimage) are renamed "A".
Back to top
Check the mapping file
The mapped file generated by dotfuscator is a file in XML format. In addition to the name map already mentioned, it also contains some statistics on renaming process efficiency. Figure 6 summarizes the statistics of the type and method of the volaxed application.
The mapping file is also used to perform incremental fuzzy processing. This process allows you to import names from previous runs, which will notify the fuzzy handler to rename them in the same way they are previously performed. If you release a patch (or new plugin) for an approved application, you can use the same name collection as the original version to fuzzy to update. This is especially useful to maintain a plurality of enterprise development teams of multiple interdependent applications.
Back to top
Fuzzy treatment program defect
In complex applications, it is necessary to carefully treat fuzzy treatment (especially rename), which is very sensitive to the correct configuration. If you are not careful, the fuzzy handler may destroy your application. In this section, we will discuss the very common problems that may occur when using a fuzzy handler.
First, when the application includes a strong named assembly, you need more work. Strong named assembly is a digital signature, allowing the running library to determine if the assembly has changed after the signature. This signature is a sha1 hash, the hash sign has a private key pair of RSA public key / private key. The signature and public key are embedded in the metadata of the assembly. Because the fuzzy handler modifies the assembly, it is important to sign after fuzzy processing. The signature set should be delayed before the development process and fuzzy processing, and then complete the signature process after fuzzy processing. For more details on latency signature assemblies, see the .NET Framework documentation and remember to close the strong name verification when testing the delayed signature.
Using the Reflection API and Dynamic Loading also complicates the fuzzy treatment process. Because these functions are dynamic, they tend to replace static analysis techniques used by most fuzzy treatment programs. Consider the following C # code snippet, which get a type by name and dynamically instantiates it, returns the type conversion to the interface: public myinterface getNewType () {
TYPE TYPE = Type.gettype (GetUserInputString (), TRUE
Object newinstance = activator.createInstance (TYPE);
Return newinstance as myinterface;
}
The name of the type comes from another method. GetUserInputString may require a user to enter a string or a string may be retrieved from a database. In any method, the type name does not appear in the code used to recover the static analysis, so it cannot be known which type in the input assembly may be instantiated in this way. The solution to this example is to prevent all potentially loadable types that implement MyInterface (please note that the method and field rename can be renamed). This is why manually configuring and understanding the application of fuzzy processing to play an important role. Dotfuscator Community Edition provides you with tools that prevent renaming selection types, methods, or fields. You can choose a separate name; in addition, you can write exclusion rules using regular expressions and other criteria (eg, visuality on the scope). For example, you can exclude all public methods to avoid renaming.
Another problem using a fuzzy handler occurs after deploying a fuzzy process, and trying to support it. Suppose your app triggers an exception (this even on our best people), the customer sends you the stack dump shown below:
System.exception: a serious error HAS OCCURRED
AT CV.A ()
AT CV..ctor (HashTable A_0)
AT Ar.A (DI A_0)
AT ae.a (string [] A_0)
Obviously, this is much less than the information obtained in stacking in the stack dump from the unflagous treatment program. Good news is that you can use the mapping file generated during the fuzzy processing to decode the stack track back to the original symbol. The bad news is sometimes not enough information in the stack trace to explicitly retrieve the original symbol from the mapping file. For example, the method of ignoring the method returns the type of notification in the dump. In applications that use enhanced overloaded backmodation algorithm fuzzy processing, only methods of the return type can be renamed to the same name. Therefore, stack tracking is blurred. In most cases, you can make the possibilities be small enough, so that the original name is found at a very high deterministic. To this end, Dotfuscator Professional provides a tool to move stack trace to the original problematic approach.
Back to top
summary
You don't need to let hackers use the ILDASM utility of your hand in your application in your application in order to be inappropriate. You can protect your code with a very well fuzzy handler. Fuzzy treatment has an obstacle to reverse engineering. In the Visual Studio .NET 2003 box, Dotfuscator Community Edition can complete a good fuzzy treatment only by clicking several clicks.
Related Articles, please refer to: Inside Microsoft .NET IL Assembler, the author is Serge Lidin (Microsoft Press, 2002) Dotfuscator FAQ For background information, see: ildasm.exetutorialandakrinohttp: //vexedddotnet.benamotz.comhttp: //www.preemptive. COMGABRIEL TOROK is the president of Preemptive Solutions. He is one of Javascript Primer Plus and Java Primer Plus, which is published by Macmillan. Gabriel has made a lot of reports in many software development seminars worldwide and provides tutorials.
Bill Leach is the Chief Technology Officer of Preemptive Solutions. He is the architect and technology leadership of the fuzzy handling program product line. Bill has done a technical review personnel for software development books and articles.
From MSDN Magazine, March 2003. This magazine can be purchased through newsstands from all over the country or subscribe.
Go to the original English page