首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Xposed的检测和反制(上)

XPOSED

框架

检测和反制

之前看到有人发了关于使用xposed屏蔽抖音检测xposed的思路(https://www.52pojie.cn/thread-684757-1-1.html),贴出了部分伪代码,

但觉抖音写的蛮有意思的,自己对这方面也不是很清楚,毕竟Android我没怎么学习。借这个机会,了解一下。写的不是很清楚,大家多多抱哈啊!~~

整理了一下文档,我发现抖音主要使用了以下的手段检测xposed。

环境: win10 x64

使用的工具:apkdb & jeb 2.2.7

尝试加载xposed的类,如果能加载则表示已经安装了。

XposedHelpers类中存在fieldCache methodCache constructorCache 这三个静态成员,都是hashmap类型,凡是需要被hook的且已经被找到的对象都会被缓存到这三个map里面。

我们通过便利这三个map来找到相关hook信息。

备注:方法a是检测xposed到底改了什么东西存放到a中。抖音似乎会收集相关信息并上报

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;

}

检测xposed相关文件

检测XposedBridge.jar这个文件和de.robv.android.xposed.XposedBridge

XposedBridge.jar存放在framework里面,de.robv.android.xposed.XposedBridge是开发xposed框架使用的主要接口。

在这个方法里读取了maps这个文件,在linux内核中,这个文件存储了进程映射了的内存区域和访问权限。在这里我们可以看到这个进程加载了那些文件。

如果进程加载了xposed相关的so库或者jar则表示xposed框架已注入。

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;

}

检测堆栈信息

如果你的手机安装了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调用

try {

throw new Exception("");

} catch (Exception localException) {

StackTraceElement[] arrayOfStackTraceElement = localException.getStackTrace();

int m = arrayOfStackTraceElement.length;

int i = 0;

int j;

// 遍历整个堆栈查询xposed相关信息 检测 ZygoteInit 是否出现了2次

for (int k = 0; i

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

if (arrayOfStackTraceElement[i].getClassName()

.equals("de.robv.android.xposed.XposedBridge")) {

bool1 = true;

}

} else {

return bool1;

}

i += 1;

}

修改hook方法的查询结果

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

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 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

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;

}

检测方法是否被篡改

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

向上滑动阅览

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;

}

检测包名

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

if (((ApplicationInfo)localObject).packageName.equals("de.robv.android.xposed.installer"))

{

Log.wtf("HookDetection", "Xposed found on the system.");

}

}

反制Xposed

反射重写xposed设置,直接禁用

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

这个方法是酷安里中抄来的。重写application,在onCreate中写入

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) {

}

未完续待...

作者:lbzz

界世的你当不

只作你的肩膀

一LIGHT一

Fearless Sun

IT世界第五期

生活不暖 但一定要有太阳

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180312G1VNGE00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券