0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Android App环境检测分析

哆啦安全 来源:哆啦安全 2023-12-01 10:26 次阅读

1.检测是否调试APP

这个原理就是APP的AndroidManifest.xml文件中application是否配置了android:debuggable="true",设置true支持动态调试

public static boolean isAppDebuggable(Context context) {
    return (context.getApplicationInfo().flags & 2) != 0;
}

检测当前APP是否被动态调试中

public static boolean isDebuggerAttached() {
    return Debug.isDebuggerConnected() || Debug.waitingForDebugger();
}

2.检测是否模拟

这里获取了Android id,如果Android id是null,就是模拟器?如果包含GOLDFISH字符串也属于模拟器

public static boolean isEmulator(Context context) {
    return Build.PRODUCT.contains(SDK) || Build.HARDWARE.contains(GOLDFISH) || Build.HARDWARE.contains(RANCHU) || Settings.Secure.getString(context.getContentResolver(), "android_id") == null;
}

3.Root检测

检测系统的tags是不是test-keys。

检测是不是安装了supersu的APP,检测su文件是否存在。

public static boolean isRooted(Context context) {
        boolean isEmulator = isEmulator(context);
        String str = Build.TAGS;
        if ((isEmulator || str == null || !str.contains("test-keys")) && !new File("/system/app/Superuser.apk").exists()) {
            return !isEmulator && new File("/system/xbin/su").exists();
        }
        return true;
}

判断一些root的APP是否安装

private final boolean a(List list) {
        PackageManager packageManager = this.b.getPackageManager();
        boolean z = false;
        for (String str : list) {
            try {
                packageManager.getPackageInfo(str, 0);
                C0339Io.h.e(str + " ROOT management app detected!");
                z = true;
            } catch (PackageManager.NameNotFoundException unused) {
            }
        }
        return z;
}

通过which su寻找su文件

public final boolean f() {
        /*
            r5 = this;
            r0 = 0
            r1 = 0
            java.lang.Runtime r2 = java.lang.Runtime.getRuntime()     // Catch: java.lang.Throwable -> L2f
            java.lang.String r3 = "which"
            java.lang.String r4 = "su"
            java.lang.String[] r3 = new java.lang.String[]{r3, r4}     // Catch: java.lang.Throwable -> L2f
            java.lang.Process r1 = r2.exec(r3)     // Catch: java.lang.Throwable -> L2f
            java.io.BufferedReader r2 = new java.io.BufferedReader     // Catch: java.lang.Throwable -> L2f
            java.io.InputStreamReader r3 = new java.io.InputStreamReader     // Catch: java.lang.Throwable -> L2f
            java.io.InputStream r4 = r1.getInputStream()     // Catch: java.lang.Throwable -> L2f
            r3.(r4)     // Catch: java.lang.Throwable -> L2f
            java.io.Reader r3 = (java.io.Reader) r3     // Catch: java.lang.Throwable -> L2f
            r2.(r3)     // Catch: java.lang.Throwable -> L2f
            java.lang.String r2 = r2.readLine()     // Catch: java.lang.Throwable -> L2f
            if (r2 == 0) goto L29
            r0 = 1
        L29:
            if (r1 == 0) goto L32
        L2b:
            r1.destroy()
            goto L32
        L2f:
            if (r1 == 0) goto L32
            goto L2b
        L32:
            return r0
        */
        throw new UnsupportedOperationException("Method not decompiled: jmgldvb.C6107cme.f():boolean");
}

4.分区读写检测

public final boolean k() {
        String str;
        String str2;
        String[] strArr;
        int i;
        boolean z;
        String str3;
        String[] e = e();
        int i2 = 0;
        if (e == null) {
            return false;
        }
        int i3 = Build.VERSION.SDK_INT;
        int length = e.length;
        int i4 = 0;
        boolean z2 = false;
        while (i4 < length) {
            String str4 = e[i4];
            Object[] array = new Regex(StringUtils.SPACE).split(str4, i2).toArray(new String[i2]);
            Intrinsics.checkNotNull(array, "null cannot be cast to non-null type kotlin.Array");
            String[] strArr2 = (String[]) array;
            int i5 = 23;
            if ((i3 > 23 || strArr2.length >= 4) && (i3 <= 23 || strArr2.length >= 6)) {
                boolean z3 = true;
                if (i3 > 23) {
                    str = strArr2[2];
                    str2 = strArr2[5];
                } else {
                    str = strArr2[1];
                    str2 = strArr2[3];
                }
                String[] strArr3 = C4631btu.g;
                int length2 = strArr3.length;
                String str5 = str2;
                int i6 = i2;
                while (i6 < length2) {
                    String str6 = strArr3[i6];
                    if (StringsKt.equals(str, str6, z3)) {
                        if (Build.VERSION.SDK_INT > i5) {
                            str3 = str6;
                            str5 = StringsKt.replace$default(StringsKt.replace$default(str5, "(", "", false, 4, (Object) null), ")", "", false, 4, (Object) null);
                        } else {
                            str3 = str6;
                        }
                        strArr = e;
                        Object[] array2 = new Regex(",").split(str5, i2).toArray(new String[i2]);
                        Intrinsics.checkNotNull(array2, "null cannot be cast to non-null type kotlin.Array");
                        String[] strArr4 = (String[]) array2;
                        int length3 = strArr4.length;
                        int i7 = i2;
                        while (true) {
                            if (i7 >= length3) {
                                i = i3;
                                z = true;
                                break;
                            }
                            String[] strArr5 = strArr4;
                            i = i3;
                            z = true;
                            if (StringsKt.equals(strArr4[i7], "rw", true)) {
                                C0339Io.b(str3 + " path is mounted with rw permissions! " + str4);
                                z2 = true;
                                break;
                            }
                            i7++;
                            strArr4 = strArr5;
                            i3 = i;
                        }
                    } else {
                        strArr = e;
                        i = i3;
                        z = z3;
                    }
                    i6++;
                    z3 = z;
                    e = strArr;
                    i3 = i;
                    i2 = 0;
                    i5 = 23;
                }
            } else {
                C0339Io.h.e("Error formatting mount line: " + str4);
            }
            i4++;
            e = e;
            i3 = i3;
            i2 = 0;
        }
        return z2;
}

5.面具检测

通过which命令查找面具可执行文件。

public final boolean m() {
    return a("magisk");
}

6.APP安装时间检测

通过日志发现每次启动都会检测APP的安装,更新时间。

PackageInfoUtils_generatePackageInfo_1 com.CTION, firstInstallTime: 1701134370160, lastUpdateTime: 1701134626468

7.ROM检测

如果是开发版的ROM,通常tags都是:test-keys

public final boolean q() {
        String str = Build.TAGS;
        return str != null && StringsKt.contains$default((CharSequence) str, (CharSequence) "test-keys", false, 2, (Object) null);
}

8.挂载信息获取

这个mount会把挂载信息返回,可以检测挂载信息中是否有magisk或者zygisk字符串等。

private final String[] e() {
        try {
            InputStream inputStream = Runtime.getRuntime().exec("mount").getInputStream();
            if (inputStream == null) {
                return null;
            }
            String propVal = new Scanner(inputStream).useDelimiter("\A").next();
            Intrinsics.checkNotNullExpressionValue(propVal, "propVal");
            Object[] array = new Regex(StringUtils.LF).split(propVal, 0).toArray(new String[0]);
            Intrinsics.checkNotNull(array, "null cannot be cast to non-null type kotlin.Array");
            return (String[]) array;
        } catch (IOException e) {
            C0339Io.a((Exception) e);
            return null;
        } catch (NoSuchElementException e2) {
            C0339Io.a((Exception) e2);
            return null;
        }
}

9.读取系统属性

读取了系统的全部属性,应该手机手机型号,厂商等等信息。

private final String[] g() {
        try {
            InputStream inputStream = Runtime.getRuntime().exec("getprop").getInputStream();
            if (inputStream == null) {
                return null;
            }
            String propVal = new Scanner(inputStream).useDelimiter("\A").next();
            Intrinsics.checkNotNullExpressionValue(propVal, "propVal");
            Object[] array = new Regex(StringUtils.LF).split(propVal, 0).toArray(new String[0]);
            Intrinsics.checkNotNull(array, "null cannot be cast to non-null type kotlin.Array");
            return (String[]) array;
        } catch (IOException e) {
            C0339Io.a((Exception) e);
            return null;
        } catch (NoSuchElementException e2) {
            C0339Io.a((Exception) e2);
            return null;
        }
}

判断是不是模拟器:ro.kernel.qemu

获取手机厂商ro.product.manufacturer

品牌:ro.build.product

指纹:ro.build.fingerprint

10.开发者模式adb检测

Settings中获取adb状态。

Settings.Secure

Global getInt : adb_enabled

Secure getInt : adb_wifi_enabled

11.可疑的二进制文件

这里就是可以传递su,magisk等等参数

public final boolean a(String filename) {
        String[] a;
        Intrinsics.checkNotNullParameter(filename, "filename");
        boolean z = false;
        for (String str : C4631btu.d.a()) {
            String str2 = str + filename;
            if (new File(str, filename).exists()) {
                C0339Io.b(str2 + " binary detected!");
                z = true;
            }
        }
        return z;
}

12.ro.debuggable检测

ro.debuggable这个系统属性,在user版本的系统中是0,如果发现是1可以判断当前系统是可调试状态和root状态。

public final boolean b() {
        HashMap hashMap = new HashMap();
        hashMap.put("ro.debuggable", "1");
        hashMap.put("ro.secure", "0");
        String[] g = g();
        if (g == null) {
            return false;
        }
        boolean z = false;
        for (String str : g) {
            for (String str2 : hashMap.keySet()) {
                String str3 = str;
                if (StringsKt.contains$default((CharSequence) str3, (CharSequence) str2, false, 2, (Object) null)) {
                    String str4 = "[" + ((String) hashMap.get(str2)) + ']';
                    if (StringsKt.contains$default((CharSequence) str3, (CharSequence) str4, false, 2, (Object) null)) {
                        C0339Io.b(str2 + " = " + str4 + " detected!");
                        z = true;
                    }
                }
            }
        }
        return z;
}

13.无障碍检测

getEnabledAccessibilityServiceList

获取当前无障碍服务的激活的APP信息,这里拿到了激活了无障碍的APP,只有发现有,APP直接崩溃。

private final List getPackageAccessibilityServiceEnabledList(Context context) {
        PackageInfo packageInfo;
        List enabledAccessibilityServiceList = getAccessibilityService(context).getEnabledAccessibilityServiceList(-1);
        Intrinsics.checkNotNullExpressionValue(enabledAccessibilityServiceList, "accessibilityManager.get…ceInfo.FEEDBACK_ALL_MASK)");
        List list = enabledAccessibilityServiceList;
        ArrayList arrayList = new ArrayList(CollectionsKt.collectionSizeOrDefault(list, 10));
        for (AccessibilityServiceInfo accessibilityServiceInfo : list) {
            ServiceInfo serviceInfo = accessibilityServiceInfo.getResolveInfo().serviceInfo;
            try {
                packageInfo = context.getPackageManager().getPackageInfo(serviceInfo.packageName, 0);
            } catch (PackageManager.NameNotFoundException unused) {
                PackageInfo packageInfo2 = new PackageInfo();
                packageInfo2.packageName = serviceInfo.packageName;
                packageInfo2.applicationInfo = serviceInfo.applicationInfo;
                packageInfo = packageInfo2;
            }
            arrayList.add(packageInfo);
        }
        return arrayList;
}

14.获取APP安装列表

获取了用户安装的所有APP,应该是收集上传,判断是否装了一些root有关的APP。

public List getInstalledApps(PackageManager packageManager) {
        Intrinsics.checkNotNullParameter(packageManager, "packageManager");
        List installedPackages = packageManager.getInstalledPackages(0);
        Intrinsics.checkNotNullExpressionValue(installedPackages, "packageManager.getInstalledPackages(0)");
        return filterNotSystemApp(installedPackages);
}

‍现在的APP检测环境都挺全

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Android
    +关注

    关注

    12

    文章

    3851

    浏览量

    125642
  • APP
    APP
    +关注

    关注

    33

    文章

    1530

    浏览量

    71631
  • 调试
    +关注

    关注

    7

    文章

    527

    浏览量

    33625
  • 环境检测
    +关注

    关注

    0

    文章

    16

    浏览量

    7459

原文标题:Android App环境检测分析

文章出处:【微信号:哆啦安全,微信公众号:哆啦安全】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Android APP如何进行访问硬件驱动

    本文我们要讲的是在用 i.MX8 平台开发时,Android APP 如何进行访问硬件驱动。
    的头像 发表于 12-04 13:50 475次阅读
    <b class='flag-5'>Android</b> <b class='flag-5'>APP</b>如何进行访问硬件驱动

    #Android开发 Android开发环境搭建_1.9 案例1:我的第一个App(HiAndroid

    Android
    电子知识科普
    发布于 :2022年12月08日 17:55:54

    [资料分享]+《Android软件安全与逆向分析

    环境搭建 1  1.1  Windows分析环境搭建 1  1.1.1  安装JDK 1  1.1.2  安装Android SDK 3  1.1.3  安装
    发表于 09-26 10:53

    史无前例,详细视频讲解开发AndroidAPP开发!!

    导读:本文记录了一个机友-小徐基于机智云APP开源框架,从搭建Java环境开始,教你下载JDk、下载AndroidStudio,到控制设备页面等,完成一款正式版安卓APP的开发过程。擅
    发表于 07-13 12:16

    如何使用BlueSTSDK Android App检测加速事件?

    你好, 我正在使用BlueSTSDK Android应用程序接收STEVAL-STLKT01V1 SensorTile通过蓝牙低功耗传输的数据。我想用这个应用程序检测加速度计事件作为方向,单击等
    发表于 10-16 10:15

    HiSpark wifi-lot MQTT的移植——Android MQTT 调试APP

    昨天跟着 连志安老师的教程,实现了HiSpark wifi-lot MQTT的移植,借助老师的MQTT服务器,成功实现了消息的发布和订阅。今天成热打铁,弄了一个Android APP,实时的发布
    发表于 12-02 12:20

    分享一个不错的单片机与Android App的通信方案

    源码传送门前言本篇文章将围绕App与单片机的蓝牙通信来说说lz最近进行开发的一些方案与思考此文分为三部分:单片机的PWM与串口通信Android的蓝牙开发单片机与Android App
    发表于 01-10 06:25

    怎么实现Android APP与STM32无线环境控制系统的设计?

    如何实现Android APP与STM32无线环境控制系统的设计?
    发表于 01-19 07:15

    怎样去搭建一种App Inventor环境

    App Inventor学习环境搭建App Inventor(简称AI)由谷歌实验室开发,后移交麻省理工学院,是一款可视化编程环境,采用搭积木的方式快速建立应用程序,并且可以结合AI伴
    发表于 02-28 12:18

    关于Android下的APP开发体验过程记录

    关于Android下的APP开发体验过程记录
    发表于 03-04 11:38

    基于AndroidAPP安全检测技术浅析

    基于AndroidAPP安全检测技术浅析
    发表于 06-28 16:03 16次下载
    基于<b class='flag-5'>Android</b>的<b class='flag-5'>APP</b>安全<b class='flag-5'>检测</b>技术浅析

    Android 12“App Pairs”功能:改造分屏多任务能力

    Android 12“App Pairs”功能:新分屏多任务能力,安卓,app,谷歌,分屏,应用程序
    发表于 02-04 14:45 1517次阅读

    基于Android的果蝇识别APP

    本文档的主要内容详细介绍的是基于Android的果蝇识别APP采用随机森林,神经网络等多种算法。
    发表于 03-01 09:28 6次下载

    Android使用Wireshark抓包

    Frida逆向分析APP实战 Objection动态分析App Frida Hook的使用方法 Android逆向
    的头像 发表于 11-16 10:07 3700次阅读

    Arduino Android APP来控制8个继电器

    电子发烧友网站提供《Arduino Android APP来控制8个继电器.zip》资料免费下载
    发表于 07-10 10:48 1次下载
    Arduino <b class='flag-5'>Android</b> <b class='flag-5'>APP</b>来控制8个继电器