Android安全-代码安全3-Dex文件校验

重编译apk其实就是重编译了classes.dex文件,重编译后,生成的classes.dex文件的hash值就改变了,因此我们可以通过检测安装后classes.dex文件的hash值来判断apk是否被重打包过。

  (1)读取应用安装目录下/data/app/xxx.apk中的classes.dex文件并计算其哈希值,将该值与软件发布时的classes.dex哈希值做比较来判断客户端是否被篡改。

  (2)读取应用安装目录下/data/app/xxx.apk中的META-INF目录下的MANIFEST.MF文件,该文件详细记录了apk包中所有文件的哈希值,因此可以读取该文件获取到classes.dex文件对应的哈希值,将该值与软件发布时的classes.dex哈希值做比较就可以判断客户端是否被篡改。

  为了防止被破解,软件发布时的classes.dex哈希值应该存放在服务器端。

  另外由于逆向c/c++代码要比逆向Java代码困难很多,所以关键代码部位应该使用Native C/C++来编写。

  classes.dex 在 Android 系统上基本负责完成所有的逻辑业务,因此很多针对 Android 应用
程序的篡改都是针对 classes.dex 文件的。在 APK 的自我保护上,也可以考虑对 classes.dex
文件进行完整性校验,简单的可以通过 CRC 校验完成,也可以检查 Hash 值。由于只是检查
classes.dex,所以可以将 CRC 值存储在 string 资源文件中,当然也可以放在自己的服务器上,
通过运行时从服务器获取校验值。基本步骤如下:

  • 首先在代码中完成校验值比对的逻辑,此部分代码后续不能再改变,否则 CRC 值
    会发生变化;
  • 从生成的 APK 文件中提取出 classes.dex 文件,计算其 CRC 值,其他 hash 值类似;
  • 将计算出的值放入 strings.xml 文件中。

核心代码如下:

代码:

1. String apkPath = this.getPackageCodePath();

2. Long dexCrc = Long.parseLong(this.getString(R.string.dex_crc));

3. try {

4. ZipFile zipfile = new ZipFile(apkPath);

5. ZipEntry dexentry = zipfile.getEntry("classes.dex");

6. if(dexentry.getCrc() != dexCrc){

7. System.out.println("Dex has been *modified!");

8. }else{

9. System.out.println("Dex hasn‘t been modified!");

10. }

11. } catch (IOException e) {

12. // TODO Auto-generated catch block

13. e.printStackTrace();

14. }

但是上述的保护方式容易被暴力破解, 完整性检查最终还是通过返回 true/false 来控制
后续代码逻辑的走向,如果攻击者直接修改代码逻辑,完整性检查始终返回 true,那这种方
法就无效了,所以类似文件完整性校验需要配合一些其他方法,或者有其他更为巧妙的方式
实现?

APK 完整性校验

虽然 Android 程序的主要逻辑通过 classes.dex 文件执行,但是其他文件也会影响到整个
程序的逻辑走向,以上述 Dex 文件校验为例,如果程序依赖 strings.xml 文件中的某些值,则
修改这些值就会影响程序的运行,所以进一步可以整个 APK 文件进行完整性校验。但是如
果对整个 APK 文件进行完整性校验,由于在开发 Android 应用程序时,无法知道完整 APK 文
件的 Hash 值,所以这个 Hash 值的存储无法像 Dex 完整性校验那样放在 strings.xml 文件中,
所以可以考虑将值放在服务器端。核心代码如下:

代码:

1. MessageDigest msgDigest = null;

2. try {

3. msgDigest = MessageDigest.getInstance("MD5")

4. byte[] bytes = new byte[8192];

5. int byteCount;

6. FileInputStream fis = null;

7. fis = new FileInputStream(new File(apkPath));

8. while ((byteCount = fis.read(bytes)) > 0)

9. msgDigest.update(bytes, 0, byteCount);

10. BigInteger bi = new BigInteger(1, msgDigest.digest());

11. String md5 = bi.toString(16);

12. fis.close();

13. /*

14. 从服务器获取存储的 Hash 值,并进行比较

15. */
  
16. } catch (Exception e) {

17. e.printStackTrace();

18. }转自:http://bbs.pediy.com/showthread.php?t=183116
时间: 2024-08-25 03:59:28

Android安全-代码安全3-Dex文件校验的相关文章

Android 在代码中安装 APK 文件

废话不说,上代码 private void install(String filePath) { Log.i(TAG, "开始执行安装: " + filePath); File apkFile = new File(filePath); Intent intent = new Intent(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if (Build.VERSION.SDK_INT >

在Android java代码中如何改变文件的权限

在LINUX下每个文件都有一个权限的属性 ,那么在Android中怎么用java改变某个文件的权限呢? Android中有两种方法可以改变文件的权限 1. 用openFileOutput方法: FileOutputStream fos; fos = openFileOutput("filename", MODE_WORLD_READABLE);  FileOutputStream android.content.ContextWrapper .openFileOutput(String

利用DexClassLoader动态加载dex文件

Java中也有类加载器ClassLoader,其作用是动态装载Class文件,当我们从网络下载Class文件,或者在编译时不参与而在运行时动态调用时就需要用类加载器.由于Android对class文件进行了重新打包和优化,最终APK文件中包含的是dex文件,加载这种文件就需要用到DexClassLoader. DexClassLoader(dexPath, optimizedDirectory, libraryPath, parent) dexPath:目标类所在的APK或者jar包,/.../

Dex文件方法数超过65536怎么破?

你的应用中的Dex 文件方法数超过了最大值65536的上限,会提示你: UNEXPECTED TOP-LEVEL EXCEPTION:java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536at com.android.dx.merge.DexMerger$6.updateIndex(DexMerger.java:501)at com.android.dx.merge.DexMerger$IdMerger.me

[Android] 配置安卓模拟器,使得dex文件不被优化成odex

最近做一个模块,需要将apk里面加载的dex文件dump出来,所以需要配置让dalvik不要把dex文件优化成odex. 1. 配置build.prop 主要是通过修改文件/system/build.prop里面的配置. (1) dalvik.vm.dexopt-flags 本参数控制Dalvik虚拟机的程序代码校验和优化.可填写的值有m.v和o.m为标准选项,可以是m=y或m=n.若m=y则启用不安全代码的校验和托管代码的优化.兼容性和安全性最高.v为校验选项,可与o并存.可以是v=a或v=n

Dex文件的完整性校验

classes.dex 在 Android 系统上基本负责完成所有的逻辑业务,因此很多针对Android 应用程序的篡改都是针对 classes.dex 文件的.在 APK 的自我保护上,也可以考虑对 classes.dex文件进行完整性校验,简单的可以通过 CRC 校验完成,也可以检查 Hash 值.由于只是检查classes.dex,所以可以将 CRC 值存储在 string 资源文件中,当然也可以放在自己的服务器上, 通过运行时从服务器获取校验值.基本步骤如下: 首先在代码中完成校验值比对

class 文件与dex文件区别 (dvm与jvm区别)及Android DVM介绍

区别一:dvm执行的是.dex格式文件  jvm执行的是.class文件   android程序编译完之后生产.class文件,然后,dex工具会把.class文件处理成.dex文件,然后把资源文件和.dex文件等打包成.apk文件.apk就是android package的意思. jvm执行的是.class文件. 区别二:dvm是基于寄存器的虚拟机  而jvm执行是基于虚拟栈的虚拟机.寄存器存取速度比栈快的多,dvm可以根据硬件实现最大的优化,比较适合移动设备. 区别三:.class文件存在很

解决Android单个dex文件不能超过65535个方法问题

一.找坑:谷歌规定单个dex文件中的方法不能超过65536的限制 我们编写项目过程中在工程的lib文件夹下引用的第三方插件jar包太多或者项目过大,编译运行时就有可能报出com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536错误.看到这个错误说明你的方法加起来已经超过了65536这个数目.但是谷歌规定单个dex文件中的方法不能超过65536的限制. 如下图所示,Android Studio 中的

解决Android单个dex文件不能超过65536个方法问题

当我们的项目代码过大时,编译运行时会报Unable to execute dex: method ID not in[0, 0xffff]: 65536)错误.当出现这个错误时说明你本身自己的工程代码中含有的太多的方法,或者你的工程lib文件夹下引用的第三方插件jar包有太多的方法,这两者的方法加起来已经超过了65536这个数目.而谷歌规定单个dex文件中的方法不能超过65536的限制. 那么这个时候,我们就需要分包处理解决.一般情况下的解决方案就是把整个项目工程包括jar,区分开来分解成两个d