最新消息:欢迎访问Android开发中文站!商务联系QQ:1304524325

Xposed为你开启一扇窗

开发进阶 loading 106浏览 0评论

Xposed为你开启一扇窗

Xposed框架是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作,在这个框架下,我们可以加载很多插件App,这些插件App可以直接或间接劫持、篡改、伪造一些信息。

原理探究

Android平台的动态劫持,通过替换/system/bin/app_process程序控制zygote进程,使得app_process在启动过程中会加载XposedBridge.jar这个jar包,从而完成对Zygote进程及其创建的Dalvik虚拟机的劫持。理论上我们的插件APP可以hook到系统任意一个Java进程zygote、systemserver、systemui。

原理就不讲那么多了,网上有很多分析的文章,比如:

Xposed框架原理深入研究

https://blog.csdn.net/ascii2/article/details/47974217

Dalvik虚拟机原理及Xposed hook原理

https://cloud.tencent.com/developer/article/1193511

Android Hook框架Xposed原理与源代码分析

https://blog.csdn.net/wxyyxc1992/article/details/17320911

不得不稍微提一下:Method中,有两个非常重要的指针:

54 /*
 55  * The remaining items are not used for abstract or native methods.
 56  * (JNI is currently hijacking "insns" as a function pointer, set
 57  * after the first call.  For internal-native this stays null.)
 58  */
 59 
 60 /* the actual code */
 61 const u2*   insns;  /* instructions, in memory-mapped .dex */

 66 /*
 67  * JNI: native method ptr; could be actual function or a JNI bridge.  We
 68  * don't currently discriminate between DalvikBridgeFunc and
 69  * DalvikNativeFunc; the former takes an argument superset (i.e. two
 70  * extra args) which will be ignored.  If necessary we can use
 71  * insns==NULL to detect JNI bridge vs. internal native.
 72  */
 73 DalvikBridgeFunc nativeFunc;

有兴趣的可以去研究一下,这里不做赘述。

免Root使用 Xposed 模块

VirtualXposed,英文原话“A simple app to use Xposed without root, unlock the bootloader or modify system image, etc. “,翻译:“使用VirtualXposed可以免root、不用解锁bootloader或修改系统镜像”。

官方文档:https://vxposed.com/

GitHub:https://github.com/android-hacker/VirtualXposed

Xposed组成部分

Xposed的C++部分

主要是用来替换/system/bin/app_process并为XposedBridge提供JNI方法。

XposedInstaller

Xposed的安装包,负责配置Xposed工作的环境并且提供对基于Xposed框架的Modules的管理。

在安装XposedInstaller之后,app_process与XposedBridge.jar放置在了/data/data/de.robv.android.xposed.installer

XposedTools

XposedTools就是用来帮助我们编译Xposed和XposedBridge的

XposedMods

开发者使用Xposed开发的一些Modules

Xposed使用

如何集成

AndroidManifest.xml

<meta-data
    android:name="xposedmodule"
    android:value="true" />
<meta-data
    android:name="xposeddescription"
    android:value="省略一万字,想写啥就写啥~~~" />
<meta-data
    android:name="xposedminversion"
    android:value="54" />

assets/xposed_init 此文件内容添加Xposed入口类路径

d.xposedshare.hook.MainHookLoad

app/lib/ 此路径下,集成XposedBridgeAPI-89.jar,

build.gradle中添加 compileOnly files(‘lib/XposedBridgeAPI-89.jar’)

然后,我们就可以在Xposed Installer中看到我们自己定义的模块了。

注意:在运行Xposed之前,需要把Install Run去掉哦。每次修改运行HOOK相关之处的代码,都需要重启手机!

演示

我是如何分析的?

打开App,比如这个页面,为了不增加收入,就把码给挡住了,;-)

这样我们在用Accessibility拿到当前页面的ClassName,比如这样:

这样就给我们反编译出来的代码找到了分析入口。对就从这个类下手。className====类路径+类名。className在xposed框架使用时,用来拿到class。

接下来我们使用Apktools打开需要学习的App,慢慢读起来,学习到很多优秀之处。

解压反编译包的资源

找到二维码页面的Activity:

找到相关组件Field:

在分析的过程中,发现了一个点,对于我们熟悉App的个别模块的逻辑由很大帮助,一个日志验证类,客官请看:

所以我们平时在打印log时一定要注意咯。另外,在分析App时,看到混淆的代码,方法、变量等名称都已经变化了,这就要求当使用Hook时需要根据不同版本适配。

如何使用Xposed?

下面我们就从三个方面演示一下

Hook Android系统方法

public class MainHookLoad implements IXposedHookLoadPackage {
   @Override
   public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
       //系统的演示用
       XposedHelpers.findAndHookMethod("android.telephony.TelephonyManager", lpparam.classLoader,
                "getDeviceId", new XC_MethodHook() {
         @Override
         protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            XposedBridge.log("donald beforeHookedMethod");
         }

         @Override
         protected void afterHookedMethod(MethodHookParam methodHookParam) throws Throwable {
            methodHookParam.setResult("这是被修改的数据imei");
            XposedBridge.log("donald Hook device id is successful!!! ");
         }
      });
   }
}

这样就轻轻松松hook住系统方法,任何App在调用时返回我们修改的内容。手机上很多系统方法修改后,一个物理手机就转身多个虚拟手机了。

Hook第三方App(最最有名的支付工具:支付宝)

public class MainHookLoad implements IXposedHookLoadPackage {
   @Override
   public void handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
 // hook设置金额和备注的onCreate方法,自动填写数据并点击
            XposedHelpers.findAndHookMethod("com.alipay.mobile.payee.ui.PayeeQRSetMoneyActivity", lpparam.classLoader, "onCreate", Bundle.class, new XC_MethodHook() {
     @Override
     protected void afterHookedMethod(MethodHookParam param) throws Throwable {
        Field jinErField = XposedHelpers.findField(param.thisObject.getClass(), "b");
        final Object jinErView = jinErField.get(param.thisObject);
        Field beiZhuField = XposedHelpers.findField(param.thisObject.getClass(), "c");
        final Object beiZhuView = beiZhuField.get(param.thisObject);

         //设置支付宝金额和备注
         XposedHelpers.callMethod(jinErView, "setText", "123");
         XposedHelpers.callMethod(beiZhuView, "setText", "备注内容");
         //点击确认
         Field quRenField = XposedHelpers.findField(param.thisObject.getClass(), "e");
         final Button quRenButton = (Button) quRenField.get(param.thisObject);
         quRenButton.performClick();
         }
    });

// hook获得二维码url的回调方法

XposedHelpers.findAndHookMethod("com.alipay.mobile.payee.ui.PayeeQRSetMoneyActivity", lpparam.classLoader, "a",          XposedHelpers.findClass("com.alipay.transferprod.rpc.result.ConsultSetAmountRes", lpparam.classLoader), new XC_MethodHook() {
  @Override
  protected void afterHookedMethod(MethodHookParam param) throws Throwable {
    Field moneyField = XposedHelpers.findField(param.thisObject.getClass(), "g");
    String money = (String) moneyField.get(param.thisObject);

    Field markField = XposedHelpers.findField(param.thisObject.getClass(), "c");
    Object markObject = markField.get(param.thisObject);
    String mark = (String) XposedHelpers.callMethod(markObject, "getUbbStr");

    Object consultSetAmountRes = param.args[0];
    Field consultField = XposedHelpers.findField(consultSetAmountRes.getClass(), "qrCodeUrl");
    String payUrl = (String) consultField.get(consultSetAmountRes);
    XposedBridge.log(money + "  " + mark + "  " + payUrl);
     }
    });
  }
}

这样就很容易的拿到我们自己设置支付宝金额与备注的收款码了。比如qrCodeUrl就是长这样:”https://qr.alipay.com/sldgjsdlgjio23o8hned9nd?t=1546998123456

Hook日志类(风险)

//这是重点强调:打印日志的逆向风险
Class<?> clazzLog = lpparam.classLoader.loadClass("com.alipay.mobile.verifyidentity.log.VerifyLogCat");
XposedHelpers.findAndHookMethod(clazzLog, "i", String.class, String.class, new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        super.beforeHookedMethod(param);
        XposedBridge.log("====VerifyLogCat==i==" + param.args[0] + "  " + param.args[1]);
    }
});

XposedHelpers.findAndHookMethod(clazzLog, "d", String.class, String.class, new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        super.beforeHookedMethod(param);
        XposedBridge.log("====VerifyLogCat==d==" + param.args[0] + "  " + param.args[1]);
    }
});

XposedHelpers.findAndHookMethod(clazzLog, "e", String.class, String.class, new XC_MethodHook() {
    @Override
    protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
        super.beforeHookedMethod(param);
        XposedBridge.log("====VerifyLogCat==e==" + param.args[0] + "  " + param.args[1]);
    }
});

这是重点强调风险:打印日志的逆向风险。随便打一下log,我们的app逻辑就很容易被屡出来。

社区文化

论坛:https://api.xposed.info

Xposed API:https://xposed.appkg.com/

Github:https://github.com/rovo89/Xposed.git

xda-developers(下载资源最好在这里哦):
https://forum.xda-developers.com/showthread.php?t=3034811

总结

工程源码Github:

https://github.com/donald99/XposedShare

Xposed太酷了。值得我们深入学习研究。

其实Xposed并没有想象中那么复杂,原理和相关的API都很简单,难的是逆向分析的过程,实现Hook:反编译后分析乱乱的代码,打日志调试输出堆栈信息,抓包等等,需要我们去分析很多未知的东西,不断猜测,不断尝试,折腾一番可能毫无进展,不过不要灰心,有耐心总会找到灵光一现的那一刻。另外研究之后,在开发我们的APP时,对安全威胁方面就会有意识避让。

作者:奇舞移动
链接:https://www.jianshu.com/p/5c0e3e220a2a
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

转载请注明:Android开发中文站 » Xposed为你开启一扇窗

您必须 登录 才能发表评论!