今天给大家讲一下app防破解技术,很多开发者在app的安全层面知道的并不多,导致自己费了很多时间写的apk被轻易破解,代码被盗用分析关键信息。现在从以下几点来阐述:
1.Java代码是比较容易反编译的,为了很好的保护Java代码,我们往往会对编译好的class文件进行混淆处理
在app的build.gradle文件设置 minifyEnabled true,并在proguard-rules.pro添加
-optimizationpasses 5 # 指定代码的压缩级别 -dontusemixedcaseclassnames # 是否使用大小写混合 -dontpreverify # 混淆时是否做预校验 -verbose # 混淆时是否记录日志 -keepattributes Signature -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 方法不被混淆 native <methods>; } -keepclasseswithmembers class * { # 保持自定义控件类不被混淆 public <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * {# 保持自定义控件类不被混淆 public <init>(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers class * extends android.app.Activity { # 保持自定义控件类不被混淆 public void *(android.view.View); } -keepclassmembers enum * { # 保持枚举 enum 类不被混淆 public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { # 保持 Parcelable 不被混淆 public static final android.os.Parcelable$Creator *; }
2.去除日志信息
-assumenosideeffects class android.util.Log { public static *** d(...); public static *** v(...); } -assumenosideeffects class android.util.Log { public static *** e(...); public static *** v(...); } -assumenosideeffects class android.util.Log { public static *** i(...); public static *** v(...); } -assumenosideeffects class android.util.Log { public static *** w(...); public static *** v(...); }
3.对抗反编译工具,做资源混淆
4.对抗模拟器
public static Boolean notHasLightSensorManager(Context context) { SensorManager sensorManager = (SensorManager) context.getSystemService(context.SENSOR_SERVICE); Sensor sensor8 = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); //光 if (null == sensor8) { return true; } else { return false; } }
/** * 用途:根据CPU是否为电脑来判断是否为模拟器 * @return */ public static boolean checkIsNotRealPhone() { String cpuInfo = readCpuInfo(); if ((cpuInfo.contains("intel") || cpuInfo.contains("amd"))) { return true; } return false; } /** * 用途:根据CPU是否为电脑来判断是否为模拟器(子方法) * @return */ public static String readCpuInfo() { String result = ""; try { String[] args = {"/system/bin/cat", "/proc/cpuinfo"}; ProcessBuilder cmd = new ProcessBuilder(args); Process process = cmd.start(); StringBuffer sb = new StringBuffer(); String readLine = ""; BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8")); while ((readLine = responseReader.readLine()) != null) { sb.append(readLine); } responseReader.close(); result = sb.toString().toLowerCase(); } catch (IOException ex) { } return result; }
5.对抗apk重打包
if(getSignature("security.tct.com.intentvirus") != -457442184){ Toast.makeText(this,"app被重打包",Toast.LENGTH_SHORT).show(); }
public int getSignature(String packageName) { PackageManager pm = this.getPackageManager(); PackageInfo pi = null; int sig = 0; try { pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); Signature[] s = pi.signatures; sig = s[0].hashCode(); } catch (PackageManager.NameNotFoundException e) { sig = 0; e.printStackTrace(); } return sig; }