首页
论坛
课程
招聘
[程序开发] [源码分析] [HOOK注入] [逆向分析] FakeXposed最强屏蔽Xposed、Root检测,自定义maps、文件重定向等支持Android5~11
2021-2-22 10:42 6019

[程序开发] [源码分析] [HOOK注入] [逆向分析] FakeXposed最强屏蔽Xposed、Root检测,自定义maps、文件重定向等支持Android5~11

2021-2-22 10:42
6019

FakeXposed

一个通用多功能的 Xposed 隐藏器,采用 NativeJava 结合来做到双向屏蔽检测,提供高度自由化为每个应用配置不同属性。它不仅仅局限于屏蔽 Xposed 检测,还提供更多更加高级的功能,如 maps 文件自定义屏蔽各种检测、完整的文件重定向功能、访问权限控制、JNI 方法监控、动态符号查找屏蔽 dlsym 等等,还可以提供给其它模块在进程内动态添加或修改配置。开源地址 https://github.com/sanfengAndroid/FakeXposed 目前问题还较多不够稳定,欢迎加群讨论

原理简要介绍

  • Native Hook 使用我的另一开源项目 fake-linkerJava Hook 使用 Xposed 框架,大部分功能都是由 Native Hook 来完成,Xposed 不限于原版 XposedEdXposedVirtualXposed等等
  • 内部提供 堆栈类应用环境变量全局系统属性Android Global属性Runtime.exec拦截文件访问/重定向等符号拦截,各种属性的隐藏和修改,下面我将简单介绍一些原理,代码都是基于 Android 最新源码主分支,旧分支一些变化不是太大自行分析即可

类/堆栈类隐藏

  • Hook Class.forName()ClassLoader.loadClass()Throwable.getStackTrace() 方法,判断隐藏类加载则抛出异常或删除该元素。目前我在测试 EdXposed 中只有部分情况会走该回调,可能框架处理了有关部分

应用/组件隐藏

  • 使用动态代理 PackageManagerActivityManagerActivityTaskManager屏蔽常见会使用到获取其它应用属性的方法,如:getInstalledPackagesgetInstalledApplicationsgetRunningServicesgetTasks等等。应用进程本身就是通过 Bindersystem_server 服务进程通信进程内只存在一个 IBinger 对象,因此非常适合使用动态代理,这里屏蔽掉几乎所有能够访问其它应用的方式,具体查看源码HookSystemComponent
  • PackageManager 源码在 ActivityThread.getPackageManager
    1
    2
    3
    4
    5
    6
    7
    8
    9
    static volatile IPackageManager sPackageManager;
    public static IPackageManager getPackageManager() {
      if (sPackageManager != null) {
          return sPackageManager;
      }
      final IBinder b = ServiceManager.getService("package");
      sPackageManager = IPackageManager.Stub.asInterface(b);
      return sPackageManager;
    }
    因此只需要使用反射修改 sPackageManager 静态变量即可
  • ActivityManager 源码 AndroidO 以上在 ActivityManager.IActivityManagerSingletonAndroidO 以下在 ActivityManagerNative.gDefault,都是一个单例对象
    1
    2
    3
    4
    5
    6
    7
    8
    9
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
      new Singleton<IActivityManager>() {
          @Override
          protected IActivityManager create() {
              final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
              final IActivityManager am = IActivityManager.Stub.asInterface(b);
              return am;
          }
      };
    同样反射修改 Singleton 里面的对象即可
  • ActivityTaskManagerAndroidQ 以上新增的一个服务,修改方法同 ActivityManager

环境变量修改

  • Java 调用 System.getenv()System.getenv(String) 源码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public static java.util.Map<String,String> getenv() {
      SecurityManager sm = getSecurityManager();
      if (sm != null) {
          sm.checkPermission(new RuntimePermission("getenv.*"));
      }
     
      return ProcessEnvironment.getenv();
    }
    public static String getenv(String name) {
      if (name == null) {
          throw new NullPointerException("name == null");
      }
     
      return Libcore.os.getenv(name);
    }

    其最终调用两个函数 Libcore.os.environ()Libcore.os.getenv(String)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public final class Libcore {
      private Libcore() { }
      public static final Os rawOs = new Linux();
      public static volatile Os os = new BlockGuardOs(rawOs);
      ...
    }
     
    public final class Linux implements Os {
      Linux() { }
      public native String getenv(String name);
      public native String[] environ();
      ...
    }

    不同版本 Libcore.os 的实现对象类名不一样,但是区别很小,而 native 中访问到是 libc 导出变量 environ、导出函数 getenv,因此通过 Native Hook 拦截 getenv 函数即可拦截对应 Java System.getenv(String)调用,而 System.getenv() 调用是直接使用 environ 变量,因此暂时采用Java Hook替换该Map对象,通常情况下应用是很少使用到 System.getenv 非系统环境变量的,一些软件检测才会使用,因此后续可能会直接修改 environ 变量中的值

全局属性 SystemProperties 修改

  • Java 反射使用 SystemProperties.get 系列方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @NonNull
    @SystemApi
    public static String get(@NonNull String key, @Nullable String def) {
        if (TRACK_KEY_ACCESS) onKeyAccess(key);
        return native_get(key, def);
    }
    ...
    @FastNative
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
    private static native String native_get(String key, String def);

    调用 android_os_SystemProperties.cpp 中的方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    template<typename Functor>
    void ReadProperty(const prop_info* prop, Functor&& functor)
    {
    #if defined(__BIONIC__)
        auto thunk = [](void* cookie,
                        const char* /*name*/,
                        const char* value,
                        uint32_t /*serial*/) {
            std::forward<Functor>(*static_cast<Functor*>(cookie))(value);
        };
        __system_property_read_callback(prop, thunk, &functor);
    #else
        LOG(FATAL) << "fast property access supported only on device";
    #endif
    }
     
    template<typename Functor>
    void ReadProperty(JNIEnv* env, jstring keyJ, Functor&& functor)
    {
        ScopedUtfChars key(env, keyJ);
        if (!key.c_str()) {
            return;
        }
    #if defined(__BIONIC__)
        const prop_info* prop = __system_property_find(key.c_str());
        if (!prop) {
            return;
        }
        ReadProperty(prop, std::forward<Functor>(functor));
    #else
        std::forward<Functor>(functor)(
            android::base::GetProperty(key.c_str(), "").c_str());
    #endif
    }
     
    jstring SystemProperties_getSS(JNIEnv* env, jclass clazz, jstring keyJ,
                                 jstring defJ)
    {
        jstring ret = defJ;
        ReadProperty(env, keyJ, [&](const char* value) {
            if (value[0]) {
                ret = env->NewStringUTF(value);
            }
        });
        if (ret == nullptr && !env->ExceptionCheck()) {
          ret = env->NewStringUTF("");  // Legacy behavior
        }
        return ret;
    }
     
    int register_android_os_SystemProperties(JNIEnv *env)
    {
        const JNINativeMethod method_table[] = {
            { "native_get",
              "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
              (void*) SystemProperties_getSS },
            { "native_get_int", "(Ljava/lang/String;I)I",
              (void*) SystemProperties_get_integral<jint> },
            { "native_get_long", "(Ljava/lang/String;J)J",
              (void*) SystemProperties_get_integral<jlong> },
            { "native_get_boolean", "(Ljava/lang/String;Z)Z",
              (void*) SystemProperties_get_boolean },
            { "native_find",
              "(Ljava/lang/String;)J",
              (void*) SystemProperties_find },
            { "native_get",
              "(J)Ljava/lang/String;",
              (void*) SystemProperties_getH },
            { "native_get_int", "(JI)I",
              (void*) SystemProperties_get_integralH<jint> },
            { "native_get_long", "(JJ)J",
              (void*) SystemProperties_get_integralH<jlong> },
            { "native_get_boolean", "(JZ)Z",
              (void*) SystemProperties_get_booleanH },
            { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
              (void*) SystemProperties_set },
            { "native_add_change_callback", "()V",
              (void*) SystemProperties_add_change_callback },
            { "native_report_sysprop_change", "()V",
              (void*) SystemProperties_report_sysprop_change },
        };
        return RegisterMethodsOrDie(env, "android/os/SystemProperties",
                                    method_table, NELEM(method_table));
    }

    而它调用了 libc.so 中的 __system_property_find__system_property_read_callback,在低版本中获取属性也使用到了 __system_property_get 方法,因此采用 Native Hook 以上这三个方法,这里也要注意不同版本在不同动态库中实现

Android Global 属性修改

  • 采用 Java Hook Global.getString 方法修改

Runtime.exec 拦截

  • 内容太长,查看 原帖

文件重定向/访问控制(核心)

  • 文件重定向/黑名单:Native Hook 与 IO 有关的方法,由于我们使用的 PLT Hook 因此要尽可能的包含全部函数
    • openat__openatopenfopenlibc 函数,Java 中的 File 使用调用到 Libcore.os 中,这与上面分析环境变量类似,因此只需要 Hook libc 中的 IO 函数即可,查看代码hook_io
    • syscall 函数,自己实现 软中断系统调用 的无法拦截,其 inline Hook 框架也无法拦截,只能通过修改内核或动态查找 软中断系统调用 然后再 Hook,这种极个别情况忽略,查看代码 hook_syscall
    • exec 簇执行函数,它会传入可执行文件路径,也需要重定向,查看代码 hook_exec
    • 与时间相关函数 utimesutimelutimes,查看代码 hook_time
    • 与文件访问路径相关函数 chdirlinkat等,查看代码 hook_unistd
    • 与文件状态相关函数 fchmodatfstatatstat等,查看代码 hook_stat
    • maps 文件过滤,基于文件重定向,当要访问 maps 文件时将修改掉需要过滤的数据然后将它重定向到缓存路径,查看代码 io_redirect
    • 动态加载函数 dlopenandroid_dlopen_ext,查看代码 hook_dlfcn
  • 文件权限控制
    • stat fstatataccess 等函数,查看代码 hook_stat

符号隐藏

  • Native Hook dlsym 函数,屏蔽一些符号查找和重定向 libc 库中的函数到 Hook 模块 中,查看代码 hook_dlfcn

系统共享库查找

  • 内容较长,查看 原帖
  1. 根据代码位置猜测,或者直接在 maps 文件里面查找哪些已经加载的可疑的库,目前查找到系统有关的库包含如下几个

    • libjavacore.so 与文件重定向、文件状态、exec 执行有关
    • libnativehelper.so 与动态加载有关
    • libnativeloader.so Android 7 以上动态加载有关
    • libart.so 与文件重定向、动态加载有关
    • libopenjdk.so 与文件重定向、文件状态有关
    • libopenjdkjvm.so 与文件访问有关
    • libandroid_runtime.so 与文件访问有关
    • libcutils.so 与 SystemProperties 访问有关
  2. 如果有遗漏的库可以调用 NativeHook.relinkLibrary() 重新重定位该库

其它模块调用

查看 FakeXposed 说明文档

软件使用截图

  • 软件状态 ![home](
  • 应用配置,长按开启/关闭 package_configuration
  • 应用配置,长按开启/关闭 ![package_configuration](
  • 应用配置,长按开启/关闭 package_configuration
  • 对应功能配置 ![package_hidden](
  • 应用配置,长按开启/关闭 package_configuration ![dlsym_hidden](
  • 应用配置,长按开启/关闭 package_configuration

[公告]名企招聘!

最后于 2021-2-23 12:48 被北辰制作编辑 ,原因: 添加问题说明
收藏
点赞15
打赏
分享
最新回复 (27)
雪    币: 202
活跃值: 活跃值 (66)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
pkiot 活跃值 2021-2-22 17:53
2
0
坏蛋
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_xxggzthx 活跃值 2021-2-22 18:57
3
0
太强了,火钳刘明
雪    币: 387
活跃值: 活跃值 (405)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
_air 活跃值 2021-2-23 00:17
4
0
牛批  感谢分享  respect
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
万里星河 活跃值 2021-2-23 02:33
5
0
支持一下
雪    币: 261
活跃值: 活跃值 (146)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
乐不思蜀1 活跃值 2021-2-23 09:10
6
0
厉害 支持
雪    币: 2364
活跃值: 活跃值 (9240)
能力值: ( LV9,RANK:166 )
在线值:
发帖
回帖
粉丝
0x指纹 活跃值 3 2021-2-23 09:29
7
0
感谢分享 赞
雪    币: 1842
活跃值: 活跃值 (791)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
virjar 活跃值 1 2021-2-23 11:03
8
0
这才是真的强,老板多放点儿这种有料的东西出来啊
雪    币: 516
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
ST0n5 活跃值 2021-2-23 11:06
9
0
支持 太赞了
雪    币: 2965
活跃值: 活跃值 (1249)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
dayday向上8 活跃值 2 2021-2-23 11:43
10
0
道行太浅,只能瑞斯拜
雪    币: 391
活跃值: 活跃值 (88)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
林雪 活跃值 2021-2-23 16:20
11
0
道行太浅,只能瑞斯拜
雪    币: 1263
活跃值: 活跃值 (66)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mb_udcjdwum 活跃值 2021-2-23 17:15
12
0
太强了吧,大佬,支持一下!有成品就更好啦,小白一枚!
雪    币: 682
活跃值: 活跃值 (2302)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
supperlitt 活跃值 2021-2-23 17:33
13
0
666666666
雪    币: 705
活跃值: 活跃值 (518)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
TUGOhost 活跃值 2021-2-23 20:06
14
0
想知道fake-linker的具体实现原理,或者能够给点相关文档博客之类的吗?
雪    币: 1555
活跃值: 活跃值 (801)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
北辰制作 活跃值 2021-2-23 20:36
15
0
https://sanfengandroid.github.io/2021/01/10/modify-linker-to-implement-plt-hook/   fake-linker的实现原理,github上面也有链接
雪    币: 236
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
逆向小白白 活跃值 2021-2-23 23:39
16
0
优秀
雪    币: 1923
活跃值: 活跃值 (173)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
VNRKDOEA 活跃值 2021-2-24 08:47
17
0
火钳留名
雪    币: 820
活跃值: 活跃值 (693)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lhxdiao 活跃值 2021-2-24 14:58
18
0
不错
雪    币: 1493
活跃值: 活跃值 (410)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 2021-2-25 11:00
19
0
牛批
雪    币: 5826
活跃值: 活跃值 (739)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
黑洛 活跃值 1 2021-2-25 15:19
20
0
支持
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
anliou 活跃值 2021-2-27 11:18
21
0
我这里把大神的项目编译成了 成品   
https://download.csdn.net/download/weixin_45691961/15485774
雪    币: 4
活跃值: 活跃值 (101)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
noahsu 活跃值 6天前
22
0
厉害
雪    币: 89
活跃值: 活跃值 (244)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
香风一族 活跃值 6天前
23
0
牛逼、牛逼、太牛逼
雪    币: 209
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
冒险岛mxd 活跃值 5天前
24
0
牛逼 留个脚印
雪    币: 53
活跃值: 活跃值 (585)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
番茄西瓜汤 活跃值 2天前
25
0
太极好像适配不上,不支持还
游客
登录 | 注册 方可回帖
返回