Android应用程序的保护机制
来源:互联网 发布:泉山区淘宝 编辑:程序博客网 时间:2024/05/21 14:57
大家都知道Android的APK是非常容易被破解的,目前市面上有太多的工具可以去反编译Apk,添加自己的代码,然后重新打包后发布到应用市场上。
因为Android应用市场五花八门,没有统一的监管机制,光靠应用市场去保护原创应用是完全行不通的,这就对我们的应用APK提出了较高的安全性要求。
当然破解和防止破解永远都是相对立的,双方技术都在不断的成长,所以我们不能完全杜绝破解,但是能在一定程度上避免破解,也就达到我们的目的了。
本文主要从以下几个方面简单介绍下Android应用程序的保护机制。
一、防止反编译
主要是保护DEX、RES、SO库等文件。
目前市面上也有第三方公司提供了Apk加固技术,比如360加固。经过加固后的APK能在一定程度上加大被反编译的难度。
二、防止二次打包
首先,我们需要阻止别的程序员反编译,动态调试我的应用。换句话说,就是需要阻止黑客程序员安装我们的应用到模拟器上。
其次,检测应用程序的完整性,我们可以用jni技术校验应用程序的完整性,也可以利用数字签名的方式来检测应用程序的完整性。1、校验包名
判断当前应用的包名是否和官方的应用包名一致。
2、检验签名
我们知道当一个apk文件被反编译破解、修改完代码逻辑之后,要使用jarsigner工具来重新给apk签名,才能运行修改后的apk文件。一个应用程序的签名,
是识别一个开发者的唯一标识,如果一个应用程序被别人反编译,那么这个应用程序的签名肯定会改变。当发现程序的签名改变时,我们就强制退出APP
3、校验classes.dex
4、校验整个apk的完整性
完整代码如下
public class ApkDefender { /** * 检查APP的合法性 * @param ctx * @return false:APP被修改 */ public static boolean checkInvalidate(Context ctx) { //一、判断线上版本是否运行在模拟器上 if (isEmulator()) { return false; } //二、应用完整性校验(建议放在服务器端校验) //1、包名校验 if (!"com.terry.securitydefender".equals(ctx.getPackageName())) { return false; } //2、检测签名(最好放在服务器端校验) String signature = getSignature(ctx); if("8219089110d0c8c1972cd7e34e96a027".equals(signature)){ return false; } //3、校验classes.dex(每次发版,classes.dex的Crc都不一样,因此最好放到服务器端校验) long dexCrc = getDexCrc(ctx); if(dexCrc>0&&dexCrc!=4156059761L){ return false; } /** 4、校验整个apk是否被修改(每次发版,APK的SHA1值都不一样,因此最好放到服务器端校验) */ String sha1 = getSha1(ctx); if(!TextUtils.isEmpty(sha1)&&!"bfa2cb2d9160806efaea6adb505e379ac1057a49".equals(sha1)){ return false; } return true; } /** * 判断应用程序是否运行在模拟器上 * @return */ private static boolean isEmulator() { //只要是在模拟器中,不管是什么版本的模拟器,在它的MODEL信息里就会带有关键字参数sdk if (Build.MODEL.contains("sdk") || Build.MODEL.contains(Build.VERSION.SDK)) { return true; } else { return false; } } /** * 获得应用程序的数字签名 * @return */ private static String getSignature(Context ctx) { try { PackageManager pm = ctx.getPackageManager(); // 得到当前应用程序的签名 PackageInfo info = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_SIGNATURES); String signature = info.signatures[0].toCharsString();//原始md5值,比较长 signature= getMD5(signature); return signature; } catch (Exception e) { e.printStackTrace(); return null; } } /** * 获取classes.dex的Crc值,判断classes.dex是否被修改 * @param ctx * @return */ private static long getDexCrc(Context ctx) { try { String apkPath = getApkPath(ctx); if(TextUtils.isEmpty(apkPath))return 0; ZipFile zipfile = new ZipFile(apkPath); ZipEntry dexentry = zipfile.getEntry("classes.dex"); return dexentry.getCrc(); } catch (Exception e) { e.printStackTrace(); } return 0; } /** * 获取Apk的SHA1值 * @return */ private static String getSha1(Context ctx) { String apkPath = getApkPath(ctx); if(TextUtils.isEmpty(apkPath))return null; FileInputStream fis = null; try { MessageDigest msgDigest = MessageDigest.getInstance("SHA-1"); byte[] bytes = new byte[1024]; int byteCount; fis = new FileInputStream(new File(apkPath)); while ((byteCount = fis.read(bytes)) > 0) { msgDigest.update(bytes, 0, byteCount); } byte[] digest = msgDigest.digest(); String sha = HEX.byteToString(digest); return sha; } catch (Exception e) { e.printStackTrace(); } finally { if (null != fis) try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } /** * 获取apk的安装路径 * @param context * @return */ private static String getApkPath(Context context) { try { PackageManager pm = context.getPackageManager(); PackageInfo pkgInfo = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES); ApplicationInfo appInfo = pkgInfo.applicationInfo; return appInfo.sourceDir; } catch (Exception e) { e.printStackTrace(); } return null; }//---------------------------------------------- public static String getMD5(String str) {return getMD5(str.getBytes());}public static String getMD5(byte[] toencode) {try {MessageDigest md5 = MessageDigest.getInstance("MD5");md5.reset();md5.update(toencode);return HEX.byteToString(md5.digest());} catch (NoSuchAlgorithmException e) {}return "";}public static String byteToString(byte[] b) {char[] newChar = new char[b.length * 2];for (int i = 0; i < b.length; i++) {newChar[2 * i] = hex[(b[i] & 0xf0) >> 4];newChar[2 * i + 1] = hex[b[i] & 0xf];}return new String(newChar);}private static final char[] hex = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };}
这样能在一定程度上加大二次打包的难度。因为这些都是代码编写的,破解者只要找到对应代码修改后,还是能二次打包。
三、代码安全
可以通过一些自动化检测平台来检测我们的应用是否存在漏洞,然后针对性的加强安全性。
腾讯的金刚审计系统 http://service.security.tencent.com/kingkong
360的捉虫猎手 http://appscan.360.cn/
阿里巴巴的聚安全 http://jaq.alibaba.com/gc/appsec/index.htm
百度的移动云测试中心 http://mtc.baidu.com/
梆梆加固测试平台 http://dev.bangcle.com/apps/index
参考:
http://www.freebuf.com/articles/terminal/102396.html
http://www.droidsec.cn/ 安卓安全中文站
http://blog.nsfocus.net/mobile-app-security-security-test/移动app检测要点
http://zbc.baijia.baidu.com/article/365622 10大移动安全威胁
- Android应用程序的保护机制
- Android:保护自己开发的Android应用程序
- linux应用程序使用到的保护机制 semaphore和pthread_mutex
- Android应用程序的权限机制
- Android受限广播保护机制
- SEAndroid安全机制对Android属性访问的保护分析
- SEAndroid安全机制对Android属性访问的保护分析
- SEAndroid安全机制对Android属性访问的保护分析
- SEAndroid安全机制对Android属性访问的保护分析
- Android中DRM版权保护机制的研究
- SEAndroid安全机制对Android属性访问的保护分析
- SEAndroid安全机制对Android属性访问的保护分析
- shiro保护你的应用程序
- android应用程序的签名(Signature) 签名机制
- Android应用程序间的内容分享机制
- Android应用程序的消息处理机制
- Android应用程序签名机制
- [Rx86OS-XX] x86保护操作系机制 (异常处理) 保护应用程序机制 库
- ibatis调用oracle存储过程,返回游标集合
- Android 异步消息处理机制
- StringBuffer的用法
- iOS滚动Label滚动button--- VXXTextScrollView
- 代理模式---有事找助理
- Android应用程序的保护机制
- RxJava—Schedule(调度器)
- eclipse安装spring tool suite插件
- css特效复选按钮
- 洪荒之父洪君彦个人资料
- 初识PHP(2)
- Ext.state.Manager.setProvider(new Ext.state.CookieProvider())
- Beautiful Soup 4.2.0 文档
- TCL脚本语言基础介绍