Binder Proxy技术方案

作者 低端码农

时间 2014.08.23

0x0

看到有多朋友尝试通过hook系统进程system_process的ioctl,以企图截获系统的IPC通讯。这个方法的弊端是太偏低层了,当截获成功了之后,要解析当中的通讯数据是比較麻烦了. 另外,当中还涉及一堆兼容性的问题,因为不同的Android固件版本号,有好些Parcelable结构的字段是有所修改,这些变化假设ioctl里做解析,都须要一一顾及到才行,因此这个方法我觉得距离产品化另一段距离。

0x1

在Android上,全部系统的NativeService主要保存在system_process和com.android.phone这两个进程,比方我们常常看到的ActivityManagerService(AMS)。这些NativeService大部分都是继承自Binder的Java对象,没错,他们是Java对象。

我们知道,Android上的大部分IPC通讯都是通过其特有的binder模块进行的,因此上述的Java的NativeService要跟内核进行通讯,由于仅仅有c/c++才干直接跟内核交互,因此这里必定存在JNI通讯。比方AMS的设计:

AMS继承Binder(IBinder的子类,封装了IPC通讯公共部分的逻辑),Binder里保存着一个类型为int的mObject的字段,这个字段正是其C++对象JavaBBinder对象的地址,这个JavaBBinder才是AMS终于跟内核通讯的对象。代码例如以下:

public class Binder implements IBinder {
//... /* mObject is used by native code, do not remove or rename */
private int mObject; //这个对象保存的就是JavaBBinder的指针
private IInterface mOwner;
private String mDescriptor; //...
}

相同的,在JavaBBinder中,也保存着一个类型jobject的mObject,指向上层Java对象。看看JavaBBinder的代码:

class JavaBBinder : public BBinder
{
//... jobject object() const
{
return mObject;
} //... private:
JavaVM* const mVM;
jobject const mObject; //这个保存的是AMS的引用
};
}

Java和C++就是通过这两个字段相互连结在一起的。

当中JavaBBinder中的mObject是整个IPC关键的一节,全部的client请求,都是先到达JavaBBinder,然后JavaBBinder再通过JNI调用mObject的execTransact的方法,终于把请求发送到AMS。

因此,我们仅仅要想办法找到AMS的对象的JavaBBinder,再把mObject替换为代理对象(记作ProxyBinder,这个对象是我们实现的Java对象),就能够实现Binder Proxy了,以下是示意图:

0x2

在Java层,要获取AMS引用,通过ServiceManager就可以,只是这类是隐藏类,通过反射才干够调用。通过ServiceManager.getService("activity")即能够拿到AMS。

在Native,要获取AMS所相应的JavaBBinder地址,defaultServiceManager的getService方法获取到。

接下来就是要替换mObject对象了,JavaBBinder的mObject对象并不能直接替换,由于mObject是const的,我写了一个DummyJavaBBinder的类,能够非常easy地处理好这个问题,DummyJavaBBinder的实现例如以下:

class DummyJavaBBinder : public BBinder{
public:
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) {
return NO_ERROR;
} jobject object() const {
return mObject;
} JavaVM* javaVM() const {
return mVM;
} void changeObj(jobject newobj){
const jobject* p_old_obj = &mObject;
jobject* p_old_obj_noconst = const_cast<jobject *>(p_old_obj);
*p_old_obj_noconst = newobj;
} private:
JavaVM* const mVM;
jobject const mObject;
};

0x3

因为BinderProxy截获的层次比較高,因此请求数据结构的解析都很方便,所使用接口大部都是Framework的接口,兼容性也不存在,以下是我写的一个演示样例,演示样例主要是实现怎样让某个pkg免杀:

private static final class ProxyActivityManagerServcie extends Binder {
private static final String CLASS_NAME = "android.app.IActivityManager";
private static final String DESCRIPTOR = "android.app.IActivityManager";
private static final int s_broadcastIntent_code; static {
if (ReflecterHelper.setClass(CLASS_NAME)) {
s_broadcastIntent_code = ReflecterHelper.getStaticIntValue("BROADCAST_INTENT_TRANSACTION", -1);
} else {
s_broadcastIntent_code = -1;
}
} private IBinder mBinder; public ProxyActivityManagerServcie(IBinder binder) {
mBinder = binder;
mResorter = new SmsReceiverResorter(binder);
} @Override
protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
/**
*
* public int broadcastIntent(IApplicationThread caller,
* Intent intent, String resolvedType, IIntentReceiver resultTo,
* int resultCode, String resultData, Bundle map,
* String requiredPermission, int appOp, boolean serialized,
* boolean sticky, int userId) throws RemoteException
*/
if (code == s_broadcastIntent_code) {
pos = data.dataposition(); data.enforceInterface(DESCRIPTOR);
IBinder caller = data.readStrongBinder();
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
int resultCode = data.readInt();
String resultData = data.readString();
Bundle map = data.readBundle();
String requiredPermission = data.readString();
int appOp = data.readInt();
boolean serialized = data.readInt() != 0;
boolean sticky = data.readInt() != 0;
int userId = data.readInt(); //TODO 获取到全部的參数,依据參数做各种截获 //FINAL
data.setDataPosition(pos);
} return mBinder.transact(code, data, reply, flags);
}
}

0x4

这个技术方案,涉及到注入和dex载入,这方面网上教程许多,so注入能够參考古河大神的LibInject, 而Java注入能够參考malokch的《注入安卓进程,并hook java世界的方法》.

另外也能够參考我之前写的系列文章《进击的Android注入术》。这个系列具体讲述了so注入,dex注入到binder proxy的整个技术细节。

演示样例的源代码我已经上传到https://github.com/boyliang/Hijack_AMS_broadIntent

Binder Proxy技术方案的更多相关文章

  1. 分布式锁1 Java常用技术方案

    前言:       由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.所以自己结合实际工作中的一些经验和网上看到的一些资 ...

  2. unity小地图技术方案总结

    技术方案 一:从顶视图获取实时小地图(优点实现快容易对地图进行放大缩小操作而且地图,缺点是不好对地图做出修改,只能在顶部加个另外的相机层来遮盖) 1.创建Redertexture并改名为smallma ...

  3. iOS多线程技术方案

    iOS多线程技术方案 目录 一.多线程简介 1.多线程的由来 2.耗时操作的模拟试验 3.进程和线程 4.多线程的概念及原理 5.多线程的优缺点和一个Tip 6.主线程 7.技术方案 二.Pthrea ...

  4. Facebook存储技术方案:找出“暖性BLOB”数据

    Facebook公司已经在其近线存储体系当中彻底弃用RAID与复制机制,转而采用分布式擦除编码以隔离其所谓的“暖性BLOB”. 暖性?BLOB?这都是些什么东西?大家别急,马上为您讲解: BLOB—— ...

  5. 分布式锁1 Java常用技术方案(转)

    转:http://www.cnblogs.com/PurpleDream/p/5559352.html#3450419 前言:       由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临 ...

  6. Android基于WIFI实现电脑和手机间数据传输的技术方案研究

    Android手机和电脑间基于wifi进行数据传输,从技术上讲,主要有两种方案: 一种是通过ftp协议实现,Android手机作为数据传输过程中的ftp服务器: 一种是通过http协议实现.Andro ...

  7. 技术方案:在外部网址调试本地js(基于fiddler)

    1 解决的问题 1)        场景1:生产环境报错 对前台开发来说,业务逻辑都在js中,所以报错90%以上都是js问题. 如果生产环境出现报错,但是测试环境正常.这时修改了代码没有环境验证效果, ...

  8. 分布式锁2 Java非常用技术方案探讨之ZooKeeper

    前言:       由于在平时的工作中,线上服务器是分布式多台部署的,经常会面临解决分布式场景下数据一致性的问题,那么就要利用分布式锁来解决这些问题.以自己结合实际工作中的一些经验和网上看到的一些资料 ...

  9. 全面解密QQ红包技术方案:架构、技术实现、移动端优化、创新玩法等

    本文来自腾讯QQ技术团队工程师许灵锋.周海发的技术分享. 一.引言 自 2015 年春节以来,QQ 春节红包经历了企业红包(2015 年).刷一刷红包(2016 年)和 AR 红包(2017 年)几个 ...

随机推荐

  1. LCD显示--Ht1621b芯片显示屏驱动

    Ht1621b芯片显示屏驱动 关于HT1621b芯片的具体信息能够參考数据手冊上的内容:百度文库HT1621b中文资料 CS : 片选输入接一上拉电阻当/CS 为高电平读写HT1621的数据和命令无效 ...

  2. linux命名管道通信过程

    前一个道,这节学习命名管道. 二命名管道 无名管道仅仅能用来在父子进程或兄弟进程之间进行通信,这就给没有亲缘关系的进程之间数据的交换带来了麻烦.解决问题就是本节要学习的还有一种管道通信:命名管道. 命 ...

  3. C#对HTTP数据还原

    使用C#对HTTP数据还原   [创建时间:2016-05-12 00:19:00] NetAnalyzer下载地址 在NetAnalyzer2016中加入了一个HTTP分析功能,很过用户对此都很感兴 ...

  4. CentOS下yum使用代理的设置

    export后好像没用? 问题描述: CentOS yum时出现“Could not retrieve mirrorlist http://mirrorlist.centos.org/?release ...

  5. linux route命令的使用详解

    route命令用于显示和操作IP路由表.要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现.在Linux系统中,设置路由通常是 为了解决以下问题:该Linu ...

  6. 腾讯測试project师笔试面试记录

        从3月29日參加腾讯笔试開始,開始了为期1周的腾讯之旅,尽管最后还是跪在了二面上,可是感觉收获非常多,至少明确了自己与向往的BAT公司的差距,明确了自己还是路漫漫其修远兮.     腾讯非常注 ...

  7. Codeforces Round #309 (Div. 2) C

    题意: 就是给出总共同拥有k种颜色.每种颜色有ki种,排列必须满足第i+1种的最后一种颜色必须在第i种最后一种颜色的后面,其它颜色任意.总共同拥有多少种排列点的方法. 分析: 如果d[i]表示前i种的 ...

  8. codeforces 597B Restaurant

    题目链接:http://codeforces.com/contest/597/problem/B 题目分类:贪心 题目分析:经典的看节目问题(挑战程序设计page 40) 代码: #include&l ...

  9. Java中替代C# ref/out 关键字方案:

    刚学习Java不久,今天遇到一个问题,需要在方法中修改传入的对象的值,确切的说是需要使用一个方法,创建一个对象,并把其引用返回,熟悉C#的我的第一反应就是C#中的ref/out关键字,结果发现Java ...

  10. TCP/IP详细解释--TCP/IP可靠的原则 推拉窗 拥塞窗口

    TCP和UDP在同一水平---传输层.但TCP和UDP最不一样的地方.TCP它提供了一个可靠的数据传输服务,TCP是面向连接的,那.使用TCP两台主机通过第一通信"拨打电话"这个过 ...