Prevent reverse engineering of Visual Basic. Net or C # code. Release Date: 12/28/2004 | update date: 12/28/2004
Gabriel Torok and Bill Leaching
This document assumes that you are familiar with. NET and C #
Summary
One of the advantages of. NET architecture is that an assembly built using this architecture contains a lot of useful information that can be restored using the intermediate language disassembly program ildasm. However, this will bring about another problem, that is, people who can access your binary code can restore the original source code in a very similar way. The author will introduce the program fuzzy processing in this article, which can be used as a means to prevent reverse engineering. They will also discuss different types of fuzzy processing technologies available and demonstrate the new fuzzy processing tools included in Visual Studio. NET 2003.
Content on this page
|
Disassembly |
|
Decompilation |
|
Deep understanding of fuzzy processing |
|
Rename metadata |
|
Delete non-basic metadata |
|
Other technologies |
|
Use dotfuscator community Edition |
|
Check the ing File |
|
Defects of the fuzzy processing program |
|
Summary |
From now on, you may be familiar with the rich metadata Microsoft. net Framework architecture brings all the benefits. You may not know the ease of use of metadata brings about a problem that has not been noticed by most developers currently. Programs written for the Common Language Runtime Library (CLR) are easier to reverse engineering. In any case, this is not a defect in the. NET Framework Design; it is just a modern, intermediate compilation language (Java language applications have the same characteristics) reality. Both Java and. NET Framework use rich metadata embedded in executable code: bytecode in Java and Microsoft intermediate language (msil) in. net ). Because it is much more advanced than binary machine code, executable files are full of information that can be easily cracked.
With the help of tools such as ildasm (along.. NET Framework SDK) or similar to anakrino and reflector. net, anyone can easily view your assembly and reverse engineer it into readable source code. Hackers can search for security defects to explore, steal unique ideas, and crack programs. This is enough to make you hesitate.
Do not worry. There is a fuzzy processing solution that helps you prevent reverse engineering. Fuzzy processing is a technique that provides seamless Rename for symbols in an assembly. It also provides other techniques to prevent the deserialization program. If appropriate, fuzzy processing can greatly improve the application's ability to prevent reverse engineering, while keeping the application intact. Fuzzy processing technology is usually used in Java environments. Over the years, it has helped many companies protect their intellectual property rights based on Java technology products.
Currently, many third parties have responded by creating a. Net code fuzzy handler. Microsoft Works with our company preemptive solutions in Visual Studio ?. NET 2003 contains dotfuscator community edition, and preemptive solutions also introduces a variety of fuzzy processing program software packages.
By using dotfuscator community edition, this article will teach you all the content related to fuzzy processing (a brief introduction to disassembly) the types of fuzzy processing available and the problems to be solved when the fuzzy processing program is used.
To demonstrate decompilation and fuzzy processing, we will use an open-source implementation of the classic vexed game. Vexed. NET is written by roey Ben-amotz and can be obtained from the http://vexeddotnet.benamotz.com. This is a smart game, and your goal is to move similar blocks together to make them disappear. The following is a simple method in 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 comes with a disassembly utility named ildasm that allows you to decompile. NET Framework Assembly into il assembly language statements. To start ildasm, you must ensure that the. NET Framework SDK is installed, enter ildasm in the command line, and then the name of the program you want to disassemble. In the current example, we will enter "ildasm vexed.net.exe ". In this way, the ildasm UI will be started, which can be used to browse any. NET Framework-based application structure.Figure 1Shows the Undo method that has been decompiled.
Back to Top
Decompilation
If you think that only a few people who really know the Il assembly language will see and understand your source code, please remember that The Decompilation will not end here. We can use the decompilation program to create the actual source code. These utilities can decompile. Net Assembly directly into advanced languages such as C #, Visual Basic. net, or C ++. Let's take a look at the Undo method generated by the anakrino disassembly 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 identical to that of the original code. Later, we will return here to view the results after fuzzy processing.
Back to Top
Deep understanding of fuzzy processing
The paste processing is implemented using a set of related technologies. The purpose of fuzzy processing is to hide the program's intention without changing its runtime behavior. It is not encrypted, but it may be better than encrypted for. Net code. You can encrypt. Net Assembly to make them completely unreadable. However, this method may cause a typical dilemma, because the Runtime Library must execute unencrypted code and the decryption key must be stored together with the encrypted program. Therefore, you can create an automated utility to restore the key, decrypt the code, and write it to the disk in the original form of Il. Once this happens, the program is completely exposed to the decompilation.
We can compare encryption to locking a package containing six dishes into a box. Only the intended diners (CLR in this example) have keys, and we do not want anyone else to know what he or she is going to eat. Unfortunately, at the meal time, all the food will be completely under the eyes of everyone. Fuzzy processing is more like placing a package containing six dishes in a blender and then placing it in a plastic bag for diners. Of course, everyone can see the food being delivered, but they don't know what the original food is except that they happen to see a full pea or some beef-colored paste. The diners still get what they want, and the meal still offers the same nutritional value as before (Fortunately, CLR is not picky about taste ). The trick of the fuzzy processing program is to confuse the hacker, and the program can still submit the same product to the CLR.
Of course, fuzzy processing (or encryption) is not completely indestructible. Even after compilation, C ++ may be decompiled. If the hacker persists, he can re-generate your code.
Figure 2Fuzzy processing process
The obfuscation process is a process applied to the compiled. Net Assembly instead of the source code. The Fuzzy handler will never read or change your source code. Figure 2 shows the fuzzy processing process. The output of the fuzzy processing program is another set of assembly, which is functionally equivalent to the input assembly, but the program is converted in a way that hinders reverse engineering. Now we will discuss the two basic technologies used by dotfuscator community edition to achieve this goal: renaming and deleting non-basic metadata.
Back to Top
Rename metadata
The first line of defense for obfuscation is to rename a meaningful name to a meaningless name. As you know, there are many valuable clues from carefully selected names. They help document your code and serve as valuable clues to reveal the projects they represent. The CLR does not care about the descriptive nature of a name, so the fuzzy handler can modify these names freely, typically a single character name similar to ".
Obviously, the fuzzy processing program has a limit on the number of renames that a specific program can execute. Generally, there are three common rename schemes.
If your application is composed of one or more independent assemblies (that is, Codes Without fuzzy processing do not depend on any assemblies), the fuzzy processing program can rename the Assembly freely, regardless of the name's observability, as long as the name and the reference to the name are consistent in the assembly group. Windows Forms applications are a good example. As an extreme example of the opposite, if your application is designed to be used by unblurred code, then, the fuzzy handler cannot change the types or member names visible to the customer. Examples of such applications include shared class libraries, reusable components, and so on. The two are applications that are intended to be inserted into the existing framework without fuzzy processing. In this case, the fuzzy processing program can rename anything that is not accessed in the environment where it is running, regardless of visibility. ASP. NET applications are good examples of such applications.
Dotfuscator community Edition uses a patented rename technology called "reload induction", which can add a twist to the rename. After detailed analysis scope, method identifiers are overloaded to the maximum extent. The overload induction technique is not to replace the old name with a new name, but to rename many methods as much as possible to the same name, so as to confuse those who try to understand the decompilation code.
In addition, as a good sub-application, the size of the application decreases as the String Heap contained in the Assembly decreases. For example, if you have a name with a length of 20 characters, renaming it as "a" will save 19 characters. In addition, it saves space by saving the String Heap items and continuously re-using rename. Rename each item as "a" means that "A" is stored only once, and each method or field renamed as "A" can point to it. This effect is enhanced by overload induction because the shortest identifier is continuously reused. Generally, up to 35% of the methods for a reload induction project are renamed as "".
To understand the impact of Renaming on decompiled code, see the Undo method after renaming:
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);
}
}
As you can see, this method is hard to understand without any fuzzy processing.
Back to Top
Delete non-basic metadata
In compiled. Net-based applications, not all metadata is used at runtime. Some of the data will be used by other tools (such as the designer, IDE, and debugger ). For example, if you define an attribute named "size" in Type C #, the compiler will omit the metadata of the attribute name "size, and associate the name with the methods that implement the get and set operations (they are named "get_size" and "set_size" respectively "). When you start to write code for setting the size attribute, the compiler will always generate a call to the method "size-size" itself, and will never reference this attribute through its name. In fact, the attribute name is used by IDE and developers who use your code; CLR never accesses it.
If you only use your application by using the Runtime Library rather than other tools, it is safe for the fuzzy handler to delete this type of metadata. In addition to attribute names, event names and method parameter names are also listed in this category. Dotfuscator community edition deletes all these types of metadata when it deems it safe to do so.
Back to Top
Other technologies
Dotfuscator community Edition uses the technology we just introduced to provide good fuzzy processing, but you should know that the fuzzy processing technology provides more powerful protection while, the reverse engineering may also be blocked. Dotfuscator Professional Edition implements many other technologies, including control flow fuzzy processing, string encryption, incremental fuzzy processing, and scale reduction.
Control flow is a powerful fuzzy processing technology. It aims to hide the intent of a series of commands without changing the logic. More importantly, it can be used to delete the clues that The Decompilation program is looking for to faithfully reproduce advanced source code statements (such as if-then-else statements and loops. In fact, this technology is trying to disrupt the work of the disassembly program.
To view the running effect, after using Rename and control flow fuzzy processing, study the decompiled undo method again (seeFigure 3). You can see that the disassembly program does not generate the original nested if statement, but generates an if statement, two nested while loops, and some goto which they are bundled. The label I1 is referenced, but it is not generated by the decompilation Program (we assume it is an decompilation program error ).
String encryption is a technology that applies simple encryption algorithms to strings embedded in your applications. As mentioned above, any encryption (or decryption in special cases) executed during runtime is fundamentally insecure. That is to say, hackers with superb technology can actually crack it, but it is worth doing so for strings in application code. We are faced with the fact that if hackers want to enter your code, they will not blindly start to search for renamed types. They may indeed search for "invalid license keys", which will direct them to code that executes license processing. Searching strings is not always simple; string encryption settings are protected because only encrypted versions exist in the compiled password.
Incremental Fuzzy processing helps release patches to solve problems that customers encounter in the face of fuzzy processing. When fixing errors in code, classes, methods, or fields are often created or deleted. Changing Code (for example, adding or deleting a method) may cause subsequent fuzzy processing to run, thus slightly changing the rename of a transaction. The name previously called "A" may now be called "B ". Unfortunately, it is not easy to figure out how to rename or rename different content.
Incremental Fuzzy processing can solve this problem. Dotfuscator creates a ing file to show you how it is renamed. However, this ing file can also be used for dotfuscator input in subsequent operations to indicate that the previously used rename should be used again wherever possible. If you release your product and then fix some classes, dotfuscator runs in a way that imitates its previous rename solution. In this way, you can only publish repaired classes to your customers.
Reducing the scale does not strictly block reverse engineering, but it is worth mentioning that because the fuzzy processing program almost always has to perform dependency analysis on the input assembly. Therefore, the fuzzy processing program can not only perform fuzzy processing well, but also use your understanding of the application program to delete unused code of your program. It seems a bit strange. In fact, it is very easy to delete unused code. Who wrote the unused code? The answer is, all of us. In addition, we all use reusable libraries and types written by others.
Reusable code means that there is some accompanying code that can process many use cases, but in any given application, you usually only use one or two of these many use cases. The advanced fuzzy processing program can determine this and delete all unused code (and, instead of from the compiled assembly ). The result is that the output contains exactly the types and methods that your application no longer needs. Small applications can save computing resources and shorten loading time. These benefits are especially important for applications or distributed applications running on. NET Compact framework.
Back to Top
Use dotfuscator community Edition
Now let's use dotfuscator community edition to blur the vexed application. Dotfuscator community Edition uses a configuration file to specify the fuzzy processing settings for a specific application. It allows you to easily create and maintain configuration files, run the fuzzy processing program, and check the output. In addition, the dotfuscator community edition command line interface allows you to easily integrate fuzzy processing into your automatic generation process. You can start the GUI directly from the Tools menu of Visual Studio. NET 2003.
To configure vexed for fuzzy processing, you must specify three items in the dotfuscator community edition Gui: Input assembly, ing file location, and output directory. The input assembly (called the trigger assembly) is specified on the trigger tab. You can add any number of assemblies as needed, but only one is required for the vexed application.
On the "RENAME | options" tab, specify the location of the ing file (see figure 4 ). The ing file contains a clear name ing between the original name and the name to be blurred, which is crucial. It is important to save the file after you perform fuzzy processing on the application. Without this file, you cannot easily check for errors of the application that has been blurred. Because of its importance, dotfuscator does not rewrite the existing ing file by default, unless you explicitly select the "Overwrite map file" box.
Finally, the "build" Tab allows you to specify the directory of the fuzzy processed application. After completing the above work, You can blur the application. You can save the configuration file for future use, and then press the "build" button on the "build" tab, or use the "play" button on the toolbar. During building, dotfuscator displays progress information in the GUI output pane. On the options tab, select quiet or verbose to control the amount of information displayed here.
Once the generation is complete, you can browse the results on the output tab, as shown in figureFigure 5. As you can see, dotfuscator displays an application graphics view similar to the Object Browser. The new name is located at the bottom of the original name in the view. In this figure, you will see that the class named "board" is renamed to "H", and the two methods (init and toimage) with different signatures are renamed to "".
Back to Top
Check the ing File
The ing file generated by dotfuscator is an XML file that contains not only the preceding name ing, but also some statistics that indicate the validity of the renaming process.Figure 6Summarizes the types and methods of the vexed application after fuzzy processing.
The ing file is also used for incremental fuzzy processing. This process allows you to import names from previous operations, which will notify the fuzzy processing program to perform rename in the same way as before. If a hotfix (or new plug-in) is released for a fuzzy processing application, you can perform fuzzy processing on the updated application using the same name set as the original version. This is especially useful for enterprise development teams that maintain multiple interdependent applications.
Back to Top
Defects of the fuzzy processing program
Fuzzy processing (especially renaming) for complex applications is tricky and highly sensitive to correct configurations. If you are not careful, the fuzzy processing program will interrupt your application. In this section, we will discuss some common problems that may occur when using the fuzzy processing program.
First, if your application contains a strongly-named assembly, you need to do more work. A strongly-named assembly is digitally signed and allows the runtime to determine whether the Assembly has been changed after the signature. A signature is a sha1 hash value that uses the RSA public/private key pair to sign a private key. Both the signature and public key are embedded in the Assembly metadata. Because the fuzzy processing program modifies the program, it is very important to perform the signature after the fuzzy processing. You should delay the signature of the Assembly during development and before fuzzy processing, and then complete the signing process. For more information about delayed signature assembly, see. NET Framework documentation. Remember to disable strong name verification when testing the delayed signature assembly.
Using the reflection API and dynamic class loading will also increase the complexity of the fuzzy process. Since these utilities are dynamic, they are superior to the static analysis used by most fuzzy processing programs. Consider the following C # code snippet, which obtains the type by name and dynamically instantiates it, And then converts the type and returns it to the interface:
public MyInterface GetNewType() {
Type type = Type.GetType( GetUserInputString(), true );
object newInstance = Activator.CreateInstance( type );
return newInstance as MyInterface;
}
The type name comes from another method. Getuserinputstring may require the user to enter a string or retrieve a string from the database. No matter which method is used, the Code does not display the type names that can be recovered from static analysis. Therefore, you cannot understand which types in the input set may be instantiated using this method. In this case, the solution is to prevent renaming all potential load types that implement myinterface (note that you can still rename methods and fields ). Therefore, manual configuration and mastering of some application related to fuzzy processing are very important here. Dotfuscator community edition provides multiple tools to prevent renaming of the selected type, method, or field. You can select and select a unique name. Alternatively, you can use regular expressions and other standards (such as scope visibility) to write exclusion rules. For example, you can exclude all public methods from renaming.
When you have deployed a fuzzy processing application and try to support it, another problem occurs when you use the fuzzy processing program. Assume that the application throws an exception (this happens for most people) and the customer sends you the following stack dump:
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)
Apparently, the above stack dump contains less information than the information contained in the program that has not been blurred. On the other hand, you can use the ing file generated during fuzzy processing to decode the stack trace back to the original code. The downside is that messages in the stack trace are sometimes insufficient to explicitly retrieve original symbols from the ing file. For example, note that the method return type is omitted in the dump. In the application that uses the enhanced overload induction and rename Algorithm for fuzzy processing, only methods of different return types may be renamed to the same name. Therefore, stack tracing may be arbitrary. In most cases, you can narrow down the search dimensions so that you are more sure to find the original name. To get help, dotfuscator professional provides you with a tool to automatically convert stack tracing back to the original method you don't like.
Back to Top
Summary
You can prevent hackers from using the ubiquitous ildasm utility to maliciously process your applications. You can use a fuzzy processing program to protect your code. Fuzzy processing can effectively prevent reverse engineering. With dotfuscator community edition provided in Visual Studio. NET 2003, you can perform fuzzy processing with just a few clicks.
For more information, see
Inside Microsoft. NET il extends erBy Serge lidin (Microsoft Press 2002)
Dotfuscator FAQ
For background information, see
Ildasm.exe tutorial
Anakrino
Http://vexeddotnet.benamotz.com
Http://www.preemptive.com
Gabriel TorokHe is the president of preemptive solutions. He and others co-authorJavascript primer plusAndJava primer plusBoth books are published by Macmillan. Gabriel gave speeches and lectures at development conferences around the world.
Bill LeachingIs the chief technology officer of preemptive solutions. He is the architect and Technical Director of the dotfuscator product line. Bill also serves as a technical comment on software development books and articles.
Go to the original English page
Back to Top