Android obfuscation of app code
Receives a new task to confuse the code of the existing project. I have had some knowledge about obfuscation before, but it is not detailed or complete enough to know that obfuscation is still tricky. But fortunately, the current project is not too complex (for obfuscation purposes) and can be completed in advance ~~ This is a summary.
Part 1
This section describes the procedure (eclipse ):
1. Open the obfuscator: Find the project under the project root directory. properties file, set "# proguard. config =$ {sdk. dir}/tools/proguard/proguard-android.txt: proguard-project.txt this line before the '#' Delete;
2. Modify the obfuscation configuration file: Find the proguard-project.txt file under the project root directory and modify the code. This part is the most critical;
3. Save the relevant files for future use when an error occurs: the files in the proguarddirectory (the main object is mapping.txt) and the project source code under the project root directory (the main object is mapping.txt;
4. error handling during project running: locate the error location based on the error information and the ing saved in step 1.
After knowing this, we will expand it. After you start eclipsean, a new project will be created, and the project. properties and proguard-project.txt will be created. Compile our code, and then copy the content in "# proguard. config =$ {sdk. dir}/tools/proguard/proguard-android.txt: volumes of proguard-project.txt. The following is my test code:
public class MainActivity extends Activity {private String mName;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mName = ttdevs;getString(mName);setName(mName);showDialog();// testError();}public String getString(String name) {return hello + name;}public void setName(String name) {System.out.println(I'm + name);}private void showDialog() {new Handler().postDelayed(new Runnable() {@Overridepublic void run() {ScoreAlertDialog.showDialog(MainActivity.this);}}, 2000);}public static class ScoreAlertDialog {public static void showDialog(final Activity activity) {if (activity.isFinishing()) {return;}try {AlertDialog.Builder builder = new AlertDialog.Builder(activity);builder.setTitle(alert_title);builder.setNegativeButton(cancel, null);builder.setPositiveButton(submit, new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {try {Toast.makeText(activity, Welcome, Toast.LENGTH_LONG).show();} catch (Exception e) {e.printStackTrace();}}});builder.show();} catch (Exception e) {e.printStackTrace();}}}private void testError() {try {int error = 1 / 0;} catch (Exception e) {e.printStackTrace();}}}
Package, decompile, and finally we get the following code:
After analyzing the code above, we will find that all the custom method names are replaced with short letters without special meanings, but the onCreate () method of the activity is not changed; the last testError () the method is also removed because it is not called. These are the default obfuscation policies. Here we can see that the confusion is still a small case ~~
Proceed to the next step. Open the logged-out testError () and run the package. An error is returned. The error message is as follows:
java.lang.ArithmeticException: divide by zero at com.ttdevs.proguard.MainActivity.b(Unknown Source) at com.ttdevs.proguard.MainActivity.onCreate(Unknown Source) at android.app.Activity.performCreate(Activity.java:4531) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1071) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2150) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2229) at android.app.ActivityThread.access$600(ActivityThread.java:139) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1261) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:4945) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at dalvik.system.NativeStart.main(Native Method)
Because this example is simple, it is easy to see that there is a problem anywhere, but it can still be used to illustrate the problem we want to express: how to restore the error message of the obfuscated code. To achieve this goal, we need three files: android-sdk-windows oolsproguardin etrace.bat、mapping.txtand the error information (log.txt ). Then execute the following command (window system ):
retrace.bat mapping.txt log.txt
We can clearly see that the B () method in the error log is the setName () method in our actual code.
Note that every time the apk is exported, a corresponding mapping file is generated in the proguard folder under the project directory. Therefore, for each apk, we need to save the corresponding mapping file. So far, the entire obfuscation process has been introduced.
Refer:
Official documents: http://developer.android.com/tools/help/proguard.html
Http://www.cnblogs.com/over140/archive/2011/04/22/2024528.html (I wanted to flip one by myself, the results found that a long time ago the farmer uncle has been translated, here directly reference and thank it)
Part 2
The first part describes how to perform the operation. Refer to the official documentation to learn about the operation. The remaining one is the most difficult to compile the proguard-project.txt file. For this part, there are two processing strategies: Writing by yourself and using the ones written by others. First, let's talk about how to use a third-party library written by others. No matter whether it is open source or closed source, we can find configuration of obfuscated code in its User Guide in special circumstances, if we reference the famous guillep PullToRefresh, we can find the following code in his document:
-optimizationpasses 5-dontusemixedcaseclassnames-dontskipnonpubliclibraryclasses-dontpreverify-verbose-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*-keep public class * extends android.app.Activity-keep public class * extends android.app.Application-keep public class * extends android.app.Service-keep public class * extends android.content.BroadcastReceiver-keep public class * extends android.content.ContentProvider-keep public class * extends android.app.backup.BackupAgentHelper-keep public class * extends android.preference.Preference-keep public class com.android.vending.licensing.ILicensingService-keepclasseswithmembernames class * { native
;}-keepclasseswithmembernames class * { public
(android.content.Context, android.util.AttributeSet);}-keepclasseswithmembernames class * { public
(android.content.Context, android.util.AttributeSet, int);}-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String);}-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *;}
With this part of code, we can directly copy and insert it into our project. This method is still copy. Let's take a small example to see how to write code to control obfuscation. "#" In comment indicates comment ):
# -keep public class com.ttdevs.proguard.** { *; }# -keepclasseswithmembers public class com.ttdevs.proguard.** { *; }-keep public class com.ttdevs.proguard.MainActivity {java.lang.String getString(java.lang.String);}
Then we export the apk and decompile it to get the following code:
Compared with the previous one, we found that the getString method is not obfuscated. No error. When proguard-project.txt means that the getString () method of MainActivity should not be confused. You can also try the effect of the two lines commented in the above obfuscation code.
The core part of ProGuard has been involved. The rest is to study the ProGuard documentation, master its syntax, and use it. I wanted to find a complete ProGuard translation document, but I haven't found one after finding N for a long time, and there are very few scattered translations. The recent time is very short, and the ability is limited, it is also difficult to translate several frequently-used commands, so the idea of carefully reading can only be pushed back for the moment. Here is a brief introduction to the keep command:
-Keep [, modifier,...] class_specification
Specify the members (attributes and methods) of the class or class reserved as the starting point in your code ). For example, to maintain an application, you can specify the main class and its main method. To process a library, you need to describe its public access elements in detail.
In addition, there is a brief summary of the keep and a standard in the syntax. The Class Specification will show you how to represent the constructor, attributes, and methods, and the difference between * And. For example, * Indicates matching any class name but not including the package separator, while ** indicates matching any class name and including any number of package separators, therefore, the Code mentioned above is as follows: the first line: Keep com. ttdevs. all classes under proguard are not confused with all methods of classes under the sub-package, and the second line keeps com. ttdevs. all methods and member variables of classes under proguard and sub-packages are not confused.
// There are many more details about TODO, such as-libraryjars,-dontwarn, and-keepattributes.