CVE漏洞中文网

0DayBank一个专门收集整理全球互联网漏洞的公开发布网站
  1. 首页
  2. 百科
  3. 正文

xposed

2017年5月23日 759点热度 0人点赞 0条评论

xposed

  • 首页
  • 分类阅读
  • 文库
  • 专栏
  • 公开课
  • 商城
  • 漏洞盒子
注册 | 登录
投稿

Xposed模块编写的那些事

L52016-09-25共321940人围观 ,发现 11 个不明物体终端安全

*本文原创作者:L5,本文属FreeBuf原创奖励计划,未经许可禁止转载

背景阐述

Android是一种基于Linux的自由及开放源代码的操作系统,由Google公司和开放手机联盟领导及开发。由于其开放的特质,吸引了一大批硬件厂商和软件开发者。第三方的统计数据显示,2016年Android占有的市场份额高达76.4%,远远超过其他智能手机厂商。

大量的Android os装机量,在丰富安卓系统使用场景的同时,也催生出了许多安全问题。xposed框架提供了不需要修改系统源码就能灵活定制系统功能的能力,极大的方便了安全研究人员的工作。且xposed利用了JNI机制修改Java framework的功能实现,没有涉及arm本地指令的适配工作,所以很少出现兼容性问题。本文是为了带领大家了解下此框架的能力以及实现方式,最终打造一款属于自己的“神器”。

本文总计5个章节,以xposed的使用需求作为切入点,由浅入深地介绍了模块的编写实战、模块编写进阶篇和常用模块编写以及异常情况&后续展望。本文来源于平时的实践,用作大家互相交流与学习。

xposed 使用需求

我们在选择使用xposed功能模块的时候,可能基于以下需求之一:

[1]监控app行为:查看关键api 的调用日志,用于特定目标的行为分析。

[2]定制系统功能:改变原先函数的处理逻辑,自定义api行为。

[3]沙箱功能定制:主要关注反环境检测(上述两点关注app本身),如:恶意样本分析,模拟器需要尽可能的“真实”以便触发样本行为。

当然,实际的需求并不会仅仅局限于此,可能会更多。这里列出的需求点也只是个人的总结,如有遗漏,敬请告知。毕竟需求驱动学习,文章的出发点也是希望聚集有着共同需求点的小伙伴,大家有个讨论地方,共同学习和进步。好,其它话不多说,接下来进入xposed模块的编写实战。

xposed 模块编写实战

xposed 模块的能力包括以下几个方面:

[1] 对普通函数或者构造函数有作用(针对具体实现类,不包括接口,抽象类的实现函数也可以hook)。

[2] 对目标函数进行 before、after 代码插桩,多用于操作(查看或修改)api的入参以及返回值。

[3] 目标函数替换,多用于功能变更、版本升级。

接下来,我们列举下 xposed 模块编写可能遇到的实际场景(假设阅读本文之前,读者拥有基本的模块编写经验)。在这个demo中,我将尽可能全面的再现需要hook操作的场景。比如:函数体、构造函数、匿名类、匿名内部类以及类的值域。

1.png

上述demo中存在

(1)静态field变量sMoney

(2)隐藏函数hidden_fun(触发的条件相对苛刻)

(3)内部类inner_class

(4)匿名内部类Animal animal = new Animal(){}

(5)构造函数demo()

我们逐个回顾下相应问题的解决方法:

(1)静态field变量sMoney的值的修改和获取,可以直接使用xposed提供的XposedHelpers类相关功能函数。具体操作可以类比以下示例代码片段:

/*
 * Hook field
 * class: com.example.inner_class_demo.demo
 *  field: sMoney
 */

Class clazz = XposedHelpers.findClass("com.example.inner_class_demo.demo",lpparam.classLoader);
XposedHelpers.setStaticObjectField(clazz,"sMoney",110);
Field sMoney = clazz.getDeclaredField("sMoney");
sMoney.setAccessible(true);
System.out.println(sMoney.get(null));

(2)主动调用隐藏函数hidden_fun(这一类函数是指触发条件比较苛刻的函数,但是我们又需要了解它的输入、输出的大致关系),需要通过clazz来新建实例,最后将此实例与函数名组装成XposedHelpers.callMethod() 的实参需求形式。具体操作可以类比以下示例代码片段:

/*
 * Call hidden function
 * class   : com.example.inner_class_demo.demo 
 *  function: hidden_fun()
 */

Class clazz = XposedHelpers.findClass("com.example.inner_class_demo.demo",lpparam.classLoader);
XposedHelpers.callMethod(constructor.newInstance(),"hidden_fun");

以上代码仅适用于存在无参构造函数的类,如果目标类没有无参构造函数,那就麻烦一点了,需要根据构造函数参数类型,反射寻找构造函数,接着才能类似上述操作。具体操作可以类比以下示例代码片段:

假设此时的构造函数仅有以下函数,即public demo(){}不存在的情形: 
public demo(String str){...}

/*
 * Call hidden function
 * class   : com.example.inner_class_demo.demo 
 *  function: hidden_fun()
 */

Class clazz = XposedHelpers.findClass("com.example.inner_class_demo.demo",lpparam.classLoader);
Constructor constructor = clazz.getConstructor(String.class);
XposedHelpers.callMethod(constructor.newInstance("..."),"hidden_fun");

(3)内部类inner_class作为Android编程过程常见的一种编程方式,这里为了demo的全面,也将其列出。其实内部类整个处理过程与普通类极其相似,具体操作可以类比以下示例代码片段:

/*
 * Hook the function of inner class
 * class   : com.example.inner_class_demo.demo$inner_class
 *  function: secret(String , boolean)
 */

XposedHelpers.findAndHookMethod("com.example.inner_class_demo.demo$inner_class", lpparam.classLoader,

    "secret", String.class, boolean.class, new XC_MethodHook() {

      protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        for (int i = 0; i < param.args.length; i++) {
          XposedBridge.log(" argument is:" + param.args[i]);
        }

        int field_result = (int) XposedHelpers.getObjectField(param.thisObject,"pMoney");

        XposedBridge.log(String.valueOf(field_result));
      }
    });

需要注意的是,这里打印目标函数参数列表的时候,用了XposedBridge.log()。这样的输出方式对日志的长度有限制,即长度不超过1024。特殊场合(比如:文件读取时,需要查看文件的内容)需要注意处理下,不然会出现截断的现象。

(4)匿名内部类Animal animal = new Animal(){}的处理

同内部类,一般是class_name$1之类,具体可以反编译目标程序查看下。常见的反编译工具,比如:apktool、jeb、baksmali 均可以方便达到目的。

(5)构造函数demo()的处理,可以使用xposed提供的XposedHelpers类,具体操作可以类比以下示例代码片段:

/*
 * Hook the constructor of class
 * class   : om.example.inner_class_demo.demo
 *  function: demo()
 */

Class clazz = XposedHelpers.findClass("com.example.inner_class_demo.demo",lpparam.classLoader);
XposedHelpers.findAndHookConstructor(clazz, new XC_MethodHook() {
  ...
});

需要注意的是,由于构造函数不同于普通函数,函数名不需要提供(因为与类名相同,xposed框架处理函数名问题)。

模块编写进阶篇

在实际的模块编写时候,我们都或多或少地遇到一些问题。接下来我将列出一些我在实践过程中遇到的一些问题和解决思路,期待帮助有同样困惑的小伙伴。如果你有问题,这里很不幸的又没有列出,那你可以拿出来大家一起讨论下。

一:同时监控多个构造函数、多个重载函数

通过上一小节模块的编写,我们现在已经可以顺利hook某一特定目标函数了。如果遇到某一类函数需要“批量”hook操作的时候,比如:需要同时监控多个构造函数、多个重载函数,我们此时不可能去挨个hook每个具体目标,那么应该怎么操作呢?我们可以这样来实现:

/*
 * Hook all constructors of class
 * class   : om.example.inner_class_demo.demo
 *  function: demo()、demo(String)
 */

hookAllConstructors(clazz, new XC_MethodHook() {
  ...
});

/*
 * Call all methods of class
 * class   : om.example.inner_class_demo.demo
 *  function: method()、method(String)
 */

hookAllMethods(clazz, new XC_MethodHook() {
  ...
});

我们可以总结一个规律:hook重载函数时候,只需要忽略参数的具体类型即可。这种方式其实可以达到两种效果:1. 高效的处理函数重载问题 2.目标函数参数类型太复杂,自定义的类型太多。忽略参数类型,可以简化我们的hook工作。

二:目标app功能丰富,用到multidex加载技术,我们又该怎么办?

由于dalvik环境下xposed对multidex的支持没有很好的通用解决方案,寻找目标函数会发生ClassNotFoundError,所以处理multidex需要一些技巧(Tips): 此问题因为classloader出错引起的,所以要寻找attachBaseContext 的classloader,而非lpparam.classLoader(此思路来自非虫前辈)。

下图即为xposed作者对不支持multidex的解释,详细的内容可以去github上查看对应的issue。

图片5.png

常用模块编写

在这一章节,我将列出一些常见的功能模块。希望发散下大家的思路、节约模块开发的时间成本(毕竟重复劳动会消耗些时间、精力,积少成多嘛)。

第一部分

Hook org.apache.http 包中的网络请求,忽略参数然后使用hookAllMethods就可以同时拦截HttpPost、HttpGet、HttpUriRequest类型的网络请求参数。

/*
 * Hook net access
 * abstract class: org.apache.http.impl.client.AbstractHttpClient
 *  function      : execute(HttpHost target, HttpRequest request,HttpContext context)
 *                :execute(HttpUriRequest request, HttpContext context)
 */

hookAllMethods("org.apache.http.impl.client.AbstractHttpClient", lpparam.classLoader,
  "execute", new XC_MethodHook() {

  @Override
  protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
   print_args(param);
  }
});

需要注意点有二:

1. 这里就是0×02章节里面第[1]点提到的,xposed针对抽象类中的具体实现函数的hook。

2. 这里参数特殊,如果直接强转成String类型然后输出,将会得到无意义的输出,形如:org.apache.http.client.methods.HttpPost@41d45200。所以输出之前可以判断下,具体操作可以类比以下示例代码片段:

Object arg = param.args[i];
String argValue = "null";

if(arg instanceof HttpPost){
  URI uri = ((HttpPost)arg).getURI();
  argValue = String.format("uri=%s ", uri.toString());
}else if(arg instanceof HttpGet){
  URI uri = ((HttpGet)arg).getURI();
  argValue = uri.toString();
}else if(arg instanceof HttpUriRequest){
  URI uri = ((HttpUriRequest)arg).getURI();
  argValue = uri.toString();
}else
  argValue = arg.toString();

这里需要注意的是,HttpPost 之类的包在高版本的sdk中已经不存在了,顺利通过编译需要进行以下操作:1. Android studio中修改编译文件,添加

android {
    useLibrary 'org.apache.http.legacy'
}

3. ADT中可以按照以下教程,The import org.apache.http.HttpResponce cannot resolved error solution

第二部分

网络重定向,修改网络请求地址,“模拟“”中间人攻击效果,具体操作可以类比以下示例代码片段:

/*
 * Redirect net access
 * class: java.net.URL
 *
 */

XposedHelpers.findAndHookConstructor("java.net.URL", lpparam.classLoader, String.class, new XC_MethodHook() {
  @Override
  protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
    String url = (String) param.args[0];
    param.args[0] = "http://www.baidu.com/";
    XposedBridge.log("new URL to " + param.args[0]);
  }
});

[3] IO异常监控,这里的IO异常包括所有网络IO异常和本地异常,具体操作可以类比以下示例代码片段:

/*
 * Monitor IO Exception
 * class: java.io.IOException
 *
 */

XposedBridge.hookAllConstructors(IOException.class, new XC_MethodHook() {
  @Override
  protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    XposedBridge.log((Throwable) param.thisObject);
  }
});

异常情况和后续展望

常用的hook操作总结如下,Object…代表着变参,实际编程过程中,需要保证提供的参数列表中最后一个参数一定是hook操作的回调,前面是函数参数class类型。

/*
 *  Hook any method (or constructor) with the specified callback
 *
 * @param targetclass The method in which
 * @param hookMethod The method to be hooked.
 * @param callback The callback to be executed when the hooked method is called.
 * @return An object that can be used to remove the hook.
 */

XposedHelpers#findAndHookMethod(String, ClassLoader, String, Object...)
XposedHelpers#findAndHookMethod(Class, String, Object...)
XposedBridge#hookAllMethods

XposedHelpers#findAndHookConstructor(String, ClassLoader, Object...)
XposedHelpers#findAndHookConstructor(Class, Object...)
XposedBridge#hookAllConstructors

模块编程过程中,如果不希望直接提供变参列表,可以提供Object数组,这样可以保证上述接口的“稳定”。具体操作可以类比以下示例代码片段:

Object[] args_obj = new Object[2] ;

XC_MethodHook callback_fun = new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
      XposedBridge.log("...");

    }

    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
      XposedBridge.log("...);

    }
};

args_obj[0] = String.class;
args_obj[1] = callback_fun;

findAndHookMethod(class_name, lpparam.classLoader, function_name,args_obj);

以上demo为debug版本,没有混淆。在实践过程中,可能遇到混淆甚至加固的产品。更有甚者,目标app即使没有混淆、加固,但是我们还是不能很快定位目标函数,难道此时只能大海捞针般静态寻找target?这时候需要通过一些辅助工具帮助我们定位api位置。

此文章可能考虑续篇,内容根据上述异常情况或者我能想到的新的出发点与思路。比如:反模拟器检测、反调试和加密库操作监控,每一点都是一个小的工程,需要考虑周全些才能有实用价值,大家一起努力。

最后,感谢非虫对文章难点提供的解决思路,以及最终文章质量的把关。

致谢非虫(非虫看雪ID)

*本文原创作者:L5,本文属FreeBuf原创奖励计划,未经许可禁止转载

L51 篇文章等级: 1级
|
|
  • 上一篇:FBI被坑了!破解iPhone 5c的密码其实只要100美元
  • 下一篇:智能手机可通过测量电磁能和声波来入侵3D打印机

这些评论亮了

  • yege0201(3级)回复
    xposed针对multidex的解决办法(这还是xposed作者给的解决办法,https://github.com/rovo89/XposedBridge/issues/30#issuecomment-68486449),已经用了好久了,还没出现什么问题,运行情况良好。
    findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    // place your hooks here, it should work with lpparam.classLoader
    findAndHookMethod(class, lpparam.classLoader, method, arg1, arg2, ... new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
    // this will be called before the clock was updated by
    // the original method
    Log.d("xposed", "劫持开始了~");
    }
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    // this will be called after the clock was updated by
    // the original method
    }
    });
    }
    });
    )9(亮了
  • 虽如此却但是(1级)回复
    不错,谢谢分享
    )6(亮了
发表评论

已有 11 条评论

  • 向北向南61 (1级) 2016-09-25回复1楼

    很赞的文章,提到的很多点都是在写xposed的时候遇到的一些坑,我对文章提到的multidex比较好奇,确实在写的时候发现有些app会报classnotfound的问题,您提到需要attachBaseContext的ClassLoader,还是不太清楚,请问您详细说一下吗?

    亮了(3)
  • yege0201 (3级) 2016-09-25回复2楼

    xposed针对multidex的解决办法(这还是xposed作者给的解决办法,https://github.com/rovo89/XposedBridge/issues/30#issuecomment-68486449),已经用了好久了,还没出现什么问题,运行情况良好。
    findAndHookMethod(Application.class, "attach", Context.class, new XC_MethodHook() {
    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    // place your hooks here, it should work with lpparam.classLoader
    findAndHookMethod(class, lpparam.classLoader, method, arg1, arg2, … new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
    // this will be called before the clock was updated by
    // the original method
    Log.d("xposed", "劫持开始了~");
    }

    @Override
    protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    // this will be called after the clock was updated by
    // the original method
    }
    });
    }
    });

    亮了(9)
  • 还我青山绿水 2016-09-26回复3楼

    亮了(3)
  • iAcn连续 2016-09-26回复4楼

    我就不 Mark 了[doge]

    亮了(1)
  • lpcdma 2016-09-26回复5楼

    怎么hook静态变量呢,例如
    private static int vul = 0
    我想hook这里的vul,
    求解,谢谢

    亮了(3)
  • 六丁目 (1级)移动安全工作者... 2016-09-26回复6楼

    我去,楼上都赶早啊

    亮了(4)
  • 虽如此却但是 (1级) 2016-09-26回复7楼

    不错,谢谢分享

    亮了(6)
  • 腾讯安全管家 2016-09-26回复8楼

    卧槽病毒怎么写的啊

    亮了(5)
  • 林疏狂 (1级) 2016-09-26回复9楼

    膜拜

    亮了(3)
  • 移动安全_Bert 2016-09-28回复10楼

    好文

    亮了(1)
  • 情随事迁 2016-12-25回复11楼

    怎么解决静态方法里面创建的receiver每次都不一致问题?我广播接受者监听,每次创建了2次,明明不可能出现的后面发现地址不对,一个class处在不同的空间。这问题咋搞?。 框架作者已经把我拉黑了。我没法反馈

    亮了(1)

必须您当前尚未登录。登陆?注册

必须(保密)

表情插图

取消

L5

这家伙太懒,还未填写个人描述!

1 篇文章0 条评论

相关阅读

  • 2017第一季度安卓短信扣费木马研究:七成扣费木马擅长以”用户的名义”骗取话费
  • “SandJacking”攻击:在未越狱的 iOS 设备上安装恶意应用
  • 以为禁用麦克风就不会被监听了吗?用耳机也可以哟
  • 移动APP安全行业报告电商篇
  • 针对国外一款超火约会软件Tinder的取证分析

特别推荐

关注我们 分享每日精选文章

不容错过

  • 飞越珠海来看你:2016 GeekPwn澳门全程纪实FB独家2016-05-16
  • 【更新PPT下载】网络安全黑暗森林法则:2015中国互联网安全大会(ISC)深度回顾FB独家2015-10-10
  • 五大安全研究者必用的搜索引擎secist2016-12-22
  • 机器学习与人工智能将应用于哪些安全领域?bimeover2017-02-03

FREEBUF

  • 免责声明
  • 关于我们
  • 加入我们

广告及服务

  • 寻求报道
  • 广告合作
  • 联系我们
  • 友情链接

关注我们

  • 官方微信
  • 新浪微博
  • 腾讯微博
  • Twitter

赞助商

Copyright © 2013 WWW.FREEBUF.COM All Rights Reserved 沪ICP备13033796号

css.php

正在加载中...

0daybank

标签: 暂无
最后更新:2017年5月23日

小助手

这个人很懒,什么都没留下

点赞
< 上一篇
下一篇 >

文章评论

您需要 登录 之后才可以评论

COPYRIGHT © 2024 www.pdr.cn CVE漏洞中文网. ALL RIGHTS RESERVED.

鲁ICP备2022031030号

联系邮箱:wpbgssyubnmsxxxkkk@proton.me