android 安全sdk相关

news2024/11/30 4:05:16

前述

        在网上有看到许多android安全sdk相关的内容,有重复的也有比较新鲜的内容,这里做一个整体的合集,以及后续又看到一些比较新的东西会一起放在这里。

        android内sdk目前可以分为以下几个部分(有一些部分可能会存在一些重合)——设备指纹,root相关,环境检测,模拟器特征,改机软件

设备指纹

1.android_id

google给的app唯一id,存放在/data/system/users/0/settings_ssaid.xml文件中,只有在文件存储位置处修改,设备重刷或设备恢复出厂设置等时候才会被修改。可以用Settings.Global.getString() 、Settings.Secure.getString()、Settings.System.getString()来获取(根据/data/system/users/0/下的文件名字推测可用这些方法获取该目录下一些文件的内容)

2.drmid(设备媒体id)

media drm的设备id,同时和app包名以及签名有关,即不同包名或者不同签名,drmid会不一样,可以视为另外一个android_id,缺点是还和包名有关,注意:极少数机型上获取该id的过程存在崩溃且google也在逐渐的废除该id,可参考:https://developer.android.com/identity/user-data-ids

UUID wideVineUuid = new UUID(-0x121074568629b532L, -0x5c37d8232ae2de13L);
try {
    MediaDrm wvDrm = new MediaDrm(wideVineUuid);
    byte[] wideVineId = wvDrm.getPropertyByteArray(MediaDrm.PROPERTY_DEVICE_UNIQUE_ID);
    return Utils.md5(wideVineId);
} catch (Exception e) {
    return null;
}

3.gsfiid

gsfiid是Google Service Framework ID,Google服务框架 ID

public static String gsfid() {
    Context context = DeviceGlobal.getContext();
    Uri uri = Uri.parse("content://com.google.android.gsf.gservices");
    if (uri != null) {
        try (Cursor cursor = context.getContentResolver().query(uri,
                null, null,
                new String[]{"android_id"}, null)) {
            if (cursor.moveToFirst()) {
                return Long.toHexString(Long.parseLong(cursor.getString(1)));
            }
        } catch (Throwable tr) {
            Logger.w(TAG, tr.toString());
        }
    }
    return null;
}

4.apk相关

apk安装时间和路径,可以通过getPackageInfo中的firstInstallTime获取,可以作为唯一id和防刷

5.boot_id,oaid,imei,serial number

boot_id可以通过cat /proc/sys/kernel/random/boot_id获取,重启后会更新,是uuid格式字符串格式。

imei是SIM卡相关的信息,谷歌已经删除该属性来保护隐私性

serial number是手机adb devices的一串数字,可以通过getprop ro.serialno获取

oaid是国内android广告标识符,用户可以选择重置和退出广告跟踪。

6.文件哈希

使用stat获取/,/data/,/data/system/vendor/firmware,/system/bin,/vendor/lib,/systen/framework,/system/fonts,或者一些固定app目录的文件名,inode,uid,创建时间,最后修改时间组合等属性组合求hash作为指纹

7.网络相关

这里主要是指机器的ip,mac,网络的类型,这里的信息除了可以做设备指纹之外,也可以用来判断设备的环境等特征。获取方法可以通过ip -a或者ip neigh show命令行执行或者读取/proc/net/arp获取相关信息

root检测

1.path检测

getenv("path") 获取路径,和su或者magisk组合,判断root是否存在

2.属性获取

可以通过以下属性特征来判断设备是不是root了

getprop service.adb.root = "1"
getprop init.svc.adb_root = "running"
getprop ro.secure = "0"
getprop ro.debuggable = "1"
getprop ro.build.tags = "test-keys"

3.内存扫描

内存扫描有以下几种方式——1.检测/proc/self/maps 是否存在名为“/memfd:/jit-cache"的段(加载zygisk模块);2.检测栈空间[stack]的权限是否为"rw-p";3.检测map表是否存在匿名的且具有可执行属性。

4.selinux上下文检测

cat /proc/self/attr/prev,看文件中的内容是否为"u:r:zygote:s0",其中r表示进程,zygote表示进程权限

5.常见root应用检测

可以尝试包名检测,遍历/data/data/目录,看有没有一下目录

com.topjohnwu.magisk
eu.chainfire.supersu
com.noshufou.android.su
com.noshufou.android.su.elite
com.koushikdutta.superuser
com.thirdparty.superuser
com.yellowes.su
com.fox2code.mmm
io.github.vvb2060.magisk
com.kingroot.kinguser
com.kingo.root
com.smedialink.oneclickroot
com.zhiqupk.root.global
com.alephzain.framaroot
io.github.huskydg.magisk
me.weishu.kernelsu

6.其他

可以尝试访问/data,/system,/etc,查询是否有busybox可以执行——尝试which busybox或者是执行busybox

hook检测

1.frida检测

  • 默认端口检测——27042
  • 常见路径检测——/data/local/tmp/frida-server
  • 检查进程/proc/self/fd/目录,寻找是否存在关键字linjector
  • 内存模块扫描——frida-agent,frida-gadge,可以去/proc/self/maps文件下找找字符串
  • inlinehook检测frida——查询函数头部是不是0xd61f020058000050

2.Xposed检测

  • java.lang.ClassLoader.getSystemClassLoader.loadClass("de.robv.android.xposed.XposedHelpers") ——看xposed是否加载
  • 遍历/data/data/目录,寻找有无以下包名
de.robv.android.xposed.installer #Xposed框架
org.meowcat.edxposed.manager #EdXposed框架
com.tsng.hidemyapplist #隐藏应用列表
com.tsng.hidemyroot #隐藏Root
org.lsposed.manager #LSPosed框架
me.weishu.exp #VirtualXposed 太极
top.canyie.dreamland.manager #VirtualXposed 夢境
io.va.exposed #VirtualXposed 夢境
io.va.exposed64 #VirtualXposed 夢境
io.virtualapp #VirtualApp
io.virtualapp.sandvxposed64 #VirtualApp
  • 检测下列文件或文件路径是否存在
/sbin/.magisk/modules/riru_lsposed
/data/adb/lspd
/sbin/.magisk/modules/zygisk_lsposed
/sbin/.magisk/modules/riru_edxposed
/data/misc/riru/modules/edxp
/data/adb/riru/modules/edxp.prop
/sbin/.magisk/modules/taichi
/data/misc/taichi
/sbin/.magisk/modules/dreamland
/data/misc/riru/modules/dreamland
/data/adb/riru/modules/dreamland
/system/bin/app_process.orig
/system/xposed.prop
/system/framework/XposedBridge.jar
/system/lib/
libxposed_art.so
/system/lib/
libxposed_art.so
.no_orig
/system/lib64/
libxposed_art.so
/system/lib64/
libxposed_art.so
.no_orig
/system/bin/app_process_zposed
/system/framework/ZposedBridge.jar
/system/lib/
libzposed_art.so
  • artmethod结构体判断,artmethod中access_flags和entry_point_from_jni_在hook过程中会发生更改。

3.调试检测

  • 调试端口检测——读取/proc/net/tcp,ida远程调试端口用的是23946端口
  • 调试进程名检测——直接ps -a,看是否有android-server或者adb-server
  • tracepid检测——读取/proc/self/status,查看tracepid是不是为0
  • ptrace检测——因为每个进程只能被一个ptrace检测,所以可以自己启动一个ptrace或者对ptrace检测
  • 断电指令检测——检测bkpt指令
  • dalvik模式下可以用libdvm.so中dvmDbgIsDebuggerConnected()函数检测,art模式下使用libart.so中gDebuggerActive中
  • 可以读取/proc/self/cmdline查看内容是否为zygote

模拟器云手机检测

1.特有的文件

模拟器特有文件

"/boot/bstmods/vboxguest.ko",
"/boot/bstmods/vboxsf.ko",
"/dev/mtp_usb",
"/dev/qemu_pipe",
"/dev/socket/baseband_genyd",
"/dev/socket/genyd",
"/dev/socket/qemud",
"/dev/socket/windroyed-audio",
"/dev/socket/windroyed-camera",
"/dev/socket/windroyed-gps",
"/dev/socket/windroyed-sensors",
"/dev/vboxguest",
"/dev/vboxpci",
"/dev/vboxuser",
"/fstab.goldfish",
"/fstab.nox",
"/fstab.ranchu-encrypt",
"/fstab.ranchu-noencrypt",
"/fstab.ttVM_x86",
"/fstab.vbox86",
"/init.goldfish.rc",
"/init.magisk.rc",
"/init.nox.rc",
"/init.ranchu-encrypt.rc",
"/init.ranchu-noencrypt.rc",
"/init.ranchu.rc",
"/init.ttVM_x86.rc",
"/init.vbox86.rc",
"/init.vbox86p.rc",
"/init.windroye.rc",
"/init.windroye.sh",
"/init.x86.rc",
"/proc/irq/20/vboxguest",
"/sdcard/Android/data/com.redfinger.gamemanage",
"/stab.andy",
"/sys/bus/pci/drivers/vboxguest",
"/sys/bus/pci/drivers/vboxpci",
"/sys/bus/platform/drivers/qemu_pipe",
"/sys/bus/platform/drivers/qemu_pipe/qemu_pipe",
"/sys/bus/platform/drivers/qemu_trace",
"/sys/bus/virtio/drivers/itolsvmlgtp",
"/sys/bus/virtio/drivers/itoolsvmhft",
"/sys/class/bdi/vboxsf-1",
"/sys/class/bdi/vboxsf-2",
"/sys/class/bdi/vboxsf-3",
"/sys/class/misc/qemu_pipe",
"/sys/class/misc/vboxguest",
"/sys/class/misc/vboxuser",
"/sys/devices/platform/qemu_pipe",
"/sys/devices/virtual/bdi/vboxsf-1",
"/sys/devices/virtual/bdi/vboxsf-2",
"/sys/devices/virtual/bdi/vboxsf-3",
"/sys/devices/virtual/misc/qemu_pipe",
"/sys/devices/virtual/misc/vboxguest",
"/sys/devices/virtual/misc/vboxpci",
"/sys/devices/virtual/misc/vboxuser",
"/sys/fs/selinux/booleans/in_qemu",
"/sys/kernel/debug/bdi/vboxsf-1",
"/sys/kernel/debug/bdi/vboxsf-2",
"/sys/kernel/debug/x86",
"/sys/module/qemu_trace_sysfs",
"/sys/module/vboxguest",
"/sys/module/vboxguest/drivers/pci:vboxguest",
"/sys/module/vboxpcism",
"/sys/module/vboxsf",
"/sys/module/vboxvideo",
"/sys/module/virtio_pt/drivers/virtio:itoolsvmhft",
"/sys/module/virtio_pt_ie/drivers/virtio:itoolsvmlgtp",
"/sys/qemu_trace",
"/system/app/GenymotionLayout",
"/system/bin/OpenglService",
"/system/bin/androVM-vbox-sf",
"/system/bin/droid4x",
"/system/bin/droid4x-prop",
"/system/bin/droid4x-vbox-sf",
"/system/bin/droid4x_setprop",
"/system/bin/enable_nox",
"/system/bin/genymotion-vbox-sf",
"/system/bin/microvirt-prop",
"/system/bin/microvirt-vbox-sf",
"/system/bin/microvirt_setprop",
"/system/bin/microvirtd",
"/system/bin/mount.vboxsf",
"/system/bin/nox",
"/system/bin/nox-prop",
"/system/bin/nox-vbox-sf",
"/system/bin/nox_setprop",
"/system/bin/noxd",
"/system/bin/noxscreen",
"/system/bin/noxspeedup",
"/system/bin/qemu-props",
"/system/bin/qemud",
"/system/bin/shellnox",
"/system/bin/ttVM-prop",
"/system/bin/windroyed",
"/system/droid4x",
"/system/etc/init.droid4x.sh",
"/system/etc/init.tiantian.sh",
"/system/lib/egl/libEGL_emulation.so",
"/system/lib/egl/libEGL_tiantianVM.so",
"/system/lib/egl/libEGL_windroye.so",
"/system/lib/egl/libGLESv1_CM_emulation.so",
"/system/lib/egl/libGLESv1_CM_tiantianVM.so",
"/system/lib/egl/libGLESv1_CM_windroye.so",
"/system/lib/egl/libGLESv2_emulation.so",
"/system/lib/egl/libGLESv2_tiantianVM.so",
"/system/lib/egl/libGLESv2_windroye.so",
"/system/lib/hw/audio.primary.vbox86.so",
"/system/lib/hw/audio.primary.windroye.so",
"/system/lib/hw/audio.primary.x86.so",
"/system/lib/hw/autio.primary.nox.so",
"/system/lib/hw/camera.vbox86.so",
"/system/lib/hw/camera.windroye.jpeg.so",
"/system/lib/hw/camera.windroye.so",
"/system/lib/hw/camera.x86.so",
"/system/lib/hw/gps.nox.so",
"/system/lib/hw/gps.vbox86.so",
"/system/lib/hw/gps.windroye.so",
"/system/lib/hw/gralloc.nox.so",
"/system/lib/hw/gralloc.vbox86.so",
"/system/lib/hw/gralloc.windroye.so",
"/system/lib/hw/sensors.nox.so",
"/system/lib/hw/sensors.vbox86.so",
"/system/lib/hw/sensors.windroye.so",
"/system/lib/init.nox.sh",
"/system/lib/libGM_OpenglSystemCommon.so",
"/system/lib/libc_malloc_debug_qemu.so",
"/system/lib/libclcore_x86.bc",
"/system/lib/libdroid4x.so",
"/system/lib/libnoxd.so",
"/system/lib/libnoxspeedup.so",
"/system/lib/modules/3.10.30-android-x86.hd+",
"/system/lib/vboxguest.ko",
"/system/lib/vboxpcism.ko",
"/system/lib/vboxsf.ko",
"/system/lib/vboxvideo.ko",
"/system/lib64/egl/libEGL_emulation.so",
"/system/lib64/egl/libGLESv1_CM_emulation.so",
"/system/lib64/egl/libGLESv2_emulation.so",
"/vendor/lib64/egl/libEGL_emulation.so",
"/vendor/lib64/egl/libGLESv1_CM_emulation.so",
"/vendor/lib64/egl/libGLESv2_emulation.so",
"/vendor/lib64/libandroidemu.so",
"/system/lib64/hw/gralloc.ranchu.so",
"/system/lib64/libc_malloc_debug_qemu.so",
"/system/usr/Keylayout/droid4x_Virtual_Input.kl",
"/system/usr/idc/Genymotion_Virtual_Input.idc",
"/system/usr/idc/droid4x_Virtual_Input.idc",
"/system/usr/idc/nox_Virtual_Input.idc",
"/system/usr/idc/windroye.idc",
"/system/usr/keychars/nox_gpio.kcm",
"/system/usr/keychars/windroye.kcm",
"/system/usr/keylayout/Genymotion_Virtual_Input.kl",
"/system/usr/keylayout/nox_Virtual_Input.kl",
"/system/usr/keylayout/nox_gpio.kl",
"/system/usr/keylayout/windroye.kl",
"system/etc/init/ndk_translation_arm64.rc",
"/system/xbin/noxsu",
"/ueventd.android_x86.rc",
"/ueventd.andy.rc",
"/ueventd.goldfish.rc",
"/ueventd.nox.rc",
"/ueventd.ranchu.rc",
"/ueventd.ttVM_x86.rc",
"/ueventd.vbox86.rc",
"/vendor/lib64/libgoldfish-ril.so",
"/vendor/lib64/libgoldfish_codecs_common.so",
"/vendor/lib64/libstagefright_goldfish_avcdec.so",
"/vendor/lib64/libstagefright_goldfish_vpxdec.so",
"/x86.prop",
"/system/lib/virtio_pt.ko", //itoolsAVM
"dev/bst_gps", //BlueStacks
"/dev/bstgyro", //BlueStacks Game
"/system/bin/bstfolder", //BlueStacks Game
"/system/lib/msf.ko", //memu
"/dev/nemuuser", //Mumu
"/dev/nemuinit", //Mumu
"/system/lib/fastpipe.ko", //Dnplayer
"/fstab.andy", //AndY
"/dev/virtiopt",    //itoolsAVM or nox
"/sys/module/vboxsf/srcversion", //vbox
"/dev/goldfish_pipe"  //qemu

2.特有的属性

  • qemu特有的属性
"ro.kernel.qemu.avd_name",
"ro.kernel.qemu.gles",
"ro.kernel.qemu.gltransport",
"ro.kernel.qemu.opengles.version",
"ro.kernel.qemu.uirenderer",
"ro.kernel.qemu.vsync",
"ro.qemu.initrc",
"init.svc.qemu-props",
"qemu.adb.secure",
"qemu.cmdline",
"qemu.hw.mainkeys",
"qemu.logcat",
"ro.adb.qemud",
"qemu.sf.fake_camera",
"qemu.sf.lcd_density",
"qemu.timezone",
"init.svc.goldfish-logcat",
"ro.boottime.goldfish-logcat",
"ro.hardware.audio.primary",
"init.svc.ranchu-net",
"init.svc.ranchu-setup",
"ro.boottime.ranchu-net",
"ro.boottime.ranchu-setup",
"init.svc.droid4x",
"init.svc.noxd",
"init.svc.qemud",
"init.svc.goldfish-setup",
"init.svc.goldfish-logcat",
"init.svc.ttVM_x86-setup",
"vmos.browser.home",
"vmos.camera.enable",
"ro.trd_yehuo_searchbox",
"init.svc.microvirtd",
"init.svc.vbox86-setup",
"ro.ndk_translation.version",
"redroid.width",
"redroid.height",
"redroid.fps",
"ro.rf.vmname"
  • 模拟器属性
"init.svc.microvirtd",
"bst.version",
"ro.phoenix.version.code",
"ro.phoenix.version.codename",
"init.svc.droid4x",
"microvirt.memu_version",
"microvirt.imsi",
"microvirt.simserial",
"ro.px.version.build",
"ro.phoenix.os.branch",
"init.svc.su_kpbs_daemon",
"init.svc.noxd",
"init.svc.ttVM_x86-setup",
"init.svc.xxkmsg",
"ro.bild.remixos.version",
"microvirt.mut",
"init.svc.ldinit",
"sys.tencent.os_version",
"sys.tencent.android_id",
"ro.genymotion.version",
"init.svc.pkVM_x86-setup",
"ro.andy.version",
"ro.build.version.release",
"ro.product.model",
"ro.product.brand",
"ro.boot.bootloader",
"ro.build.version.securitypatch",
"ro.build.version.incremental",
"gsm.version.baseband",
"gsm.version.ril-impl",
"ro.build.fingerprint",
"ro.build.description",
"ro.build.product",
"ro.boot.vbmeta.digest",
"ro.hardware",
"ro.product.name",
"ro.product.board",
"ro.recovery_id",
"ro.expect.recovery_id",
"ro.board.platform",
"ro.product.manufacturer",
"ro.product.device",
"sys.usb.state",
"ro.setupwizard.mode",
"ro.build.id",
"ro.build.tags",
"ro.build.type",
"ro.debuggable"

3.系统架构判断

主要是判断系统是x86还是arm,arm64的,通常手机是arm或者arm64架构的,模拟器是x86架构的,这里获取的方式使用seccomp来判断

先安装seccomp架子
void install_check_arch_seccomp() {
    struct sock_filter filter[15] = {
            BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (uint32_t) offsetof(struct seccomp_data, nr)),
            BPF_JUMP(BPF_JMP + BPF_JEQ, __NR_getpid, 0, 12),
            BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (uint32_t) offsetof(struct seccomp_data, args[0])),
            BPF_JUMP(BPF_JMP + BPF_JEQ, DetectX86Flag, 0, 10),
            BPF_STMT(BPF_LD + BPF_W + BPF_ABS, (uint32_t) offsetof(struct seccomp_data, arch)),
            BPF_JUMP(BPF_JMP + BPF_JEQ, AUDIT_ARCH_X86_64, 0, 1),
            BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (864 & SECCOMP_RET_DATA)),
            BPF_JUMP(BPF_JMP + BPF_JEQ, AUDIT_ARCH_I386, 0, 1),
            BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (386 & SECCOMP_RET_DATA)),
            BPF_JUMP(BPF_JMP + BPF_JEQ, AUDIT_ARCH_ARM, 0, 1),
            BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (0xA32 & SECCOMP_RET_DATA)),
            BPF_JUMP(BPF_JMP + BPF_JEQ, AUDIT_ARCH_AARCH64, 0, 1),
            BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (0xA64 & SECCOMP_RET_DATA)),
            BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ERRNO | (6 & SECCOMP_RET_DATA)),
            BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW)
 
    };
    struct sock_fprog program = {
            .len = (unsigned short) (sizeof(filter) / sizeof(filter[0])),
            .filter = filter
    };
    errno = 0;
    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
        LOG(ERROR) << "prctl(PR_SET_NO_NEW_PRIVS) " << strerror(errno);
    }
    errno = 0;
    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &program)) {
        LOG(ERROR) << "prctl(PR_SET_SECCOMP) " << strerror(errno);
    }
}

配合上面的代码 。启动调用getpid, 上面的架子会对getpid函数进行拦截 ,然后架构进行判断
string check_arch_by_seccomp() {
    if (get_sdk_level() < __ANDROID_API_N_MR1__){
        return "";
    }
    errno = 0;
    syscall(__NR_getpid, DetectX86Flag);
    if (errno == 386) {
        return "I386设备";
    } else if (errno == 864) {
        return "X86_64设备";
    } else if (errno == 0xA32 || errno == 0xA64) {
        return "";
    }else if (errno == 0) {
        //可能是没有开启seccomp
        return "";
    }
    return ("疑似X86模拟器设备"+ to_string(errno));
}

4.硬件模块

  • 温度模块——可以通过检测cpu温度记录(在/sys/class/thermal/)来判断模拟器,真机存在,模拟器不存在
int thermal_check() {
    DIR *dir_ptr;
    int count = 0;
    struct dirent *entry;
    if ((dir_ptr = opendir("/sys/class/thermal/")) != nullptr) {
        while ((entry = readdir(dir_ptr))) {
            if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
                continue;
            }
            char *tmp = entry->d_name;
            if (strstr(tmp, "thermal_zone") != nullptr) {
                count++;
            }
        }
        closedir(dir_ptr);
    } else {
        count = -1;
    }
    return count;
}
  • 相机相关——摄像头个数,闪光灯是否存在,模拟器通常只有一个摄像头,没有闪关灯
try {
    CameraManager manager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
    String[] cameraIds = manager.getCameraIdList();
    //摄像头个数
    CLog.i("cameraIds -> "+ Arrays.toString(cameraIds));
    if(cameraIds.length < CAMERA_MINIMUM_QUANTITY_LIMIT){
        items.add(
                new ListItemBean(
                "当前手机可能是模拟器&云手机",
                ListItemBean.RiskLeave.Warn,
                "camera size -> "+cameraIds.length
        ));
    }
} catch (Throwable ignored) {
 
}
  • 传感器相关——可以检测传感器数目和种类。和正常的同类型设备相比,模拟器拥有的传感器数目比正常的少许多
try {
    //3,检测传感器类型,支持的全部类型传感器
    SensorManager sm = (SensorManager) context.getSystemService(SENSOR_SERVICE);
    List<Sensor> sensorlist = sm.getSensorList(Sensor.TYPE_ALL);
 
    ArrayList<Integer> sensorTypeS = new ArrayList<>();
    for (Sensor sensor : sensorlist) {
        //获取传感器类型
        int type = sensor.getType();
        if (!sensorTypeS.contains(type)) {
            //发现一种类型则添加一种类型
            sensorTypeS.add(type);
        }
    }
    //小米k40 51个传感器类型
    //普通的pix 27个
    //华为荣耀20 18个传感器
    CLog.e("sensor types size -> " + sensorlist.size());
    //我们认为传感器少于20个则认为是风险设备
    if (sensorlist.size() < SENSOR_MINIMUM_QUANTITY_LIMIT) {
        items.add(new ListItemBean(
                "当前手机可能是模拟器&云手机",
                ListItemBean.RiskLeave.Warn,
                "sensor size -> ("+ sensorlist.size()+") \n" +
                "sensor type size -> ("+sensorTypeS.size()+") \n"
                //+ "sensor info -> \n"+ Sensorlist   //打印全部传感器信息
        ));
    }
传感器名称(有AOSP)——
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    ArrayList<Sensor> aospSensor = new ArrayList<>();
    for(Sensor sensor:sensorlist){
        if(sensor.getVendor().contains("AOSP")){
            aospSensor.add(sensor);
        }
    }
    if (aospSensor.size()>3) {
        CLog.e("传感器参数是否异常(生产厂商为AOSP)");
        items.add(new ListItemBean(
                "当前手机可能是模拟器&云手机",
                ListItemBean.RiskLeave.Warn,
                aospSensor.size()
                        +"/"+sensorlist.size()+"传感器参数异常 -> "+ aospSensor
        ));
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2250180.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

djinn:1 靶场学习小记

一、测试环境&#xff1a; kail攻击机&#xff1a;Get Kali | Kali Linux 靶场镜像&#xff1a;https://download.vulnhub.com/djinn/djinn.ova 描述&#xff1a; 该机器与 VirtualBox 和 VMWare 兼容。DHCP 将自动分配一个 IP。您将在登录屏幕上看到 IP。您必须找到并读取分…

外卖点餐系统小程序

目录 开发前准备 项目展示项目分析项目初始化封装网络请求 任务1 商家首页 任务分析焦点图切换中间区域单击跳转到菜单列表底部商品展示 任务2 菜单列表 任务分析折扣信息区设计菜单列表布局请求数据实现菜单栏联动单品列表功能 任务3 购物车 任务分析设计底部购物车区域添加商…

内网不出网上线cs

一:本地正向代理目标 如下&#xff0c;本地(10.211.55.2)挂好了基于 reGeorg 的 http 正向代理。代理为: Socks5 10.211.55.2 1080python2 reGeorgSocksProxy.py -l 0.0.0.0 -p 1080 -u http://10.211.55.3:8080/shiro/tunnel.jsp 二&#xff1a;虚拟机配置proxifer 我们是…

ThinkPHP Nginx 重写配置

目录 NGINX 重写 Admin项目隐藏入口文件&#xff0c;且禁用Admin模块&Admin.php 1️⃣配置仅用模块 2️⃣新增admin_xyz.php文件&#xff08;自定义入口文件名&#xff09;&#xff0c;并绑定admin模块 3️⃣配置nginx 重写规则 NGINX 重写 在Nginx低版本中&#xff0…

宠物电商对接美团闪购:实现快速配送与用户增值

随着宠物行业的快速发展&#xff0c;宠物电商市场也在不断扩张。消费者的需求不再局限于传统的线上购物模式&#xff0c;越来越多的人开始追求更快捷的配送服务和更优质的购物体验。为了适应这一趋势&#xff0c;许多宠物电商平台开始寻求与本地配送平台合作&#xff0c;以提供…

Flink高可用配置(HA)

从Flink架构中我们可以看到,JobManager这个组件非常重要,是中心协调器,负责任务调度和资源管理。默认情况下,每个Flink集群只有一个JobManager实例。这会产生单点故障(SPOF):如果JobManager崩溃,则无法提交新程序,正在运行的程序也会失败。通过JobManager的高可用性,…

Vue使用Mockjs插件实现模拟数据

官方文档&#xff1a;Mock.js 一.引言 在前端开发过程中&#xff0c;我们经常会遇到后端接口尚未完成&#xff0c;但前端需要进行页面构建和功能测试的情况。这时候&#xff0c;Mockjs就如同救星一般出现了。Mockjs 是一款能够模拟生成随机数据&#xff0c;拦截 Ajax 请求并返…

Liinux——进程间通信之共享内存与信号量

进程间通信之共享内存与信号量 System V进程间通信 system V 进程通信是一组在 Unix 和类 Unix 系统中用于进程间通信的机制&#xff0c;主要三种方式&#xff1a;共享内存、消息队列与信号量 今天我们一起来对共享内存进行详细的学习&#xff0c;并了解信号量的基本概念 1.…

阿里发布 EchoMimicV2 :从数字脸扩展到数字人 可以通过图片+音频生成半身动画视频

EchoMimicV2 是由阿里蚂蚁集团推出的开源数字人项目&#xff0c;旨在生成高质量的数字人半身动画视频。以下是该项目的简介&#xff1a; 主要功能&#xff1a; 音频驱动的动画生成&#xff1a;EchoMimicV2 能够使用音频剪辑驱动人物的面部表情和身体动作&#xff0c;实现音频与…

node.js nvm 安装和使用

个人笔记记录。 参考文档&#xff1a;https://blog.csdn.net/weixin_45811256/article/details/130860444 1、下载nvm-setup.exe 安装程序 2、将本地的node卸载&#xff0c;然后点击进行安装。 3、安装 node.js 方法一&#xff1a; 去nodejs官网搜索历史版本&#xff0c;找…

js:函数

函数 函数&#xff1a;实现抽取封装&#xff0c;执行特定任务的代码块&#xff0c;方便复用 声明 函数命名规范 尽量小驼峰 前缀应该为动词&#xff0c;如getName、hasName 函数的调用 函数体是函数的构成部分 函数传参 参数列表里的参数叫形参&#xff0c;实际上写的数据叫实…

【大模型】基于LLaMA-Factory的模型高效微调

LLaMA-Factory项目介绍 LLaMA Factory 是一个简单易用且高效的大型语言模型&#xff08;Large Language Model&#xff09;训练与微调平台。通过 LLaMA Factory&#xff0c;可以在无需编写任何代码的前提下&#xff0c;在本地完成上百种预训练模型的微调&#xff0c;框架特性包…

论文笔记 SliceGPT: Compress Large Language Models By Deleting Rows And Columns

欲买桂花同载酒&#xff0c;终不似&#xff0c;少年游。 数学知识 秩&#xff1a; 矩阵中最大线性无关的行/列向量数。行秩与列秩相等。 线性无关&#xff1a;对于N个向量而言&#xff0c;如果任取一个向量 v \textbf{v} v&#xff0c;不能被剩下的N-1个向量通过线性组合的方式…

hadoop_zookeeper详解

Zookeeper秒懂 工作机制特点数据结构应用场景安装选举机制初始化启动无法和Leader保持连接 节点类型监听器原理写数据流程Paxos算法算法流程 客户端命令 Zookeeper 是一个开源的分布式的&#xff0c;为分布式框架提供协调服务的 Apache 项目。 工作机制 Zookeeper是一个基于观察…

MD5算法加密笔记

MD5是常见的摘要算法。 摘要算法&#xff1a; 是指把任意⻓度的输⼊消息数据转化为固定⻓度的输出数据的⼀种密码算法. 摘要算法是 不可逆的, 也就是⽆法解密. 通常⽤来检验数据的完整性的重要技术, 即对数据进⾏哈希计算然后⽐ 较摘要值, 判断是否⼀致. 常⻅的摘要算法有: MD5…

【LeetCode每日一题】——717.1比特与2比特字符

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时空频度】九【代码实现】十【提交结果】 一【题目类别】 数组 二【题目难度】 简单 三【题目编号】 717.1比特与2比特字符 四【题目描述】 有两种特…

ATTCK红队评估实战靶场(二)

http://vulnstack.qiyuanxuetang.net/vuln/?page2 描述&#xff1a;红队实战系列&#xff0c;主要以真实企业环境为实例搭建一系列靶场&#xff0c;通过练习、视频教程、博客三位一体学习。本次红队环境主要Access Token利用、WMI利用、域漏洞利用SMB relay&#xff0c;EWS re…

SpringMVC |(一)SpringMVC概述

文章目录 &#x1f4da;SpringMVC概述&#x1f407;三层架构&#x1f407;异步调用 &#x1f4da;SpringMVC入门案例&#x1f407;入门案例&#x1f407;注意事项 &#x1f4da;小结 学习来源&#xff1a;黑马程序员SSM框架教程_SpringSpringMVCMaven高级SpringBootMyBatisPlus…

uniapp实现APP版本升级

App.vue 直接上代码 <script>export default {methods: {//APP 版本升级Urlupload() {// #ifdef APP-PLUSplus.runtime.getProperty(plus.runtime.appid, (info) > {// 版本号变量持久化存储getApp().globalData.version info.version;this.ToLoadUpdate(info.versi…

visionpro官方示例分析(一) 模板匹配工具 缺陷检测工具

1.需求&#xff1a;找出图像中的这个图形。 2.步骤 使用CogPMAlignTool工具&#xff0c;该工具是模板匹配工具&#xff0c;见名知意&#xff0c;所谓模板匹配工具就是说先使用该工具对一张图像建立模板&#xff0c;然后用这个模板在其他图像上进行匹配&#xff0c;匹配上了就说…