【专业领域】android apk 防止反编译技术第五篇-完整性校验

关于防止android apk被反编译的技术我们前面已经讲了四种。他们分别是加壳技术、运行时修改字节码、伪加密、对抗JD-GUI,如果有不明白的可以查看我的博客的前四篇中关于这四种技术的介绍。接下来我们接着介绍另一种防止apk反编译的技术-完整性校验。

一、完整性校验原理

所谓完整性校验就是我们用各种算法来计算一个文件的完整性,防止这个文件被修改。其中常用的方法就是计算一个文件的CRC32的值或者计算一个文件的哈希值。我们在防止apk被反编译的方法中也可以采用这种方法。我们知道apk生成的classes.dex主要由java文件生成的,它是整个apk的逻辑实现。所以我们可以对classes.dex文件进行完整性校验,来保证整个程序的逻辑不被修改。如果我们想要保证整个apk文件的完整性,也可以对整个apk文件进行完整性校验。下面我们分别来实现对classes.dex文件和apk文件的完整性校验。

二、用crc32对classes.dex文件的完整性进行校验

(1)可以打印出来我们的apk生的classes.dex文件的crc32的值,代码如下:

public class MainActivity extendsActivity {

@Override

protected void onCreate(BundlesavedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

String apkPath = getPackageCodePath();

Long dexCrc = Long.parseLong(getString(R.string.classesdex_crc));

try

{

ZipFile zipfile = new ZipFile(apkPath);

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

Log.i("verification","classes.dexcrc="+dexentry.getCrc());

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

Log.i("verification","Dexhas been modified!");

}else{

Log.i("verification","Dex hasn't been modified!");

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

注意:R.string.classesdex_crc的值现在可以是个随机数。

(2)运行程序打印结果,我的apk程序的classes.dex的crc32的值为713769644

(3)将上面程序的classes.dex文件的crc32的值,保存在资源文件字符串中classesdex_crc中(当然也可以保存在服务器上,然后通过网络获取校验),然后再运行上面的apk程序,打印如下:

Dex hasn't beenmodified!

(4)这时我们在上面的代码中随便加一行或者一个空格,然后重新编译运行会看到我们的程序的crc32的值改变了。程序打印如下:

Dex has beenmodified!

三、用哈希值对整个apk完整性进行校验

由于我们要对整个apk的完整性进行校验,所以我们的算出哈希值就不能存在资源文件中了因为apk中任何的改动都会引起最终apk生成的哈希值的不同。

(1)首先实现apk中计算自身哈希值的代码,如下:

public class MainActivity extendsActivity {

@Override

protectedvoid onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

String apkPath = getPackageCodePath();

MessageDigest msgDigest = null;

try {

msgDigest = MessageDigest.getInstance("SHA-1");

byte[] bytes = new byte[1024];

int byteCount;

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

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

{

msgDigest.update(bytes, 0, byteCount);

}

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

String sha = bi.toString(16);

fis.close();

//这里添加从服务器中获取哈希值然后进行对比校验

} catch (Exception e) {

e.printStackTrace();

}

}

}

(2)用linux下的sha1sum命令计算我们的apk的哈希值,命令如下:

sha1sum verification.apk

(3)将(2)中生成的哈希值存到服务器上,然后在我们的代码中从服务器获取进行完整性比较。

上面我们用计算crc32和哈希值的方法分别对classes.dex文件和整个apk完整性进行了校验,当然两个校验方法也可以互换使用。根据上面的讲述相信大家对校验文件完整性的方法有了一定的了解,下一篇我们将讲解另一种android apk防止反编译技术,期待大家的捧场。

原文发布于微信公众号 - 程序员互动联盟(coder_online)

原文发表时间:2015-04-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏JackieZheng

照虎画猫写自己的Spring

从细节跳出来 看了部分Spring的代码,前面用了四篇内容写了一些读书笔记。 回想起来,论复杂度,Spring够喝上好几壶的。他就像一颗枝繁叶茂的大树,远处看...

1866
来自专栏女程序员的日常

STM8S——Universal asynchronous receiver transmitter (UART)

UART基本介绍: 通用异步收发器UART他的功能非常强大 我们只使用UART的全双工异步通信功能,使用中断接收数据。 UART_RX:串行数据输入。 UART...

2071
来自专栏Netkiller

以太坊智能合约开发入门

摘要 本文采用碎片化写作,原文会不定期更新,请尽量阅读原文。 http://www.netkiller.cn/journal/ethereum.solidity...

6029
来自专栏郭霖

Android任务和返回栈完全解析,细数那些你所不知道的细节

任务和返回栈 一个应用程序当中通常都会包含很多个Activity,每个Activity都应该设计成为一个具有特定的功能,并且可以让用户进行操作的组件。另外,Ac...

2037
来自专栏Charlie's Road

<Solidity学习系列四>使用编译器

Solidity存储库的一个构建目标是solc,solidity命令行编译器。 使用solc --help为您提供所有选项的解释。 编译器可以生成各种输出,范围...

672
来自专栏架构之路

谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署

943
来自专栏JackieZheng

Hadoop阅读笔记(二)——利用MapReduce求平均数和去重

前言:圣诞节来了,我怎么能虚度光阴呢?!依稀记得,那一年,大家互赠贺卡,短短几行字,字字融化在心里;那一年,大家在水果市场,寻找那些最能代表自己心意的苹果香蕉梨...

2516
来自专栏FreeBuf

对登录中账号密码进行加密之后再传输的爆破的思路和方式

一. 概述 渗透测试过程中遇到web登录的时候,现在很多场景账号密码都是经过js加密之后再请求发送(通过抓包可以看到加密信息)如图一burp抓到的包,reque...

2229
来自专栏点滴积累

geotrellis使用(三十三)关于Geotrellis读取Geotiff的两个细节

前言 在上两篇文章中我介绍了如何直接将Geotiff(一个或者多个)发布为TMS服务。这中间其实我遇到了一个问题,并且这个问题伴随Geotrellis的几乎所有...

37811
来自专栏增长技术

Android Renderscript(一)

渲染脚本(Renderscript)提供用C语言(C99标准)编写的原生级高性能的计算API。Renderscript 让你的应用程序有能力跨越所有可用的处理器...

732

扫码关注云+社区