吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 81196|回复: 145
收起左侧

[Android 原创] Xposed那些事儿 -- xposed框架的检测和反制

    [复制链接]
楠楠熊 发表于 2018-1-26 00:25
本帖最后由 楠楠熊 于 2018-1-26 11:03 编辑

之前看到有人发了关于使用xposed屏蔽抖音检测xposed的思路(https://www.52pojie.cn/thread-684757-1-1.html),贴出了部分伪代码,
但觉抖音写的蛮有意思的,自己对这方面也不是很清楚,毕竟Android我没怎么学习。借这个机会,了解一下。写的不是很清楚,大家多多抱哈啊!~~



环境:      win10 x64
使用的工具:apkdb & jeb 2.2.7


1.尝试加载xposed的类,如果能加载则表示已经安装了。
XposedHelpers类中存在fieldCache methodCache constructorCache 这三个静态成员,都是hashmap类型,凡是需要被hook的且已经被找到的对象都会被缓存到这三个map里面。
我们通过便利这三个map来找到相关hook信息。
备注:方法a是检测xposed到底改了什么东西存放到a中。抖音似乎会收集相关信息并上报。

[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
  public void b()
{
    try
    {
        Object localObject = ClassLoader.getSystemClassLoader()
                .loadClass("de.robv.android.xposed.XposedHelpers").newInstance();
        // 如果加载类失败 则表示当前环境没有xposed
        if (localObject != null)
        {
            a(localObject, "fieldCache");
            a(localObject, "methodCache");
            a(localObject, "constructorCache");
        }
        return;
    }
    catch (Throwable localThrowable) {}
}
 
private void a(Object arg5, String arg6) {
    try {
        // 从XposedHelpers中读取相关的hook信息
        Field v0_1 = arg5.getClass().getDeclaredField(arg6);
        v0_1.setAccessible(true);
        Set v0_2 = v0_1.get(arg5).keySet();
        if(v0_2 == null) {
            return;
        }
        if(v0_2.isEmpty()) {
            return;
        }
        Iterator v1 = v0_2.iterator();
        // 排除无关紧要的类
        while(v1.hasNext()) {
            Object v0_3 = v1.next();
            if(v0_3 == null) {
                continue;
            }
            if(((String)v0_3).length() <= 0) {
                continue;
            }
            if(((String)v0_3).toLowerCase().startsWith("android.support")) {
                continue;
            }
            if(((String)v0_3).toLowerCase().startsWith("javax.")) {
                continue;
            }
            if(((String)v0_3).toLowerCase().startsWith("android.webkit")) {
                continue;
            }
            if(((String)v0_3).toLowerCase().startsWith("java.util")) {
                continue;
            }
            if(((String)v0_3).toLowerCase().startsWith("android.widget")) {
                continue;
            }
            if(((String)v0_3).toLowerCase().startsWith("sun.")) {
                continue;
            }
            this.a.add(v0_3);
        }
    }
    catch(Throwable v0) {
        v0.printStackTrace();
    }
}


2.检测xposed相关文件

检测XposedBridge.jar这个文件和de.robv.android.xposed.XposedBridge
XposedBridge.jar存放在framework里面,de.robv.android.xposed.XposedBridge是开发xposed框架使用的主要接口。
在这个方法里读取了maps这个文件,在linux内核中,这个文件存储了进程映射了的内存区域和访问权限。在这里我们可以看到这个进程加载了那些文件。
如果进程加载了xposed相关的so库或者jar则表示xposed框架已注入。
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public static boolean a(String paramString)
  {
    try
    {
      Object localObject = new HashSet();
       // 读取maps文件信息
      BufferedReader localBufferedReader =
                new BufferedReader(new FileReader("/proc/" + Process.myPid() + "/maps"));
       // 遍历查询关键词 反编译出来的代码可能不太准确
      for (;;)
      {
        String str = localBufferedReader.readLine();
        if (str == null) {
          break;
        }
        if ((str.endsWith(".so")) || (str.endsWith(".jar"))) {
          ((Set)localObject).add(str.substring(str.lastIndexOf(" ") + 1));
        }
      }
      localBufferedReader.close();
      localObject = ((Set)localObject).iterator();
      while (((Iterator)localObject).hasNext())
      {
        boolean bool = ((String)((Iterator)localObject).next()).contains(paramString);
        if (bool) {
          return true;
        }
      }
    }
    catch (Exception paramString) {}
    return false;
  }



3.检测方法的调用栈
如果你的手机安装了xposed框架,那么你在查看app崩溃时候的堆栈信息,一定能在顶层找到xposed的类信息,
既然xposed想改你的信息,那么在调用栈里面肯定是有它的身影的。比如出现de.robv.android.xposed.XposedBridge这个类,方法被hook的时候调用栈里会出现de.robv.android.xposed.XposedBridge.handleHookedMethod 和de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative这些xposed的方法,在dalvik.system.NativeStart.main方法后出现de.robv.android.xposed.XposedBridge.main调用
[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
try {
        throw new Exception("");
    } catch (Exception localException) {
        StackTraceElement[] arrayOfStackTraceElement = localException.getStackTrace();
        int m = arrayOfStackTraceElement.length;
        int i = 0;
        int j;
        // 遍历整个堆栈查询xposed相关信息
        for (int k = 0; i < m; k = j) {
            StackTraceElement localStackTraceElement = arrayOfStackTraceElement[i];
            j = k;
            if (localStackTraceElement.getClassName()
                    .equals("com.android.internal.os.ZygoteInit")) {
                k += 1;
                j = k;
                if (k == 2) {
                    return true;
                }
            }
            if (localStackTraceElement.getClassName().equals(e)) {
                return true;
            }
            i += 1;
        }
    }
    return false;
}
 
  try
 
{
    throw new Exception("");
}
catch(
Exception localException)
 
{
    arrayOfStackTraceElement = localException.getStackTrace();
    j = arrayOfStackTraceElement.length;
    i = 0;
}
for(;;)
 
{
    boolean bool1 = bool2;
    if (i < j) {
        if (arrayOfStackTraceElement[i].getClassName()
                .equals("de.robv.android.xposed.XposedBridge")) {
            bool1 = true;
        }
    } else {
        return bool1;
    }
    i += 1;
}

4.修改hook方法的查询结果
   数组c包含了抖音里比较重要的及各类, this.a指的是检测出的被修改的方法,字段。他执行了两者的匹配,将结果存放到了一个JSONObject里面,里面包含了是否使用模拟器,系统的详细信息,是否是双开xpp,是否适用了xp,hook了那些方法等信息上报到https://xlog.snssdk.com/do/y?ver=0.4&ts=

[HTML] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
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
private String[] c = {"android.os.Build#SERIAL",
        "android.os.Build#PRODUCT",
        "android.os.Build#DEVICE",
        "android.os.Build#FINGERPRINT",
        "android.os.Build#MODEL",
        "android.os.Build#BOARD",
        "android.os.Build#BRAND",
        "android.os.Build.BOOTLOADER",
        "android.os.Build#HARDWARE",
        "android.os.SystemProperties#get(java.lang.String,java.lang.String)",
        "android.os.SystemProperties#get(java.lang.String)",
        "java.lang.System#getProperty(java.lang.String)",
        "android.telephony.TelephonyManager#getDeviceId()",
        "android.telephony.TelephonyManager#getSubscriberId()",
        "android.net.wifi.WifiInfo#getMacAddress()",
        "android.os.Debug#isDebuggerConnected()",
        "android.app.activitymanager#isUserAMonkey()",
        "com.ss."};
 
 
public ArrayList<String> c() {
    ArrayList localArrayList = new ArrayList();
    Iterator localIterator = this.a.iterator();
    while (localIterator.hasNext()) {
        String str1 = (String) localIterator.next();
        String[] arrayOfString = this.c;
        int j = arrayOfString.length;
        int i = 0;
        while (i < j) {
            if (true == str1.startsWith(arrayOfString[i])) {
                String str2 = str1.replace(")#exact", ")").replace(")#bestmatch", ")").replace("#", ".");
                if (str2.length() > 0) {
                    localArrayList.add(str2);
                }
            }
            i += 1;
        }
    }
    return localArrayList;
}


5.检测方法是否被篡改
Modifier.isNative方法判断是否是native修饰的方法,xposedhook方法的时候,会把方法转位native方法,我们检测native方法中不该为native的方法来达到检测的目的,比如getDeviceId,getMacAddress这些方法如果是native则表示已经被篡改了。


[Java] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
public static boolean a(String paramString1, String paramString2, Class... paramVarArgs)
  {
    try
    {
      // 判断方法是不是用native修饰的
      boolean bool = Modifier.isNative(Class.forName(paramString1)
                   .getDeclaredMethod(paramString2, paramVarArgs).getModifiers());
      if (bool) {
        return true;
      }
    }
    catch (Exception paramString1)
    {
      paramString1.printStackTrace();
    }
    return false;
  }

6.检测包名
   这个是最简单也是最不靠谱的方法,因为只要禁止app读取应用列表就没办法了。

[Java] 纯文本查看 复制代码
1
2
3
4
5
if (((ApplicationInfo)localObject).packageName.equals("de.robv.android.xposed.installer"))
     {
       Log.wtf("HookDetection", "Xposed found on the system.");
     }
 }

  
        
        
反制xposed

1.通过反射重写xposed设置,直接禁用

这个方法是酷安里中抄来的。重写application,在onCreate中写入
  
[Java] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
9
try {
      Field v0_1 = ClassLoader.getSystemClassLoader()
                  .loadClass("de.robv.android.xposed.XposedBridge")
                  .getDeclaredField("disableHooks");
      v0_1.setAccessible(true);
      v0_1.set(null, Boolean.valueOf(true));
  }
    catch(Throwable v0) {
  }


未完待续。。。
  
博客发布页
https://blog.coderstory.cn/about-xposed/

免费评分

参与人数 39吾爱币 +35 热心值 +36 收起 理由
Smartisan666 + 1 + 1 热心回复!
zzzlucas + 1 + 1 谢谢@Thanks!
在下风铃 + 1 + 1 我很赞同!
慕冬 + 1 谢谢@Thanks!
审判者压缩 + 1 + 1 热心回复!
茂名市第四中学 + 1 + 1 谢谢@Thanks!
寂寞-孤独i + 1 用心讨论,共获提升!
lt666123 + 1 + 1 热心回复!
su253 + 1 + 1 我很赞同!
zfujian + 1 + 1 热心回复!
弦歌醉月 + 1 + 1 虽不懂但觉技
你压到我头发了 + 1 + 1 &amp;lt;font style=&amp;quot;vertical-align: inherit;&amp;quot;&amp;gt;&amp;lt;font style=
Nickdlk + 1 谢谢@Thanks!
wushaominkk + 1 用心讨论,共获提升!
Onlookers_汐颜 + 1 + 1 用心讨论,共获提升!
yyyl + 1 谢谢@Thanks!
测试中…… + 1 + 1 我很赞同!
Andy0214 + 1 + 1 用心讨论,共获提升!
SomnusXZY + 1 + 1 热心回复!
qwqwqe + 1 + 1 谢谢@Thanks!
大毛孩 + 1 + 1 虽然不懂,但是玩XP的都是大神
王长生 + 1 + 1 用心讨论,共获提升!
Dreamboy_w + 1 + 1 用心讨论,共获提升!
破解project + 1 + 1 鼓励转贴优秀软件安全工具和文档!
zhh4827 + 1 + 1 热心回复!
chenjingyes + 1 + 1 谢谢@Thanks!
海底总动员 + 1 谢谢@Thanks!
WeBareBears + 1 + 1 用心讨论,共获提升!
skdxg + 1 + 1 热心回复!
云幻灭 + 1 + 1 谢谢@Thanks!
乌巢禅师 + 1 + 1 谢谢@Thanks!
snccwt + 1 + 1 谢谢@Thanks!
戏言19 + 1 + 1 用心讨论,共获提升!
伍丫i倨仕 + 1 + 1 多hook一下检测的方法咯
SharsDela + 1 + 1 用心讨论,共获提升!
zhangjianfei + 1 + 1 我很赞同!
zz0147 + 1 + 1 支持一下,在Windows从来没有认真用过hook,Android下感觉xp好方便
未来待我闯 + 1 热心回复!
dwq308 + 1 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

yege0201 发表于 2018-2-3 15:18
很久以前在测试某移动App的时候发现不能再模拟器上运行,当时App用了某梆的壳儿,以为是检测了模拟器的缘故,于是换成了真机测试机,发现也不能运行。再后来新建了一个模拟器就可以运行了,就猜测是检测了Xposed和Cydia。
于是果然在壳儿的so文件中找到了相关代码,方法就是检查自身的maps里面是否存在了Xposed和Cydia的一些关键字。因为so是c写的,所以就用cydia写了个hook插件,把fopen hook掉返回干净的maps绕过。
现在很少研究移动App了,不知道已经有这么多的检测方法了,学习~
genius_j 发表于 2018-2-6 00:08
zpp0196 发表于 2018-1-26 00:43
尼霸Rc_ 发表于 2018-1-26 00:46 来自手机
给狗群主打call
殺無道 发表于 2018-1-26 00:53 来自手机
膜拜大神
psp7456 发表于 2018-1-26 07:31 来自手机
不错,学习了!
netxboy 发表于 2018-1-26 08:46
.....................


抖音为啥不让用框架? 能改它什么功能?
zjls9933 发表于 2018-1-26 09:04
楼主求个XT1570的框架  可以不
trhaha 发表于 2018-1-26 09:22
支持技术讨论帖
卞杰森 发表于 2018-1-26 09:25
不是XP的粉,不过XP还是有很大实际作用的
shijielaoren 发表于 2018-1-26 09:42
用心讨论,共获提升.感谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-20 04:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表