为了账号安全,请及时绑定邮箱和手机立即绑定

装X指南之通过 VirtualApp 实现免 Root 权限 Hook

标签:
Java

一、前言

之前写的 「装X指南之Xposed安装与配置」,有人反馈手机 root 风险较大,而且操作成本高,有没有什么方法是不需要 root 就能够实现 hook 的或者不需要 Xposed 也能玩起插件的?于是就有了这篇文章,离开 Xposed ,带你免 root 实现 hook!

二、VirtualApp

1、关于 VirtualApp 的介绍

VA目前被广泛应用于插件化开发、无感知热更新、自动化、多开等技术领域,但它决不仅限于此,Android本身就是一个极其开放的平台,免安装运行APK这一Feature打开了无限可能-----这都取决于您的想象力。

感谢 asLody 开源,据说他写这个项目才高二,佩服佩服~

  • VirtualApp 项目地址:

  1. https://github.com/asLody/VirtualApp

2、VirtualApp 的原理

VirtualApp 伪造了一套 framework 代码,实现所有在其进程启动的应用,都运行在一个虚拟空间(注:个人理解,如有错误,还请指出)。

  • VirtualApp 源码学习与原理分析

  1. https://blog.csdn.net/leif_/article/details/72420934

  2. https://blog.csdn.net/ganyao939543405/article/details/76146760

3、VirtualApp 使用问题

Github 上的代码,作者已经没有继续开源更新了,可以看到后续的所有修改,都在作者的商业版上操作,所以有可能在使用上会出现一些 bug

其实可以看到「商业版」,不管稳定性与兼容性,都做了很大的修复和改动,最重要的是,支持 Dalvik 和 Art 的 Java Hook( API 同 Xposed ),可惜在作者没有公开源码的情况下,我们个人不可能为了学习去购买「商业版」~

特别说明:作者明确指出,如果项目需要投入商业使用,请购买「商业版」。我们这里仅做技术学习使用

webp

商业版特性

4、VirtualHook 介绍

上文说到我们无法使用「商业版」的 VirtualApp ,来进行 Hook ,准确来说是作者没把 Hook 的 Api 公开。

下面我要介绍另一个基于 VirtualApp 改造的项目 —— VirtualHook(区分:VirtualAppVirtualHook 的区别,不要搞混了,后文使用 VirtualHook 来实践),感谢 rk700 开源 VirtualHook 与 YAHFA

1)VirtualHook 项目地址:
  1. https://github.com/rk700/VirtualHook

2)VirtualHook 构成:

VirtualHook is a tool for hooking application without root permission. It is based on two projects:

  • VirtualApp. It's a plugin framework which allows running applications in its virtual space.

  • YAHFA . It's a hook framework for ART which allows hooking Java method of the application.

3)VirtualHook 注入
  • 关键的地方,VirtualHook 修改 VirtualApp 的核心代码,提供 Hook 注入代码的窗口

  • 以下是在 VirtualApp 里面 VClienImpl 类注入的关键代码

    DexClassLoader dexClassLoader = new DexClassLoader(apkPath,
            VEnvironment.getDalvikCacheDirectory().getAbsolutePath(),
            libPath,
            appClassLoader);    // YAHFA do hook 
    HookMain.doHookDefault(dexClassLoader, appClassLoader);
public void findAndBackupAndHook(Class targetClass, String methodName,
String methodSig, Method hook, Method backup);

三、YAHFA

1、YAHFA 介绍

YAHFA(Yet Another Hook Framework for ART) 是基于 ART 的 Hook 框架,支持 Android 5.0 ~ 9.0 版本的 Java 方法的 Hook 与替代 。而 VirtualHook 则是靠 YAHFA 实现的免 Root Hook。

  • 来自看雪论坛:

  1. https://bbs.pediy.com/thread-216786.htm

  • YAHFA 项目地址:

  1. https://github.com/rk700/YAHFA

2、YAHFA 原理

我是看不太懂里面的原理,但是还是把别人的分析过程,贴出来给大家,希望看懂的朋友,不吝分享:

  • 写文的时候,好像作者的博客挂了,不过还是写上吧

http://rk700.github.io/2017/03/30/YAHFA-introduction/

  • csdn 一位博主分享的原理分析

https://blog.csdn.net/zhu929033262/article/details/74457324

3、YAHFA Hook

解释一下相关变量与方法:

  • className:指定要 hook 的类名

  • methodName:指定要 hook 的方法

  • methodSig:指定要 hook 的方法签名

  • hook():该方法是你 hook 方法需要处理的逻辑,这里执行 hook 相关操作

  • backup():是原方法的调用,一般不需要重写什么

1)普通方法

Log.e() 方法。代码如下:

public class Hook_Log_e {
    public static String className = "android.util.Log";    public static String methodName = "e";    public static String methodSig = "(Ljava/lang/String;Ljava/lang/String;)I";    public static int hook(String tag, String msg) {
        Log.w("YAHFA", "in Log.e(): "+tag+", "+msg);        return backup(tag, msg);
    }    public static int backup(String tag, String msg) {
        Log.w("YAHFA", "Log.e() should not be here");        return 1;
    }
}
2)静态方法

静态方法和静态差不多,区别就是,静态的方法在hook和origin的参数中,少一个 Object 的参数。如 URI.create() 方法。代码如下:

public class Hook_url {
    public static String className = "java.net.URI";    public static String methodName = "create";    public static String methodSig = "(Ljava/lang/String;)Ljava/net/URI;";    public static Object hook(String url)
    {        // 改变 url 的值
        url = "http://www.baidu.com";        return origin(url);
    } 
    public static Object origin(String url)
    {
        Log.w("YAHFA", "String.startsWith() should not be here");        return url;
    }
}
3)匿名内部类

内部类只是编译时的概念,一旦编译成功,就会出现两个不同的类,例如,类outClass中有个intClass,那么编译后就出现一个名为outClass.class和一个outClass$intClass.class的类。所以className中就要指定类路径为a.b.c.outClass$intClass

4、获取方法的签名描述符

1)方法签名描述符组成,括号内是参数的签名,括号外是返回值的签名:
如 Log.e() 里面的方法:
    public static int e(String tag, String msg)
对应
    (Ljava/lang/String;Ljava/lang/String;)I
2)各类型参照表
  • 除了 boolean 和 long 类型分别是 Z 和 J 外,其他的描述符对应的都是 Java 类型名的大写首字母。另外,void 的描述符为 V

File DesciptorJava Language Type
Zboolean
Bbyte
Cchar
Sshort
Iint
Jlong
Ffloat
Ddouble
Vvoid
[array
L + 类型描符 + ;引用类型
  • 说明:

  1. 数组用 [ 表示,二维数组 [[ 表示。如: [Ljava/lang/String; 对应 String[],
    [[Ljava/lang/Object; 对应 Object[][]

  2. 引用类型注意前面的 L , “/” 分割和 “;” ,不要遗漏了。如:Lcom/tencent/wcdb/Cursor;

  3. String 是对象,所以是:Ljava/lang/String;

  4. 还是不知道怎么写的话,可以通过以下 adb 命令找到方法签名描述符:

1. 查看 Java 类的方式  javap -s java.awt.Label
2. 查看 Android 类的方式  javap -s -bootclasspath "D:\Program Files\Android\android-sdk\platforms\android-25\android.jar" -classpath bin/classes android.app.Activity
3. 查看第三方 Jar 的类的方式 javap -s  -classpath "D:\AMap_Location.jar" com.amap.api.location.AMapLocation

四、VirtualHook 搭配 YAHFA 使用教程

我们这里是使用 VirtualHook 来实践 。总体步骤如下:

  1. git clone VirtualHook 工程或者下载源码

  2. 新建 module 并配置为插件

  3. module 打包成 apk,并放到手机里面

  4. VirtualHook 里面,克隆目标 App 和加载插件 apk

项目目录结构如下:

webp

项目目录结构

  • applibVirtualApp 相关代码

  • YAHFAHook 框架代码

  • demoHookPlugin 是插件 module

1、配置插件 module

配置插件 moduleAndroidManifest.xml 的  meta-data 的值,设置 valuetrue

<application
    android:label="@string/app_name">    <meta-data
        android:name="yahfa.hook.plugin"
        android:value="true"
    /></application>

2、配置 Hook 类

假如我们需要 Hook 处理 Log.e() 方法,新建一个 Hook_Log_e 类,并在 lab.galaxy.yahfa.HookInfo 配置(不配置的话,hook 不生效),代码如下:

public class HookInfo {
    public static String[] hookItemNames = {           "lab.galaxy.yahfa.demoPlugin.Hook_Log_e",
    };
}

注意:HookInfo 类的包名,如果需要改的话,要同时改 HookMain.doHookDefault() 方法里面的包名。

public static void doHookDefault(ClassLoader patchClassLoader, ClassLoader originClassLoader) {    try {
        Class<?> hookInfoClass = Class.forName("lab.galaxy.yahfa.HookInfo", true, patchClassLoader);        String[] hookItemNames = (String[])hookInfoClass.getField("hookItemNames").get(null);        for(String hookItemName : hookItemNames) {
            doHookItemDefault(patchClassLoader, hookItemName, originClassLoader);
        }
        hookInfoClasses.add(hookInfoClass);
    }    catch (Exception e) {
        e.printStackTrace();
    }
}

3、验证结果

  • 这里我写了个 hook 微信启动页的 onCreate() 方法。

public class Hook_Wx_Launcher {
    public static String className = "com.tencent.mm.ui.LauncherUI";    public static String methodName = "onCreate";    public static String methodSig = "(Landroid/os/Bundle;)V";    public static Activity LauncherUi;    public static void hook(Object thiz, Bundle b) {
        Log.w("czc", "LauncherUI oncreate");        return "";
    }    public static void backup(Object thiz, Bundle b) {
        Log.w("YAHFA", "LauncherUI backup");        return;
    }
}
  • 安装打包好的插件apk,插件左上有个小图标,以作区别,同时克隆 微信 到 VirtualHook 里面

webp

插件


webp

安装

  • hook 成功打印出 log


    webp

    Hook_Wx_Launcher



作者:幕后眼光
链接:https://www.jianshu.com/p/865300d4d6f9


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消