美团优选风控分析

某团优选app的部分代码.(可以看得出来,检测机器是否root,也检测了是否安装了xp环境),并且在libmtguard.so这个文件内读取了机型的很多信息,java层也获取了很多信息(某团系的so层获取机型信息都在这个so内做的)

public final class DeviceUtil {
    private static int a;
    private static long b;
    private static long c;
    private static long d;
    private static long e;
    private static long f;
    private static LEVEL g;
    private static final String[] h = {"/data/local/su", "/data/local/bin/su", "/data/local/xbin/su", "/system/xbin/su", "/system/bin/su", "/system/bin/.ext/su", "/system/bin/failsafe/su", "/system/sd/xbin/su", "/system/usr/we-need-root/su", "/sbin/su", "/su/bin/su"};
    private static final FileFilter i = new FileFilter() {
        /* class com.meituan.metrics.util.DeviceUtil.AnonymousClass1 */

        public final boolean accept(File file) {
            return Pattern.matches("cpu[0-9]", file.getName());
        }
    };

    public enum LEVEL {
        BEST(4),
        HIGH(3),
        MIDDLE(2),
        LOW(1),
        BAD(-1),
        UN_KNOW(0);
        
        int value;

        private LEVEL(int i) {
            this.value = i;
        }

        public final int getValue() {
            return this.value;
        }
    }

    public static LEVEL a(Context context) {
        if (g != null) {
            return g;
        }
        long d2 = d(context);
        int a2 = a();
        if (d2 <= 0) {
            g = LEVEL.UN_KNOW;
        } else if (d2 > 6442450944L) {
            g = LEVEL.BEST;
        } else if (d2 > IjkMediaMeta.AV_CH_WIDE_RIGHT) {
            g = LEVEL.HIGH;
        } else if (a2 <= 0) {
            g = LEVEL.UN_KNOW;
        } else if (d2 > IjkMediaMeta.AV_CH_WIDE_LEFT && a2 > 4) {
            g = LEVEL.MIDDLE;
        } else if (d2 <= IjkMediaMeta.AV_CH_STEREO_RIGHT || a2 <= 2) {
            g = LEVEL.BAD;
        } else {
            g = LEVEL.LOW;
        }
        return g;
    }

    /* JADX WARNING: Removed duplicated region for block: B:17:0x002c  */
    /* Code decompiled incorrectly, please refer to instructions dump. */
    public static int a() {
        /*
            int r0 = com.meituan.metrics.util.DeviceUtil.a
            if (r0 <= 0) goto L_0x0007
            int r0 = com.meituan.metrics.util.DeviceUtil.a
            return r0
        L_0x0007:
            r0 = 0
            java.lang.String r1 = "/sys/devices/system/cpu/possible"
            int r1 = a(r1)     // Catch:{ Exception -> 0x002a }
            if (r1 != 0) goto L_0x0016
            java.lang.String r1 = "/sys/devices/system/cpu/present"
            int r1 = a(r1)     // Catch:{ Exception -> 0x002a }
        L_0x0016:
            if (r1 != 0) goto L_0x0029
            java.lang.String r1 = "/sys/devices/system/cpu/"
            java.io.File r2 = new java.io.File     // Catch:{ Exception -> 0x002a }
            r2.<init>(r1)     // Catch:{ Exception -> 0x002a }
            java.io.FileFilter r1 = com.meituan.metrics.util.DeviceUtil.i     // Catch:{ Exception -> 0x002a }
            java.io.File[] r1 = r2.listFiles(r1)     // Catch:{ Exception -> 0x002a }
            if (r1 != 0) goto L_0x0028
            goto L_0x002a
        L_0x0028:
            int r1 = r1.length     // Catch:{ Exception -> 0x002a }
        L_0x0029:
            r0 = r1
        L_0x002a:
            if (r0 != 0) goto L_0x002d
            r0 = 1
        L_0x002d:
            com.meituan.metrics.util.DeviceUtil.a = r0
            return r0
        */
        throw new UnsupportedOperationException("Method not decompiled: com.meituan.metrics.util.DeviceUtil.a():int");
    }

    public static boolean b() {
        try {
            for (String str : h) {
                if (new File(str).exists()) {
                    return true;
                }
            }
        } catch (Exception unused) {
        }
        return false;
    }

    public static String c() {
        if (Build.VERSION.SDK_INT >= 21) {
            return TextUtils.join(",", Build.SUPPORTED_ABIS);
        }
        String str = Build.CPU_ABI;
        String str2 = Build.CPU_ABI2;
        if (TextUtils.isEmpty(str2)) {
            return str;
        }
        return str + "," + str2;
    }

    private static int a(String str) {
        Throwable th;
        FileInputStream fileInputStream;
        FileInputStream fileInputStream2 = null;
        try {
            fileInputStream = new FileInputStream(str);
            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"));
                String readLine = bufferedReader.readLine();
                bufferedReader.close();
                if (readLine != null) {
                    if (readLine.matches("0-[\\d]+$")) {
                        int parseInt = Integer.parseInt(readLine.substring(2)) + 1;
                        f.a(fileInputStream);
                        return parseInt;
                    }
                }
                f.a(fileInputStream);
                return 0;
            } catch (IOException unused) {
                fileInputStream2 = fileInputStream;
                f.a(fileInputStream2);
                return 0;
            } catch (Throwable th2) {
                th = th2;
                f.a(fileInputStream);
                throw th;
            }
        } catch (IOException unused2) {
            f.a(fileInputStream2);
            return 0;
        } catch (Throwable th3) {
            th = th3;
            fileInputStream = null;
            f.a(fileInputStream);
            throw th;
        }
    }

    public static String c(Context context) {
        long d2 = d(context);
        return d2 > 0 ? String.valueOf(d2) : "N/A";
    }

    private static long d(Context context) {
        if (d > 0) {
            return d;
        }
        if (Build.VERSION.SDK_INT < 16 || context == null) {
            return b("MemTotal:");
        }
        ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
        ActivityManager activityManager = (ActivityManager) context.getSystemService(PushConstants.INTENT_ACTIVITY_NAME);
        activityManager.getMemoryInfo(memoryInfo);
        d = memoryInfo.totalMem;
        e = memoryInfo.threshold;
        long maxMemory = Runtime.getRuntime().maxMemory();
        if (maxMemory == Long.MAX_VALUE) {
            f = (long) activityManager.getMemoryClass();
        } else {
            f = maxMemory;
        }
        return d;
    }

    private static long b(String str) {
        Throwable th;
        long j = 0;
        if (TextUtils.isEmpty(str)) {
            return 0;
        }
        BufferedReader bufferedReader = null;
        try {
            BufferedReader bufferedReader2 = new BufferedReader(new InputStreamReader(new FileInputStream("/proc/meminfo"), "UTF-8"));
            try {
                String readLine = bufferedReader2.readLine();
                while (true) {
                    if (readLine == null) {
                        break;
                    }
                    Object[] split = readLine.split("\\s+");
                    if (str.equals(split[0])) {
                        j = ((long) Integer.parseInt(split[1])) * 1024;
                        break;
                    }
                    readLine = bufferedReader2.readLine();
                }
                f.a(bufferedReader2);
            } catch (Exception unused) {
                bufferedReader = bufferedReader2;
                f.a(bufferedReader);
                return j;
            } catch (Throwable th2) {
                th = th2;
                bufferedReader = bufferedReader2;
                f.a(bufferedReader);
                throw th;
            }
        } catch (Exception unused2) {
            f.a(bufferedReader);
            return j;
        } catch (Throwable th3) {
            th = th3;
            f.a(bufferedReader);
            throw th;
        }
        return j;
    }

    @SuppressLint({"DefaultLocale"})
    public static JSONObject a(JSONObject jSONObject, Context context) {
        long j;
        try {
            jSONObject.put("deviceLevel", a(context));
            jSONObject.put("MemoryTotal", String.format("%.2f MB", Float.valueOf((((float) d(context)) * 1.0f) / 1048576.0f)));
            Object[] objArr = new Object[1];
            if (Build.VERSION.SDK_INT < 16 || context == null) {
                j = b("MemAvailable:");
            } else {
                ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
                ((ActivityManager) context.getSystemService(PushConstants.INTENT_ACTIVITY_NAME)).getMemoryInfo(memoryInfo);
                j = memoryInfo.availMem;
            }
            objArr[0] = Float.valueOf((1.0f * ((float) j)) / 1048576.0f);
            jSONObject.put("MemoryAvailable", String.format("%.2f MB", objArr));
        } catch (Exception unused) {
        }
        return jSONObject;
    }

    public static String d() {
        long j;
        if (b > 0) {
            j = b;
        } else {
            long j2 = 0;
            for (int i2 = 0; i2 < a(); i2++) {
                long a2 = m.a(e.a("/sys/devices/system/cpu/cpu" + i2 + "/cpufreq/cpuinfo_max_freq"), 0L);
                if (a2 > j2) {
                    j2 = a2;
                }
            }
            b = j2;
            j = j2;
        }
        return j > 0 ? String.valueOf(j) : "N/A";
    }

    public static String e() {
        long j;
        if (c > 0) {
            j = c;
        } else {
            long j2 = Long.MAX_VALUE;
            for (int i2 = 0; i2 < a(); i2++) {
                long a2 = m.a(e.a("/sys/devices/system/cpu/cpu" + i2 + "/cpufreq/cpuinfo_min_freq"), 0L);
                if (a2 < j2 && a2 > 0) {
                    j2 = a2;
                }
            }
            if (j2 == Long.MAX_VALUE) {
                j = 0;
            } else {
                c = j2;
                j = j2;
            }
        }
        return j > 0 ? String.valueOf(j) : "N/A";
    }

    public static String b(Context context) {
        long j;
        if (f > 0) {
            j = f;
        } else {
            d(context);
            j = f;
        }
        return j > 0 ? String.valueOf(j) : "N/A";
    }
}

解决设备指纹

由于安卓系统的开源开放策略导致在安卓内获取机型信息可以获取到非常多,所以这里想要解决设备指纹,可以有两套方案,那就是详细的分析app, 都在哪里读取的系统信息,通过hook的手段修改这些参数,当然也可以在网络发送数据前,未加密的数据进行替换,加密的数据在加密前进行参数替换也是可以的.第二种方案就是通过rom的定制可以实现未root的情况下实现一键改机。本文中采用的是第二种方案,定制rom + 长连接+ 尽可能的模拟真实用户访问 直到不封账号,不封设备,不封IP 为止.

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
本文根据“第八届中国系统架构师大会”演讲内容整理而成。 背景 美团最初以团购的形式出现,到现在有了很大的业务形态转变。尤其是经过与大众点评的业务融合,从单一业务发展成了覆盖到店餐饮、到店综合、猫眼、外卖、酒店、旅游等多个垂直领域的综合性电商,并且在各个领域都处于行业领先的地位。在这背后,美团点评不仅面临激烈的行业竞争,还有黑色产业(以下简称“黑产”)带来的各种风险,因为我们的业务有这样一些特点: • 品类多、覆盖面广:包括几乎所有吃喝玩乐服务,其中不乏容易被销赃的品类。 • 用户多、商户多:美团点评拥有6亿以上用户,400万以上合作商家,覆盖了很大部分国内网民和商户。 • 交易高频:每日订单峰值突破千万。 美团点评对黑产有着巨大的吸引力,归纳起来在这些方面尤其突出: • 用户作弊:大家常说的“薅羊毛”,用户为了骗取促销优惠的作弊行为。 • 商家刷单:常见的有刷排名、刷销量、刷好评等违反商家平台协议的行为。 • 账户和支付安全:公民信息盗用形势已经十分严峻,黑产从业者会在电商平台上盗取用户的余额,或使用他人支付信息来消费。 这些行为严重侵害平台用户和商户的利益、扰乱正常交易秩序,处理结果的好坏将决定整个业务的成败。所以美团点评需要一套灵活高效的风险控制系统和工作机制来防控这些风险。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

signature=

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值