In order to increase the security of apk and prevent it from being decompiled and cracked (for example, the commonly used decompile tool jadx GUI).
During the development of apk, the developer will work on the project Proguard rules After the confusion commonly used by google is added to the pro file and encrypted and packaged with the key alias, some third-party reinforcement methods (reinforcement, a certain degree of compression and security enhancement) or apk shelling Technology (the file will be compressed, the security will be increased, and the disadvantage: it is not available after version update) will also be used to reinforce the package.
Commonly used reinforcement methods of apk at present:
Tencent legu, 360 reinforcement and love encryption, or reinforcement using the official website: Tencent reinforcement address
360 reinforcement has one disadvantage: the strengthened apk will automatically generate libjiagu Some models in the so library occasionally report errors: (according to several years of work experience of colleagues, the problem is still in their own code)
Although after encryption, the security of the software is higher, but it is not impeccable. Some anti reinforcement technologies and shelling technologies came into being. What I want to say today is Tencent legu, 360 reinforcement and one key shelling.
tool
To shell the apk files of Android, the following software is required:
FDex2
VirtualXposed
However, it should be noted that this technology is available in Android 9 0 and above is not feasible, and virtualxposted has software version restrictions.
FDex2
Download address:
Link: https://pan.baidu.com/s/10ZfD2MSfukuLdxvUZIAyjA Extraction code: asu1
VirtualXposed
Virtual Xposed: you can use the Xposed framework without a root phone
Download link:
https://vxposed.com/
Shelling
First, install virtualxposted, FDex2 and applications that need to be shelled on the mobile phone. Then, start VirtualXposed and install FDex2 in VirtualXposed.
Then, select module management to activate FDex2 in virtual xposed.
Install the application to be shelled in virtualxposted. The specific steps are the same as those above. Then, start FDex2 in virtualxposted and configure the application to be shelled.
Run the application to be shelled in virtualxposted. The dex file after shelling is as follows:
Then, use the adb pull command to export the shelled dex file to the computer.
adb pull /data/user/0/iv.va.exposed/virtual/data/user/0/{packageName}
Finally, decompile the shelled DEX through dex2 jar.
FDex2 core code
package com.ppma.xposed; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Method; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XSharedPreferences; import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.callbacks.XC_LoadPackage; public class MainHook implements IXposedHookLoadPackage { XSharedPreferences xsp; Class Dex; Method Dex_getBytes; Method getDex; String packagename; public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable { xsp = new XSharedPreferences("com.ppma.appinfo", "User"); xsp.makeWorldReadable(); xsp.reload(); initRefect(); packagename = xsp.getString("packagename", null); XposedBridge.log("Set package name:"+packagename); if ((!lpparam.packageName.equals(packagename))||packagename==null) { XposedBridge.log("The current package name is inconsistent with the setting or the package name is empty"); return; } XposedBridge.log("Destination package name:"+lpparam.packageName); String str = "java.lang.ClassLoader"; String str2 = "loadClass"; XposedHelpers.findAndHookMethod(str, lpparam.classLoader, str2, String.class, Boolean.TYPE, new XC_MethodHook() { protected void afterHookedMethod(MethodHookParam param) throws Throwable { super.afterHookedMethod(param); Class cls = (Class) param.getResult(); if (cls == null) { //XposedBridge.log("cls == null"); return; } String name = cls.getName(); XposedBridge.log("Current class name:" + name); byte[] bArr = (byte[]) Dex_getBytes.invoke(getDex.invoke(cls, new Object[0]), new Object[0]); if (bArr == null) { XposedBridge.log("Empty data: Return"); return; } XposedBridge.log("Start writing data"); String dex_path = "/data/data/" + packagename + "/" + packagename + "_" + bArr.length + ".dex"; XposedBridge.log(dex_path); File file = new File(dex_path); if (file.exists()) return; writeByte(bArr, file.getAbsolutePath()); } } ); } public void initRefect() { try { Dex = Class.forName("com.android.dex.Dex"); Dex_getBytes = Dex.getDeclaredMethod("getBytes", new Class[0]); getDex = Class.forName("java.lang.Class").getDeclaredMethod("getDex", new Class[0]); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } } public void writeByte(byte[] bArr, String str) { try { OutputStream outputStream = new FileOutputStream(str); outputStream.write(bArr); outputStream.close(); } catch (IOException e) { e.printStackTrace(); XposedBridge.log("File write out failed"); } } }
Through the loadClass method of Hook ClassLoader, the reflection calls the getDex method to obtain Dex(com.android.dex.Dex class object), and then writes out the Dex in it. This is the principle of Hook.