Android客户端代码保护技术-完整性校验

标签: android 客户端 代码 | 发表时间:2018-01-08 17:10 | 作者:shuai1234
出处:http://www.iteye.com

  由于Android系统固有的缺陷、Android应用分发渠道管理机制等问题,导致Android客户端程序很容易被反编译篡改/二次打包,经任意签名后可在各个渠道或论坛中发布,这不仅损害了开发者的知识产权,更可能威胁到用户的敏感信息及财产安全,因此客户端程序自身的安全性尤为重要,本文以客户端完整校验为主题,提供几种Android客户端完整性校验的实现思路,供广大开发者参考。

思路1:对classes.dex文件完整性校验

       Android工程代码中的所有java代码经编译和优化最终生成Dalvik虚拟机可执行的DEX文件,DEX文件最终会打包在APK文件中,针对APK代码的篡改攻击就是针对该文件,如通常使用apktool反编译APK文件,修改smali代码。APK包中的DEX文件如下图所示:

       因此,我们可以设计编写校验代码,实现在应用程序启动时计算所程序安装包中的classes.dex文件的哈希值(可通过CRC32、MD5等摘要算法计算得到),然后与预先计算的dex文件的哈希值(该值可存储在代码或配置文件中、也可与服务器通信交互获取)进行比较,以此验证代码文件是否被篡改。

       通过检查classes.dex文件的CRC32摘要值来判断文件是否被篡改的java实现代码如下所示:

[java]  view plain  copy
 
  1. /** 
  2.  * 通过检查classes.dex文件的CRC32摘要值来判断文件是否被篡改 
  3.  * 
  4.  * @param orginalCRC 原始classes.dex文件的CRC值 
  5.  */  
  6. public static void apkVerifyWithCRC(Context context, String orginalCRC) {  
  7.     String apkPath = context.getPackageCodePath(); // 获取Apk包存储路径  
  8.     try {  
  9.         ZipFile zipFile = new ZipFile(apkPath);  
  10.         ZipEntry dexEntry = zipFile.getEntry("classes.dex"); // 读取ZIP包中的classes.dex文件  
  11.         String dexCRC = String.valueOf(dexEntry.getCrc()); // 得到classes.dex文件的CRC值  
  12.         if (!dexCRC.equals(orginalCRC)) { // 将得到的CRC值与原始的CRC值进行比较校验  
  13.             Process.killProcess(Process.myPid()); // 验证失败则退出程序  
  14.         }  
  15.     } catch (IOException e) {  
  16.         e.printStackTrace();  
  17.     }  
  18. }  

 

思路2:对apk包做完整性校验

       如果对apk包进行篡改,必会影响apk包的完整性校验值,因此根据思路1,我们也可以对整个apk包做哈希校验。

       通过检查apk包的MD5摘要值来判断代码文件是否被篡改的java实现代码如下图所示:

[java]  view plain  copy
 
  1. /** 
  2.  * 通过检查apk包的MD5摘要值来判断代码文件是否被篡改 
  3.  * 
  4.  * @param orginalMD5 原始Apk包的MD5值 
  5.  */  
  6. public static void apkVerifyWithMD5(Context context, String orginalMD5) {  
  7.     String apkPath = context.getPackageCodePath(); // 获取Apk包存储路径  
  8.     try {  
  9.         MessageDigest dexDigest = MessageDigest.getInstance("MD5");  
  10.         byte[] bytes = new byte[1024];  
  11.         int byteCount;  
  12.         FileInputStream fis = new FileInputStream(new File(apkPath)); // 读取apk文件  
  13.         while ((byteCount = fis.read(bytes)) != -1) {  
  14.             dexDigest.update(bytes, 0, byteCount);  
  15.         }  
  16.         BigInteger bigInteger = new BigInteger(1, dexDigest.digest()); // 计算apk文件的哈希值  
  17.         String sha = bigInteger.toString(16);  
  18.         fis.close();  
  19.         if (!sha.equals(orginalMD5)) { // 将得到的哈希值与原始的哈希值进行比较校验  
  20.             Process.killProcess(Process.myPid()); // 验证失败则退出程序  
  21.         }  
  22.     } catch (NoSuchAlgorithmException e) {  
  23.         e.printStackTrace();  
  24.     } catch (FileNotFoundException e) {  
  25.         e.printStackTrace();  
  26.     } catch (IOException e) {  
  27.         e.printStackTrace();  
  28.     }  
  29. }  

 

思路3:对签名文件中classes.dex哈希值的校验

        Android工程代码经编译打包生成apk包后,开发者需要对其签名才能在安卓市场上发布供用户下载和安装。对apk包签名后,会在原apk包结构基础上加入META-INF文件目录。签名后的apk包文件目录如下图所示:

       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实现代码如下所示:

[java]  view plain  copy
 
  1. /** 
  2.  * 通过检查签名文件classes.dex文件的哈希值来判断代码文件是否被篡改 
  3.  * 
  4.  * @param orginalSHA 原始Apk包的SHA-1值 
  5.  */  
  6. public static void apkVerifyWithSHA(Context context, String orginalSHA) {  
  7.     String apkPath = context.getPackageCodePath(); // 获取Apk包存储路径  
  8.     try {  
  9.         MessageDigest dexDigest = MessageDigest.getInstance("SHA-1");  
  10.         byte[] bytes = new byte[1024];  
  11.         int byteCount;  
  12.         FileInputStream fis = new FileInputStream(new File(apkPath)); // 读取apk文件  
  13.         while ((byteCount = fis.read(bytes)) != -1) {  
  14.             dexDigest.update(bytes, 0, byteCount);  
  15.         }  
  16.         BigInteger bigInteger = new BigInteger(1, dexDigest.digest()); // 计算apk文件的哈希值  
  17.         String sha = bigInteger.toString(16);  
  18.         fis.close();  
  19.         if (!sha.equals(orginalSHA)) { // 将得到的哈希值与原始的哈希值进行比较校验  
  20.             Process.killProcess(Process.myPid()); // 验证失败则退出程序  
  21.         }  
  22.     } catch (NoSuchAlgorithmException e) {  
  23.         e.printStackTrace();  
  24.     } catch (FileNotFoundException e) {  
  25.         e.printStackTrace();  
  26.     } catch (IOException e) {  
  27.         e.printStackTrace();  
  28.     }  
  29. }  

 

       以上三种完整性校验实现思路的实现代码样例采用Java语言实现,从安全角度来讲,很容易通过反编译篡改patch掉,因此在实现完整性校验代码时还需参考以下几点建议:

       1.预先计算的dex文件的哈希值、签名文件的classes.dex的SHA-1哈希值,应避免直接明文硬编码存储在代码或配置文件中,可对其采用非对称加密存储,或采取与服务端通信的方式获取。

       2.由于dex文件很容易通过dex2jar、apktool反编译后逆向分析和破解,因此该完整性校验功能可进一步使用C/C++代码进行编写实现。另外,进一步提高安全性,还可通过源码混淆,如:开源的obfuscator-llvm项目,或对.so动态库加壳,增加逆向分析和破解的难度。



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [android 客户端 代码] 推荐:

Android客户端代码保护技术-完整性校验

- - 移动开发 - ITeye博客
  由于Android系统固有的缺陷、Android应用分发渠道管理机制等问题,导致Android客户端程序很容易被反编译篡改/二次打包,经任意签名后可在各个渠道或论坛中发布,这不仅损害了开发者的知识产权,更可能威胁到用户的敏感信息及财产安全,因此客户端程序自身的安全性尤为重要,本文以客户端完整校验为主题,提供几种Android客户端完整性校验的实现思路,供广大开发者参考.

免费Android客户端静态代码安全分析工具—Dexter

- - FreebuF.COM
Bluebox Labs刚刚发布了一款免费工具,可以帮助信息安全工作者分析Android移动客户端的恶意程序以及漏洞,这款工具的名字叫Dexter. Dexter将人工和自动静态分析功能合二为一,因此分析效果更佳. 因为一般程序的源代码并未提供,Dexter在第三方软件分析和逆向分析中很有帮助.

优秀的Android Twitter客户端

- 馒头 - Solidot
Irene Janes 写道 "无论用任何标准衡量,社交网络正日益成为生活的一部分. Twitter是最流行的社交网络服务之一. 12个月前,它每天约发送6500万条消息;今天,这一数字已经上升到每天超过2亿条,相当于2亿注册用户每人每天发送一条. Twitter从根本上改变了许多人的交流方式.

谈Android手机客户端的适配测试

- - Taobao QA Team
一、           Android 客户端为什么要进行适配测试. 在正式开始android客户端的适配测试点整理之前,先给大家看几个数据. 下面是随机抽取某个android客户端在2月份的用户使用情况. 【Android不同系统版本下的分布情况】. 【客户端在不同手机分辨率下被使用的分布情况】.

新浪微博Android客户端SSO授权认证缺陷

- - BlogJava-首页技术区
转载请注明出处:  http://www.blogjava.net/zh-weir/archive/2013/09/08/403829.html. 新浪微博Android客户端SSO授权认证缺陷. 从最近几年开始,做平台的公司都流行起Open API. 这是一个非常好的理念,也受到广大开发者的欢迎.

朋游风景网推出iOS、Android 客户端,瞄准智能旅游市场

- Draven - 36氪
以前外出旅行,跟团的话,总是觉着被牵着走特别不爽;自己玩又不知道按照什么路线,又不知道各个景点背后有什么故事. 这时候就会想,有没有一个手机App,去一个景点时,它可以为你自动规划参观路线,同时还为你介绍每个景点的相关信息呢. 广州创业公司朋游风景网 就打算解决这个问题. 朋游风景于8月1日正式上线了其网站,并同期发布了iOS 应用、Android 应用.

光学识别信用卡阅读器Card.io终于发布Android版客户端

- Ying-An - 36氪
移动支付公司Card.io今天终于面向Android开发者推出了光学字符识别信用卡阅读器,结束了该应用一直没有Android客户端的历史. Card.io是一家为智能手机提供基于软件的信用卡支付解决方案的公司,该公司的技术可以让用户拿着智能手机对信用卡拍照,然后进行光学识别,进而完成支付. 一般情况下,用户在智能手机上完成信用卡支付需要很多步骤,并且在手动输入卡号时经常出错,甚至因此放弃手机支付.

腾讯应用中心Android客户端上线 设安全认证

- Tony - cnBeta.COM
Android腾讯应用中心客户端昨日全新上线,其前身是“QQ手机软件管理”. 腾讯应用中心Android客户端全新的UI和架构,显示出腾讯应用中心的社区化和开放平台理念,同时腾讯应用中心每款应用都经专业的QQ手机管家认证,用户下载更安心.

android客户端接入新浪、腾讯微博以及人人网

- - CSDN博客移动开发推荐文章
本文原创 http://blog.csdn.net/yanbin1079415046,转载请注明出处.   从事android工作也有段时间了,碍于肚子里料不多,一直也没写过什么东西. 最近刚好项目中要接入新浪微博,就顺便研究了一下android客户端接入腾讯微博和人人网. 由于是第一次写东西,加上本人小菜鸟一个,请高手勿喷,觉得文章没用的飘过,当然啦,觉得还有点用的就看看吧.

基于XMPP实现的Openfire的配置安装+Android客户端的实现

- - ITeye博客
最近在整理一些这方面的资料,闲话少说,咱还是直奔主题吧 :). 一、基于xmpp实现的openfire的配置安装. 1、 下载最新的openfire安装文件. 在这里面openfire是服务器,下面还有一个spark,这个是一个XMPP协议通信聊天的CS的IM软件,它可以通过openfire进行聊天对话.