【移动安全基础篇】——32、Android动态代码自修改实现

一、 法 方法 1
1. Jni Bridge
Jni 提供了让我们在 C++代码层中直接操作 Dalvik(java)数据的接口。我们可以在 jni 中直接操作相关的数据,修改 Android 中的代码。
Android 源码中的实现:dalvik/vm/jni.cpp

2. Object  结构体
Android 源码位置:dalvik/vm/oo/ObjectAndroid 运行时,解析 Dex 文件,并生成相关的结构体:DvmDex。该 结 构 体 中 存 储 了 各 种 字 符 串 、 类 、 方 法 等 信 息 。 加 载 的 时 候 调 用dvmDexFileOpenPartial(/dalvik/vm/DvmDex.cpp)对 Dex 文件进行解析,并转化为可执行的结构体。这也是为什么这个函数可以作为脱壳用的函数的原因之一,以前的爱加密可以直接通过钩这个函数进行脱壳。

其中,Method 结构体则是根据 DexMethod 生成的执行方法类。Dalvik 执行代码时,都是从 Method 中取出代码来执行的。因此可以直接通过操作 Method 结构体来修改执行的代码。
3. Android  源码导出
因为安全性,jni 中的结构体是部分导出的,所以需要补全相关的结构体才能操作其数据。

定义了两个返回数值的函数,并且在按钮点击时调用函数 ret1()

编译运行后取出 classes.dex 文件进行查看,得到两个函数的 isns 结构

通过反射来获取函数调用

需要导入部分源码才能使 Method*被识别

最后调用函数被更改成功
二、 法 方法 2
1. DexFile  修改
根据示例一,可以看到直接修改内存中的 DexFile 文件数据可以达到修改代码的效果。具体为:DexFile -> DexClassDef -> DexClassData -> DexMethod -> DexCode ->insns

2.  内存中 DexFile 

遍历 Map 的函数

内存 Map 已经被打印出,找到 dex 的位置

解析出 Dex 文件

将 dex 的内存访问属性从只读修改为可写

cppFlag 添加编译选项

编译报错,数据太大,需要进行修改

最后修改成功
3.  修改方法定位
dexClassDef 遍历,获取 MethodId,对比 MethodName 与 proto,获取目标 Method,然后对相应的 DexCode 进行修改。由于 Dex 加载到内存中是只有只读权限的,所以需要修改内存页的权限才能正常地修改 DexCode 数据。具体解析 Dex 结构的方法可以参考:https://github.com/F8LEFT/FDA

总会有不期而遇的温暖. 和生生不息的希望。
原文地址:https://www.cnblogs.com/devi1/p/13486414.html