preface

As you all know, most Android is currently written in Java, and even though Kotlin has been highly recommended by Google, there are still many projects that are written in Java, because it takes time for a language to change. As a result, Java code is known to be easy to decompile, so your own protection against decompilation is important.

This paper is mainly introduced from four aspects:

1. Proguard confusion

2. Fight decompiler tools

3. Fight android emulators

4. Counter APK repackaging

Proguard confusion

Proguard basis

Proguard is an open source project for obfuscation code. Proguard is mainly used for obfuscation, but it also has functions for bytecode reduction and optimization, etc. My main focus is obfuscation.

concept

The following two images are mixed and unmixed (found online) :

So you can see the difference between if confusion and no if confusion. Using obfuscation changes the name of the class completely, so it still works against decompilation if obfuscation is used.

Basic syntax:

-include {filename} reads configuration parameters from a given file. -basedirectory {directoryname} specifies the basedirectory as the relative filename. -injars {class_path} -outjars {class_path} Specifies the jar, WAR, EAR and directory to output when the jar,war,ear and directory are finished. - LIBRaryjars {classpath} Designated to deal with the application of the jar, war, ear library files and directories need - dontskipnonpubliclibraryclasses specified not to ignore the public library classes. - visible dontskipnonpubliclibraryclassmembers specified not to ignore the package library classes of members. Keep {Modifier} {class_specification} to protect specified class files and classmembers - keepClassMembers {Modifier} {class_specification} to protect specified classmembers, Keepclasseswithmembers {class_specification} Protects specified classes and class members, but only if all specified classes and class members exist. - keepNames {class_specification} protects the names of specified classes and members of classes (if they are not removed in the compression step) -keepclassmembernames {class_specification} To protect the names of the members of the specified class (if they don't compress steps removed) - keepclasseswithmembernames {class_specification} to protect the name of the specified class and a member of the class, If all specified class members are present (after the compression step) -printseeds {filename} lists the class and the members of the class -keep option, Standard output to a given file compression -dontshrink does not compress the input class file - printUsage {filename} -whyareyoukeeping {class_specification} optimization -dontoptimize Sumenosideeffects {class_specification} Optimizations assume specified methods, No side effects - AllowAccessModification optimizes when allowing access and modification of modifier classes and class members to be confused - Dontobfuscate Does not confuse input class files - printMapping {filename} - Applymapping {filename} reuse mapping to increase obfuscation - obfuscationDictionary {filename} uses keywords in a given file as the name of the method to be obfuscated -overloadaggressively Confusion when using invasive overloading - useuniqueclassmembernames sure united confusion class member name to increase the confusion - flattenpackagehierarchy {package_name} repackaging all renamed packages and on a given single package - repackageclass {package_name} repackage all rename class file in a given single package - dontusemixedcaseclassnames confusion when won't produce all kinds of class name - keepattributes {attribute_name,... } protects the given optional property, Examples include LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, And InnerClasses. - renamesourcefileattribute {string} set a given string constants in a source fileCopy the code

Actual code:

-ignorewarnings                     # Ignore warnings to avoid certain warnings when packing
-optimizationpasses 5               # specify the compression level of the code
-dontusemixedcaseclassnames         # whether to use mixed case
-dontskipnonpubliclibraryclasses    Whether to obfuscate third-party jars
-dontpreverify                      Whether to perform preverification in case of confusion
-verbose                            Whether to log when confusion occurs-optimizations ! code/simplification/arithmetic,! field/*,! class/merging/*# Algorithm used when obfuscation

-libraryjars   libs/treecore.jar  

-dontwarn android.support.v4.**     The default proGuard checks each reference for correctness, but third-party libraries often have unused classes that are not properly referenced. If not configured, the system will report an error.
-dontwarn android.os.**  
-keep class android.support.v4.** { *; }        Keep what classes from being confused-keep class com.baidu.** { *; } -keep class vi.com.gdi.bgl.android.**{*; } -keep class android.os.**{*; } -keep interface android.support.v4.app.** { *; } -keep public class * extends android.support.v4.** -keep public class * extends android.app.Fragment -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.support.v4.widget -keep public class * extends com.sqlcrypt.database -keep public class * extends com.sqlcrypt.database.sqlite -keep public class * extends com.treecore.** -keep public class * extends de.greenrobot.dao.** -keepclasseswithmembernames class * {# Keep native methods unconfused
   native <methods>;  
}  

-keepclasseswithmembers class * {            Keep custom control classes from being confused
   public <init>(android.content.Context, android.util.AttributeSet);  
}  

-keepclasseswithmembers class * {            Keep custom control classes from being confusedpublic <init>(android.content.Context, android.util.AttributeSet, int); } - KeepClassMembers class * extends Android.app.activity {// KeepClassMembers public void *(android.view.view); } -keepclassmembers enum * {Keep the enumeration enum class from being confused
   public static **[] values();  
   public static ** valueOf(java.lang.String);  
}  

-keep class * implements android.os.Parcelable {    # Keep Parcelable unconfused
 public static final android.os.Parcelable$Creator *;  
}  

-keep class MyClass;                              Keep self-defined classes from being confused
Copy the code

** Note: ** There are certain parts of Android that should not be confused, and an exception will occur if they are confused:

  • The four major components are registered with Mainfest and should not be confused
  • The Java interface method that jin calls
  • System interface method
  • Obfuscation of R files can lead to incorrect references (if reflection is used somewhere, R files will not find resources after obfuscation)

Anti-decompilation

Prevent decompilation methods

1. Proguard obfuscation can not only obfuscate code, but can also cause decompiler failures or crashes

2. Use the current domestic APK reinforcement methods. As far as I know, if you want to release your application in 360 market and Tencent market, you must use the reinforcement methods of their corresponding market: 360 reinforcement and Legu reinforcement

What are some of the decompiler tools we use?

  • apkTool
  • baksmali
  • dex2.jar
  • JEB

We can use the above two methods to decompilate these decompilators and make them hard to read or even disable the decompilator or.

As the method of confusion has been mentioned before, it is not necessary to repeat it. It is more simple to use the domestic APK reinforcement method. You can download the tool for reinforcement from the designated official website, and the document description is very detailed.

Prevention simulator

Prevent simulator reverse analysis

Reason: The reverse analysis state is usually run in the Android emulator, so we only need to determine in the code whether our current APK is running in the emulator.

There are several ways to check whether it is a simulator:

  • Detect several special files on the simulator
  • Detect the special number on the simulator
  • Check whether the DEVICE IDS is 000000000000000.
  • Check whether there are sensors and Bluetooth
  • Detect hardware information that is unique to the phone
  • Check your phone’s carrier

Here I use code to demonstrate:

Check the IDS

/** * check IDS ** @param context * @return
    */
   public static boolean chechDeviceIDS(Context context) {
       @SuppressLint("ServiceCast")
       TelephonyManager telecomManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
       @SuppressLint("MissingPermission")
       String deviceId = telecomManager.getDeviceId();
       if (deviceId.equalsIgnoreCase(DEVICE_ID)) {
           Log.e(TAG, "chechDeviceIDS==" + DEVICE_ID);
           return true;
       }
       return false;
   }
Copy the code

Check emulator specific files

/** * Check emulator specific files ** @param context * @return
    */
   public static boolean chechDeviceFile(Context context) {
       for (int i = 0; i < DEVICE_FILE.length; i++) {
           String file_name = DEVICE_FILE[i];
           File qemu_file = new File(file_name);
           if (qemu_file.exists()) {
               Log.e(TAG, "chechDeviceFile==" + true);
               return true; }}return false;
   }
Copy the code

Check the emulator unique number

/** * check the unique phone number ** @param context * @return
    */
   public static boolean chechDevicePhone(Context context) {
       @SuppressLint("ServiceCast")
       TelephonyManager telecomManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
       @SuppressLint("MissingPermission")
       String phoneNumber = telecomManager.getLine1Number();
       for (String phone : DEVICE_PHONE) {
           if (phone.equalsIgnoreCase(phoneNumber)) {
               Log.e(TAG, "chechDevicePhone==" + phoneNumber);
               return true; }}return false;
   }
Copy the code

Check whether the emulator contains these devices

/** * check to see if there is a device ** @param context * @return
    */
   public static boolean chechDeviceBuild(Context context) {
       String board = Build.BOARD;
       String bootloader = Build.BOOTLOADER;
       String brand = Build.BRAND;
       String device = Build.DEVICE;
       String hardware = Build.HARDWARE;
       String model = Build.MODEL;
       String product = Build.PRODUCT;

       if (board.equalsIgnoreCase("unknown") || bootloader.equalsIgnoreCase("unknown")
               || brand.equalsIgnoreCase("generic") || model.equalsIgnoreCase("sdk")
               || product.equalsIgnoreCase("goldfish")) {
           Log.e(TAG, "chechDeviceBuild==" + "find emulatorBuild");
           return true;
       }
       return false;
   }
Copy the code

Running results:

We can see that all the printed results show emulators. Please do not forget to add permissions when obtaining these information:

From the above we can determine whether it is a simulator, then we can kill the APP or the process in which the APP is located.

Secondary packaging

Preventing secondary packaging

  • What is double packing?
  • The SMALI code is obtained by decompiling tools, and then the SMALI code is repackaged to form APK, and finally re-signed to run.

If the program is in cracked state, our APK must be re-signed to run on the real computer or simulator, so the signature at this time must be inconsistent with the original signature. We can judge our signature at the entrance of the program to judge the second packaging.

The code is as follows:

public class MainActivity extends AppCompatActivity {
   private static final String TAG = "MainActivity";

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       Log.e(TAG, "getSignature=="+getSignature("demo.lt.com.repacking"));
   }

   private int getSignature(String packageName) {
       PackageManager packageManager = this.getPackageManager();
       PackageInfo info = null;
       int sig = 0;
       try {
           info = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
           Signature[] signatures = info.signatures;
           sig = signatures[0].hashCode();
       } catch (Exception e) {
           sig = 0;
           e.printStackTrace();
       }

       returnsig; }}Copy the code

Get the signature hashCode is unique:

So we just need to add more code to determine the secondary packaging:

public class MainActivity extends AppCompatActivity {
   private static final String TAG = "MainActivity";

   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       Log.e(TAG, "getSignature==" + getSignature("demo.lt.com.repacking"));
       if (getSignature("demo.lt.com.repacking") != -567503403) {
           Log.e(TAG, "Repackaged.");
       }
   }

   private int getSignature(String packageName) {
       PackageManager packageManager = this.getPackageManager();
       PackageInfo info = null;
       int sig = 0;
       try {
           info = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
           Signature[] signatures = info.signatures;
           sig = signatures[0].hashCode();
       } catch (Exception e) {
           sig = 0;
           e.printStackTrace();
       }

       returnsig; }}Copy the code

I’m just printing a Log here, but in actual code I can either end the process or kill the APP.

In one sentence

The above is the knowledge of today’s Android protection, not require you to be proficient in Android protection, but we as an Android developer must know these knowledge points, I believe you must be useful.

Original writing is not easy, if you think it is good, scan the code to pay attention to the point of praise, is my biggest motivation.

Follow me, there will be unexpected things waiting for you: Android, Java, big data and other video resources, books waiting for you to take. Focus on sharing Android, JAVA dry goods every day