赞
踩
混淆
因为开启混淆会使编译时间变长,所以debug模式下不开启。我们需要做的是:
1.将release下minifyEnabled
的值改为true
,打开混淆;
2.buildConfigField
不显示log日志
为什么要混淆:
- 优化java的字节码
- 减小apk文件的大小,在混淆过程中会删除未使用过的类和成员
- 代码安全,使类、函数、变量名随机变成无意义的代号形如:a,b,c...之类。防止app被反编译之后能够很容易的看懂代码
APP需要保留的公共部分(通用)
1. 判断程序是否运行在模拟器上
boolean isRunningInEmualtor() { boolean qemuKernel = false; Process process = null; DataOutputStream os = null; try{ process = Runtime.getRuntime().exec("getprop ro.kernel.qemu"); os = new DataOutputStream(process.getOutputStream()); BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(),"GBK")); os.writeBytes("exit\n"); os.flush(); process.waitFor(); // getprop ro.kernel.qemu == 1 在模拟器 // getprop ro.product.model == "sdk" 在模拟器 // getprop ro.build.tags == "test-keys" 在模拟器 qemuKernel = (Integer.valueOf(in.readLine()) == 1); Log.d("com.droider.checkqemu", "检测到模拟器:" + qemuKernel); } catch (Exception e){ qemuKernel = false; Log.d("com.droider.checkqemu", "run failed" + e.getMessage()); } finally { try{ if (os != null) { os.close(); } process.destroy(); } catch (Exception e) { } Log.d("com.droider.checkqemu", "run finally"); } return qemuKernel; }
2. 检测keystore签名,再与之前得做比较
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 (Exception e1) { sig = 0; e1.printStackTrace(); } return sig; }
3. 检测包名,版本名和版本号,然后做判断:
private String getAppInfo() { try { String pkName = this.getPackageName(); String versionName = this.getPackageManager().getPackageInfo( pkName, 0).versionName; int versionCode = this.getPackageManager() .getPackageInfo(pkName, 0).versionCode; return pkName + " " + versionName + " " + versionCode; } catch (Exception e) { } return null; }
4.完整性校验
Android工程代码经编译打包生成apk包后,开发者需要对其签名才能在安卓市场上发布供用户下载和安装。对apk包签名后,会在原apk包结构基础上加入META-INF文件目录。
META-INF文件目录下含有三个文件:MANIFEST.MF文件、ANDROIDD.SF文件、ANDROIDD.RSA文件,META_INF目录文件结构如下图所示:
其中,MANIFEST.MF文件描述了在签名时,签名工具对apk包中各个文件摘要计算后的哈希值,并对哈希值做了Base64编码。MANIFEST.MF文件中描述的classes.dex文件的SHA-1哈希值如下图所示:
一旦攻击者对APK中反编译并篡改代码,经二次打包签名后的classes.dex文件的SHA-1必定改变,因此,我们可以将该文件中的classes.dex文件的SHA-1哈希值保存起来作为校验对比值,应用程序启动时读取apk安装包中的MANIFEST.MF文件,解析出classes.dex的SHA-1哈希值,然后与原SHA-1哈希值进行比较,判断此APK包代码文件是否被篡改。
通过检查签名文件classes.dex文件的哈希值来判断代码文件是否被篡改的java实现代码如下所示:
通过检查签名文件classes.dex文件的哈希值来判断代码文件是否被篡改
@param orginalSHA 原始Apk包的SHA-1值
-
-
- public static void apkVerifyWithSHA(Context context, String baseSHA) {
- String apkPath = context.getPackageCodePath(); // 获取Apk包存储路径
- try {
- MessageDigest dexDigest = MessageDigest.getInstance("SHA-1");
- byte[] bytes = new byte[1024];
- int byteCount;
- FileInputStream fis = new FileInputStream(new File(apkPath)); // 读取apk文件
- while ((byteCount = fis.read(bytes)) != -1) {
- dexDigest.update(bytes, 0, byteCount);
- }
- BigInteger bigInteger = new BigInteger(1, dexDigest.digest()); // 计算apk文件的哈希值
- String sha = bigInteger.toString(16);
- fis.close();
- if (!sha.equals(baseSHA)) { // 将得到的哈希值与原始的哈希值进行比较校验
- Process.killProcess(Process.myPid()); // 验证失败则退出程序
- }
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }

5.Android逆向-.so文件动态调试步骤
so库加密的方法
1.是在有源码的基础上进行对特定的section进行加密
2.基于二进制级别的特定函数的加密
参考博客:
https://blog.csdn.net/nicolelili1/article/details/79243744
https://blog.csdn.net/feibabeibei_beibei?t=1
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。