小研究 - Android 字节码动态分析分布式框架(四)

安卓平台是个多进程同时运行的系统,它还缺少合适的动态分析接口。因此,在安卓平台上进行全面的动态分析具有高难度和挑战性。已有的研究大多是针对一些安全问题的分析方法或者框架,无法为实现更加灵活、通用的动态分析工具的开发提供支持。此外,很多研究只是针对单进程的分析,在安卓平台多个应用进程协作完成事务的情境下,则无法进行很好的分析。

目录

4  系统实现

4.1 安卓源代码的修改

 4.2 安卓系统 ACS 通信服务

4.2.1 初始化功能

4.2.2 注入服务

4.2.3 事件接受和转发

 4.3 Dalvik 虚拟机的扩展

4.3.1 ShadowVM 支持

4.3.2 虚拟机事件

 4.4 Binder 的扩展


4  系统实现

本章将会详细介绍本文的动态分析框架的各个模块是如何实现的,包括新增的安卓系统 ACS 通信服务、Dalvik 虚拟机的扩展、系统 Binder 库的扩展、以及远程注入和分析服务器的实现。首先,第一部分会先介绍实现这些系统需要涉及的Android 源代码目录,介绍它们原先的作用以及进行了哪些修改;接着第二部分介绍本文在 Android 系统中实现的 ACS 通信服务模块,讲述了如何高效的进行Android 内外部通信;然后在第三部分,通过介绍 DVM 部分的实现,讲述了虚拟机事件的产生以及如何处理系统库共享带来的弊端;在第四部分,介绍了如何扩展 Binder 的中间层以及内核部分,以提供分析需要的 IPC Binder 事件;最后还简单介绍了 Android 系统外对原有ShadowVM 的改造。

4.1 安卓源代码的修改

在介绍这些模块的实现之前,有必要介绍一下安卓源代码的组织结构。安卓源代码是由 repo 工具管理的许多的 git 项目仓库组成的。本文是基于 Android 开源项目的 4.1.1_r6 版本实现的。

表 4-1 列出 Android 源代码根目录下的主要的目录,并依次简介了本文实现需要修改的部分:Dalvik 文件夹含有所有 DVM 实现相关的代码,通过修改 DVM,提供了框架需要的虚拟机事件、注入事件等扩展;而 external 目录则放了 ACS 服务的实现,并编译成动态库为 DVM 提供支持;为了支持 Binder 事件,除了需要修改 frameworks/native/binder 意外,还需要修改内核 kernel 目录,为此需要修改涉及内核的 bionic 目录里的 binder.h 头文件。

 4.2 安卓系统 ACS 通信服务

为了能够在系统开始的时候就提供服务,本文通过修改 init.rc 文件,设置了 ACService 的主程序开机自动启动,并向 Service Manager 注册该服务。

ACService 主要承担的职责分为如下几个部分:

1)初始化系统的必要配置。为了能够让系统库在不同的进程中得到不同方式的处理,以减少注入系统库带来的污染,系统允许用户在外部系统分析服务器提供配置。配置中会指明哪些进程需要被监控,并利用 bypass 机制来控制不同进程的行为。因此,启动 ACS 过程中,ACS 需要先与分析服务器通信,获取分析的必要配置。此外,ACS 还需要负责清空不同应用加载的缓存。

2)完成字节码的转发。接收来自 DVM 虚拟机的字节码加载事件,并转发给外部系统的注入服务器进行注入。在注入完成后,接收注入服务器发回的字节码并交还给相应 DVM 以继续完成字节码的加载;

3)完成事件的转发。ACS 需要能够将不同进程的事件发送到分析服务器以推动分析的进行。本文采用了 Ashmem 共享内存的方式,来实现应用进程与 ACS进程的事件传输,以减少内存消耗提高性能。而在 ACS 的主程序中会单独设置一个线程,通过轮询的方法,将不同进程的事件发送出去。

ACService 采用 C++语言开发,代码位置放在外部 库 external 目录下。通过配置安卓的启动进程选项,可以让 ACService 在系统刚开始的时候就自动启动并注册,这样能够在第一时间为第一个 DVM 进程提供服务。

下图显示了在如何向 Service Manager 注册 ACService 服务,以及在程序中如何获取该服务。

/* Register ACSerivce to Service Manager */
void register_service(){
    IACService* service = new ACService();
    defaultServiceManager()->addService(
        String16("ACService"), service);
    android::ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}
/* Get ACService from Service Manager */
Sp<IACService> get_service(){
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder sm->getService(String16("ACService"));
    sp<IACService> interface_cast<IACService>(binder);
}
4.2.1 初始化功能

在 ACService 主程序的 main 方法里,会首先执行清除 DVM 字节码缓存的任务,即删除所有位于/data/dalvik-cache 目录下的 odex 字节码。接着,通过 register_service 向系统注册服务。register_service 以后,主程序会进入循环,等待服务请求。

4.2.2 注入服务

为了实现 2)中的注入功能,ACS 为 DVM 提供了一个接口,在 DVM 加载字节码文件的时候会将字节码以共享内存的方式发送给 ACService,ACService 则通过建立一个网络连接与注入服务器进行通信。DVM 加载字节码的时候,是通过IACService 的 instrumentDex 接口来与 ACService 通信的。instrumentDex 接收四个参数,分别表示含有字节码的文件的名称、原字节码的长度以及存储了原字节码的共享内存文件描述符及其最大容量。每次收到字节码,ACService 会向注入服务器发送新的注入事件。

4.2.3 事件接受和转发

而上述 3)的功能实现分为两个部分:从不同进程获取事件、以及将这些事件发送到分析服务器,实现如图4-3所示。图中上方部分表示进程Process 1,Process2……Process N 分别表示不同的待观测的 DVM 进程(DVM 进程包括了 Zygote 进程、所有从 Zygote fork 生成的进程以及其它利用 dalvikvm 程序启动的进程),各个 DVM 进程在运行的过程中,会产生 Binder IPC 调用事件、Dalvik 虚拟机的事件以及用户的分析事件。

在 ACService 进程中,有一个专门的线程,不断轮询所有队列,将未发送的事件内存块的内容转发出去。这里需要特殊说明的一点是,应用进程从 Zygote fork产生,但不同应用进程与 zygote 并不共享事件发送队列,因而所有进程可以被同等看待。

IACService 还有两个接口 mapPidPname 和 clientClose。mapPidPname 发生在zygote 通过 fork 产生子进程后,用于在 ACService 中维护进程号与进程名的映射关系,并根据进程名来判断该进程是否应当被监听;而 clientClose 表示一个虚拟机进程完成了分析任务或者在虚拟机结束后,需要在 ACS 服务中注销,注销后ACS 服务端能够进一步释放相关资源,提高运行效率。

 

 4.3 Dalvik 虚拟机的扩展

Dalvik 虚拟机的扩展,为本文框架提供了类似 JVMTI 接口中的虚拟机事件,丰富了 ShadowVM 的语意。

4.3.1 ShadowVM 支持

AREDispatch 是本文提供给用户实现异步分析的接口。它提供的 API 如图 3-6所示。这些 API 都是 native 方法,本文将其实现放在 Dalvik 虚拟机中。dalvik/vm/native 目录放置了许多 Java 库中与虚拟机运行时直接相关的类的 native方法实现。AREDispatch 必须作为系统第一批加载的类,因此其 native 方法的实现也放在这个目录下,以保证在系统 JNI 环境准备完毕前,AREDipstach 就可用。

最后通过 ACService 封装的接口 svmNewClassInfo 来将需要的类信息发送到服务器端。

jlong SetAndGetTag(Object* obj){
    jlong res;
    if(obj == NULL)
        res = 0;
    else if(obj->tag != 0)
        res = obj->tag;
    else if(dvmIsClassObject(obj))
        res = newClass((ClassObject*)obj);
    else {
        if(obj->clazz->tag == 0){ //its class not registered
            newClass(obj->clazz);
        }
        obj->tag = set_tag (obj_id++,get_class_id(obj->clazz->tag));
        res = obj->tag;
}
    return res;
}
jlong newClass(ClassObject *obj){
    jlong superid = SetAndGetTag(obj->super);
    jlong loaderid = SetAndGetTag(obj->classLoader);
    obj->tag = set_tag (obj_id++,clz_id++,1,1);
    svmNewClassInfo(obj->tag, obj->descriptor, loaderid, superid);
    return obj->tag;
}
4.3.2 虚拟机事件

在 DVM 中可以提供的事件,如下表。

 4.4 Binder 的扩展

对 Binder 事件的扩展,允许分析将不同进程、线程之间的事件串联起来,以提供一个更加完整的分析模型。为此通过修改 frameworks 目录下 Binder 实现,以及 service manager 中 C 语言实现的 binder 调用实现了 Binder 事件。

每次 Binder 调用,可以用<client_pid, client_tid, transaction_id>唯一标识,transaction_id 是一个线程局部自增长变量。原来的 Binder 库在被调用端,只能查询调用进程的进程号,而不能查询线程号,为了使 Binder 调用的接收端能够识别出 Binder 调用的完整来历,需要在传输 binder 信息的时候加上额外的信息,包括发起端的线程 id 和事务 id。

struct binder_transaction_data {
    ...
    pid_t sender_pid;
    //records the sender’s thread id

    pid_t sender_tid;
    //records the incremental counter for each binder call
    pid_t transaction_id;
    uid_t sender_euid;
    size_t data_size;
    ...
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/82950.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Typora上传文件到Gitee

工作内容,不对外开放 一、Typora上传笔记到CSDN 一、安装node.js 官网链接:Node.js (nodejs.org) 下载后得到一个.msi文件,双击即可。 win + R 打开CMD,基于node -v 和npm -v,验证是否安装成功: 二、配置Gitee 1、新建仓库 2、开源此仓库 2.1、初始化readme文件

Vue2+Vue3笔记(尚硅谷张天禹老师)day01

只是记录&#xff0c;初心是为了让页面更好看,会有错误 环境准备 下载vue:Vue下载 下面两个是可选的,主要是我想让控制台干净点 vue_dev_tool安装 vue_dev_tool安装 : Vue 控制台出现You are running Vue in development mode. Make sure to turn on production mode when dep…

【算法刷题之链表篇(1)】

目录 1.leetcode-82. 删除排序链表中的重复元素 II&#xff08;1&#xff09;题目描述&#xff08;2&#xff09;方法及思路&#xff08;一次遍历&#xff09;&#xff08;3&#xff09;代码实现 2.leetcode-19. 删除链表的倒数第 N 个结点&#xff08;1&#xff09;题目描述&a…

rabbitmq容器启动后修改连接密码

1、进入容器 docker exec -it rabbitmq bash 2、查看当前用户列表 rabbitmqctl list_users 3、修改密码 rabbitmqctl change_password [username] ‘[NewPassword]’ 4、修改后退出容器 ctrlpq 5、退出容器后即可生效&#xff0c;不需要重启容器

C++新经典07--auto、头文件防卫、引用与常量

auto的使用 严格来讲&#xff0c;在C语言中&#xff0c;如果某个函数中需要用到一些局部变量&#xff0c;那么局部变量都会集中定义在函数开头&#xff0c;而在C中不必遵循这样的规则&#xff0c;随时用随时定义即可。当然&#xff0c;作用域一般就是从定义的地方开始到该函数…

免费开源的vue+express搭建的后台管理系统

此项目已开源 前端git地址&#xff1a;exp后台管理系统前端: exp后台管理系统前端 后端git地址&#xff1a;express后台管理系统: express后台管理系统 安装运行 npm i yarn i 前端: npm run dev | yarn dev 后端: npm run start | yarn start 主要技术栈 前端后端名称版本名…

循环神经网络RNN完全解析:从基础理论到PyTorch实战

目录 一、循环神经网络全解1.1 什么是循环神经网络网络结构工作原理数学模型RNN的优缺点总结 1.2 循环神经网络的工作原理RNN的时间展开数学表述信息流动实现示例梯度问题&#xff1a;梯度消失和爆炸总结 1.3 循环神经网络的应用场景文本分析与生成1.3.1 自然语言处理1.3.2 机器…

Flutter实战·第二版-第三章 基础组件笔记

第三章&#xff1a;基础组件 3.1文本及样式 3.1.1 Text Text("Hello world",textAlign: TextAlign.left, );Text("Hello world! Im Jack. "*4,maxLines: 1,overflow: TextOverflow.ellipsis, );Text("Hello world",textScaleFactor: 1.5, );3.1…

WebDriver API及对象识别技术

html页面的iframe的切换 定位到客户管理 新增客户 会无法定位到新增客户&#xff0c;因为在另外一个iframe框架之中。 iframe是html中的框架标签&#xff0c;表示文档中可以嵌入文档&#xff0c;或者说是浮动的框架。在selenium中iframe同样如此&#xff0c;如果驱动器对…

TCP定制协议,序列化和反序列化

目录 前言 1.理解协议 2.网络版本计算器 2.1设计思路 2.2接口设计 2.3代码实现&#xff1a; 2.4编译测试 总结 前言 在之前的文章中&#xff0c;我们说TCP是面向字节流的&#xff0c;但是可能对于面向字节流这个概念&#xff0c;其实并不理解的&#xff0c;今天我们要介…

【C# 基础精讲】LINQ to Objects查询

LINQ to Objects是LINQ技术在C#中的一种应用&#xff0c;它专门用于对内存中的对象集合进行查询和操作。通过使用LINQ to Objects&#xff0c;您可以使用统一的语法来查询、过滤、排序、分组等操作各种.NET对象。本文将详细介绍LINQ to Objects的基本概念、常见的操作和示例&am…

代码随想录算法训练营第四十一天 | 343. 整数拆分,96.不同的二叉搜索树

代码随想录算法训练营第四十一天 | 343. 整数拆分&#xff0c;96.不同的二叉搜索树 343. 整数拆分动态规划贪心 96.不同的二叉搜索树 343. 整数拆分 题目链接 视频讲解 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff…

使用Druid解析SQL,获取SQL中所有使用的表

一、sqlParse组成 Druid SQL Parser分三个模块&#xff1a; - Parser - AST - Visitor 1.1 Parser parser是将输入文本转换为ast&#xff08;抽象语法树&#xff09;&#xff0c;parser有包括两个部分&#xff0c;Parser和Lexer&#xff0c;其中Lexer实现词法分析&#x…

uniapp 微信小程序 绘制海报,长按图片分享,保存海报

uView UI 2.0 dcloud 插件市场地址 弹窗海报源码 <template><!-- 推荐商品弹窗 --><u-popup :show"haibaoShow" mode"center" round26rpx z-index10076 bgColortransparent safeAreaInsetTop close"goodsclose"><image …

chatglm2-6b模型在9n-triton中部署并集成至langchain实践 | 京东云技术团队

一.前言 近期&#xff0c; ChatGLM-6B 的第二代版本ChatGLM2-6B已经正式发布&#xff0c;引入了如下新特性&#xff1a; ①. 基座模型升级&#xff0c;性能更强大&#xff0c;在中文C-Eval榜单中&#xff0c;以51.7分位列第6&#xff1b; ②. 支持8K-32k的上下文&#xff1b…

excel条件格式:不同组对应位置对比标记

问题描述 下图中有两组数据&#xff0c;想要对比两个对应位置的数据并标记 条件格式 选中其中一个单元格&#xff0c;条件格式->新建规则 使用公式确定要设置格式的单元格&#xff0c;自定义需求 格式化剩余同样标准的单元格

MySQL | JDBC连接数据库

一、什么是JDBC 概念&#xff1a; JDBC&#xff0c;即Java Database Connectivity&#xff0c;java数据库连接。是一种用于执行SQL语句的Java API&#xff0c;它是Java中的数据库连接规范。这个API由 java.sql.*,javax.sql.* 包中的一些类和接口组成&#xff0c;它为Java开发…

SpringBoot复习:(56)使用@Transactional注解标记的方法的执行流程

首先&#xff0c;如果在某个类或某个方法被标记为Transactional时&#xff0c;Spring boot底层会在创建这个bean时生成代理对象&#xff08;默认使用cglib) 示例&#xff1a; 当调用studentService的addStudent方法时&#xff0c;会直接跳到CglibAopProxy类去执行intercept方…

Edge浏览器免费使用GPT3.5

搜索sider,安装Sidebar插件 注册账号即可每天免费使用30次。 Sider: ChatGPT侧边栏,GPT-4, 联网, 绘图

30.Netty源码服务端启动主要流程

highlight: arduino-light 服务端启动主要流程 •创建 selector •创建 server socket channel •初始化 server socket channel •给 server socket channel 从 boss group 中选择一个 NioEventLoop •将 server socket channel 注册到选择的 NioEventLoop 的 selector •…