自篡改Dalvik字节码delta.apk原理

来源:互联网 发布:威锋认证的淘宝店 编辑:程序博客网 时间:2024/04/19 06:00

前段时间翻看看雪旧贴,发现一个很有趣的demo
[翻译]Android安全分析挑战:运行时篡改Dalvik字节码

这是bluebox 在13年发布的一个可以可以在运行时修改自身 dalvik 字节码的 demo。
分析了一下,该demo通过native方法,在运行时修改dalvik在内存映射字节码从而增加静态分析难度。

出去好奇,对其进行逆向分析。
加密
用压缩软件解压发现apk被加密了,尝试使用爆破工具爆破密码,结果提示爆破失败。。。
折腾好久,发现这其实是一个zip伪加密。

在 android 解析apk 时,由于忽略了加密 zip,直接跳过了加密头部的解析,因此通过修改 zip文件头的加密标识,以实现伪加密。这种方法在高版本Android系统已不可使用。
具体解压代码:
https://github.com/adamely/DalvikBytecodeTampering/blob/master/unpack.py

解压完用JEB打开,分析一下具体算法流程:

先是加载了本地native so,执行readmem()函数
native
然后对传入字符串进行操作:转换为Byte型,调用java.lang.String中自己重写的add(String)函数将字符串转换,其和需要等于1704。
这里写图片描述

然后就这么完了??
构造一个字符串试了一下。。。结果发现是错误的。题目说了对Dalvik字节码进行了篡改。
那么坑点应该就在native层。IDA打开分析:
search()

看到search()函数,命名很友好,经过分析可以知道大致思路:

使用findmagic()函数匹配dex文件模数,即寻找其在内存起始地址。找到后,使用getStrIdx()找出字符串 L/java/lang/String在内存中的偏移。同理找出add字符串idx。
然后根据类字符串idx,找到找到方法的idx,最后找到codeItem。根据codeItem我们就可以找到代码相对偏移地址了,接下来就是修改其偏移地址的字节码。
findmagic()函数:
findmagic
传入参数与Dex模数”dex\n035”比较,寻找其内存地址。

get**()函数:这里只介绍getStrIdx(),其余思路类似
这里写图片描述
首先,因为dex文件头到指向字符串索引数的偏移为0x3c,先检查是否为0。
若不为0,则遍历所有字符串,找出传入参数字符串的索引。
这里写图片描述
整理一下其代码思路:
1. 类名—->字符串索引idx—->类型索引TypeIdx—->类的定义元信息ClassDefItem—->类的代码元信息ClassDataItem
2. 方法名—->字符串索引常量池+类的TypeId—->方法Id
3. 方法Id+类代码元信息ClassDataItem—->方法的元信息EncodeMethod—->方法的指令代码结构Code
4. 将已编写好的字节码覆盖原有的字节码memcpy(code_off, &inject, 0xDEu)

下面是分析后的seach()函数代码:
这里写图片描述

也就是说,该native函数的功能就是寻找到也Ljava/lang/String;->add 函数的内存偏移,然后修改其字节码。

总结

本次的逆向其实不难,主要要熟悉Dex文件结构以及文件中各种索引的关系。刚开始不太懂可以借助010Eidt神器来分析。DEX数据结构对应关系主要位于源码\dalvik\libdex\DexClass.h 和 \dalvik\libdex\DexFile.h 中。

另外,对于这个思路只适用与Dalvik虚拟机,也就是Android5.0以下版本。因为新的ART虚拟机dex文件插入odex结构的,不能很好地在内存寻找其偏移。

0 0
原创粉丝点击