标签:
玩过Android开发的人应该都知道,Android apk的保护是非常差的,辛辛苦苦写的代码,被别人翻个底朝天倒不说,被人改了代码移头换面再拿出来害人就不能忍了。
除自带的SDK外,Android的分析和修改工具还有很多,Android下的静态分析工具,最常见的是利用ApkTool(见http://code.google.com/p/android-apktool/)反编译apk,将dalvik字节码生成smali汇编,通过对smali汇编的阅读分析,结合实际软件运行时行为,搜索定位关键信息点,再针对性的修改汇编指令,再通过ApkTool重新编译打包签名生成apk来运行,以达到破解的目的。除ApkTool之外,还有一些工具,如IDA pro、dex2jar结合jd-gui以及androguard等等。
当然,应对反编译apk来破解的方式有多种,比如加上混淆,使用签名校验等等,这里说的一种方式,并非常规方式,但若实现好之后,对用户想要通过常规的静态分析代码的方式来破解apk,不仅白费力气,还很容易被带进沟里去。
本文的方法并非独创,在实际工作中的需要对dalvik指令分析统计时,意外搜索到bluebox的这篇文章:http://bluebox.com/labs/android-security-challenge/ 。可惜的是,他们没有提供源代码,就只能按照思路,自己实现了。实现的源代码在https://github.com/freshui/dexBytecodeTamper,有兴趣的同学可以对照本文后,下载下来瞅瞅,这里先说说原理吧(只简单挑一些说,详细请查阅android源码文档)。
Dex文件的格式,在Android原生代码中,由一个DexFile的结构体描述:
以上dexFile结构描述的,是编译后直接生成的是dex文件的格式,在apk文件(就是一个zip文件,可用winrar或其他解压缩工具直接打开)中,dex文件是classes.dex。
Dalvik格式的详细情况,可以参看2008年的Google IO: Dalvik VM Intenals,说的很清楚。整体结构相比ELF格式来说,要简单一些,如下图(拷贝自Dalvik VM Internals 的ppt),通常由7个部分组成,header记录了dalvik文件的一些信息,并标记其余几个部分在文件中的位置,而其他几个部分的XXX_ids或XXX_defs,实际上都只是索引,索引的内容是存在data部分的。
dalvik与传统的class文件相比的一个优势,就是将所有的常量字符串集统一管理起来了,这样就可以减少冗余(实际我感觉,也压榨不了多少,现在都是几个G的内存了,没多少意义了),最终的dex文件size也能变小一些。在上图的几大部分中,string_ids和elf的string table有点类似,存的是每个字符串的offset的位置,其他几个部分若要引用字符串,则直接使用string_ids的下标即可,方式同elf格式的索引。索引关系可见下图:
详细的dex文件介绍就不说了,有兴趣的可以直接翻看android的源码,虽然表面看起来蛮吓人的,但其结构及复杂度不及elf,解析起来比ELF更是简单。
odex文件格式
apk安装时,会通过dexopt来验证并生产优化后的dalvik字节码odex文件。过程是将apk中的classes.dex解压后,用dexopt处理,并保存到/data/dalvik-cache/data@app@<package-name>-X.apk@classes.dex。odex文件会解析相关依赖,将加载所需的依赖库列表附加在文件中,同时会修改部分指令以加快解析和处理的速度。
odex文件可以看做是dex文件的一个超集,其结构如下:
dex文件作为优化后的odex的一部分,在本文的分析中,只需要从odex中找出dexFile的部分即可。
我们的目标是自修改字节码。要实现自修改字节码,就需要先定位到想要修改得代码的位置,这就需要先解析dex文件。dex文件我们放在native代码中解析处理,naitive代码的分析破解,要比dalvik复杂多了。这里对dex文件解析的实现,可以参考dalvik源码,其中函数可以直接拿过来使用,详情可参考其dexDump模块,代码细节不想说,可参看dalvik源码或示例。
要修改自身dalvik指令之前,我们需要查找到要修改的odex文件的map地址,然后通过mprotect调用,增加可写属性以便修改。代码如下:
首先要找到odex文件在本进程中map的位置,注意android对dalvik-cache目录下的odex文件名的命名方式:
找到odex文件后,还需要知道改odex文件在其中的size,以便mprotect修改属性:
odex文件找到后,我们需要确定dex文件在其中的偏移,以便分析dex文件格式,查找Dex文件偏移位置:
找到dex所在的偏移,就可以解析dex文件头,定位dex文件各部分所在的区域,以供下一步解析使用:
以上,已经基本确定了dex文件的信息,接下来要修改dalvik字节码了。
修改字节码之前,还需要定位到需要修改的byte Code的存放位置。目前能做到的修改仅针对dalvik指令部分,其他部分的修改未做尝试。dalvik指令的数据结构为:
这里的insns数组存放的就是dalvik的字节码。我们只要定位到相关类方法的DexCode数据段,即可通过修改insns数组,篡改指令。
定位字节码之前,需要定位到DexMethod的位置(因为只有method才有指令),在DexMehod结构中,有成员指向DexCode数据结构的偏移:
这里,codeOff即为要找的DexCode所在的偏移位置。
为找到DexMethod,我们需要找到此Method的确定信息:其所属的类,函数名,参数和返回值信息等。知道这些信息后,可以通过Dex文件结构中的class_defs和method_ids表查找到DexMethod结构,并最终返回DexCode。
相关代码封装在一个函数中实现:
找到DexCode后,即可修改指令了:
修改指令的方式:
1. 如上文描述,需要先查找到DexCode的偏移位置
2. 需要将odex文件map的内存位置,用mprotect设置内存访问权限,允许修改。
3. 修改DexCode中,insns所指向的dalvik字节码
4. 将odex所map的内存位置的访问权限改回,当然不做也没关系。
细节不详述,有兴趣可以看看示例代码。
这里需要注意一点:dalvik指令也不是可以任意修改,需要注意size、寄存器及索引不能有异常,一般只能针对每个dex文件都要重新编辑。另外一个重要点就是索引问题,这个也不展开说了。
转自:http://blog.csdn.net/freshui/article/details/13620647#comments
apk自我保护的一种实现方式——运行时自篡改dalvik指令【转载】
标签:
原文地址:http://www.cnblogs.com/chyl411/p/4314012.html