Android程序反破解技术
0x1
对抗反编译可以大概分为以下几点:
1、对抗反编译工具,例如apktool、dex2jar等
2、对抗静态编译,分为代码混淆技术、NDK保护、apk加壳保护。
3、对抗动态调试,分为检测调试器、检测模拟器。
4、防止重编译,分为检查签名,校验保护。
更多相关内容请参考《Android软件安全与逆向分析》。
0x02
对抗反编译工具,例如dex2jar,通常是在分析dex2jar源码后,来找到漏洞,在java源码中加入会触发dex2jar异常的代码,从而使dex2jar不能正常使用。
dex2jar测试版本是0.0.7.8,源码地址 https://github.com/jltxgcy/AntiCrack/tree/master/Antidex2jar。这个工程是通过在java源码中加入下面函数导致dex2jar不能正常使用的。
private int position(int idx) { // bits big-endian in each unit return 1 << (BITS_PER_UNIT - 1 - (idx % BITS_PER_UNIT)); }
0x03
对抗静态编译
1、代码混淆技术请参考 Android 混淆机制。
2、NDK保护,就是把原来在java层实现的逻辑,挪到C/C++层去实现,因为C/C++层代码反编译后生成的arm汇编,更加难以分析。
3、apk加壳保护,请参考 Android中的Apk的加固(加壳)原理解析和实现。
0x04
对抗动态调试
1、检测调试器,我们已经在 Android native反调试方式及使用IDA绕过反调试一文中,详细说明了有几种方式可以用来反调试器。
另外在这里面介绍一个java层的反调试器, https://github.com/jltxgcy/AntiCrack/tree/master/Antidebug/src/com/droider/antidebug。
2、检测模拟器,当我们的程序运行在模拟器中,我们可以推测出我们的程序正在被动态分析,这时我们可以使我们的程序退出。工程地址: https://github.com/jltxgcy/AntiCrack/tree/master/CheckQemu。
检测模拟器的方法有很多,参考 Android安全–检测是否为Android模拟器。
0x05
防止重编译。
1、检测签名
在java层检测签名,工程地址如下: https://github.com/jltxgcy/AntiCrack/tree/master/CheckSignature。核心的代码是:
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; }获取签名后,然后和正确的签名信息对比,如果对比成功,说明签名信息没有被更改。
2、校验保护
重编译Android软件的实质是重新编译classes.dex文件,代码经过重新编译后,生成的classes.dex文件的Hash值已经改变。
工程地址: https://github.com/jltxgcy/AntiCrack/tree/master/CheckCRC。
核心代码如下:
private boolean checkCRC() { boolean beModified = false; long crc = Long.parseLong(getString(R.string.crc)); ZipFile zf; try { zf = new ZipFile(getApplicationContext().getPackageCodePath()); ZipEntry ze = zf.getEntry("classes.dex"); Log.d("com.droider.checkcrc", String.valueOf(ze.getCrc())); if (ze.getCrc() == crc) { beModified = true; } } catch (IOException e) { e.printStackTrace(); beModified = false; } return beModified; }