VirtualApp 沙箱环境检测

upupupuuup

对于 PS 命令检查返回的进程信息,在平行大师、360多开分身等应用是行不通的,因为 ps 只显示了 一个进程相关的信息,所以,可以检测当不存在主进程相关的条目信息时,就判断为多开应用。

public class VA_check {
    private static String TAG = "Wooo_VA";

    /*
    * https://github.com/ysrc/AntiVirtualApp
    * https://github.com/ZaratustraN/Check_VirtualAPK   ->   https://www.jianshu.com/p/216d65d9971e , C++ 代码壳参考~
    *
    *
    *
    * */

    public static void checkVA(Context ctx) {
        checkPid(ctx);
        checkFilesDir(ctx);
        checkInstalledPKG(ctx);
        checkUID();
        checkELF();
    }

    private static void checkELF() {
        // in native
        // 同检测 uid -> "ps | grep libmainNative.so" -> 查看路径
    }

    private static void checkPid(Context ctx) {     // 没用
        int pid = android.os.Process.myPid();
        String proName = getProcessName(ctx, pid);
        Log.i(TAG, "pid -> " + pid + " , processName -> " + proName);
        String pkgName = ctx.getPackageName();
        Log.i(TAG, "pkg name -> " + pkgName);
    }

    private static String getProcessName(Context ctx, int pid) {
        try {
            ActivityManager am = (ActivityManager) ctx.getSystemService(Context.ACTIVITY_SERVICE);
            List<ActivityManager.RunningAppProcessInfo> runn = am.getRunningAppProcesses();
            if (runn != null && !runn.isEmpty()) {
                for (ActivityManager.RunningAppProcessInfo amr : runn) {
                    if (amr.pid == pid) {
                        return amr.processName;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private static void checkFilesDir(Context ctx) {
        String fdir = ctx.getFilesDir().getAbsolutePath();
        Log.i(TAG, "filesDir -> " + fdir);
        int num = fdir.length() - fdir.replace("/", "").length();
        if (num > 8) {
            Log.i(TAG, "May in VA .. slipyer num -> " + num);
        } else {
            Log.i(TAG, "May not in VA .. slipyer num -> " + num);
        }
    }

    private static void checkInstalledPKG(Context ctx) {    // 没用
        int count = 0;
        String pkgName = ctx.getPackageName();
        PackageManager pm = ctx.getPackageManager();
        List<PackageInfo> piL = pm.getInstalledPackages(0);
        for (PackageInfo pi : piL) {
            if (pkgName.equals(pi.packageName)) {
                count++;
            }
        }
        if (count > 1) {
            Log.i(TAG, "May In VA BOX  PKG-> " + count);
        }
        Log.i(TAG, "May not In VA BOX  PKG-> " + count);
    }

    private static void checkUID() {
        String filter = getUidStrFormat();

        if (filter == null) {
            return;
        }
        String result = exec("ps");
        if (result == null || result.isEmpty()) {
            return;
        }

        String[] lines = result.split("\n");
        if (lines.length <= 0) {
            return;
        }

        int exitDirCount = 0;

        for (int i = 0; i < lines.length; i++) {
            if (lines[i].contains(filter)) {
                int pkgStartIndex = lines[i].lastIndexOf(" ");
                String processName = lines[i].substring(pkgStartIndex <= 0 ? 0 : pkgStartIndex + 1, lines[i].length());
                File dataFile = new File(String.format("/data/data/%s", processName, Locale.CHINA));
                if (dataFile.exists()) {
                    exitDirCount++;
                }

            }
        }
        if (exitDirCount > 1) {
            Log.i(TAG, "is IN Virtual App. Dir count -> " + exitDirCount);
        } else {
            Log.i(TAG, "not IN Virtual App. Dir count -> " + exitDirCount);
        }
    }
/*
    same uid processName 0 -> u0_a114
    same uid processName 1 -> 7
    same uid processName 2 -> USER      PID   PPID  VSIZE  RSS   WCHAN            PC  NAME
    same uid processName 2 -> u0_a114   18188 4528  1144388 61428 SyS_epoll_ a945a514 S io.virtualapp:x
    same uid processName 3 -> io.virtualapp:x
    same uid processName 2 -> u0_a114   21331 4528  1544560 161864 SyS_epoll_ a945a514 S io.virtualapp
    same uid processName 3 -> io.virtualapp
    same uid processName 2 -> u0_a114   21485 4528  1193680 75264 futex_wait a942941c S com.xxxx.twobutton
    same uid processName 3 -> com.xxxx.twobutton
    same uid processName 2 -> u0_a114   21508 4528  1139324 56740 SyS_epoll_ a945a514 S com.xxxx.twobutton:ss
    same uid processName 3 -> com.xxxx.twobutton:ss
    same uid processName 2 -> u0_a114   21597 21485 3544   1204  sigsuspend b5a0985c S sh
    same uid processName 3 -> sh
    same uid processName 2 -> u0_a114   21598 21597 4532   1272           0 ad04c6a8 R ps
    same uid processName 3 -> ps
*/


    private static String getUidStrFormat() {
        String filter = exec("cat /proc/self/cgroup");
        if (filter == null || filter.length() == 0) {
            return null;
        }

        int uidStartIndex = filter.lastIndexOf("uid");
        int uidEndIndex = filter.lastIndexOf("/pid");
        if (uidStartIndex < 0) {
            return null;
        }
        if (uidEndIndex <= 0) {
            uidEndIndex = filter.length();
        }

        filter = filter.substring(uidStartIndex + 4, uidEndIndex);
        try {
            String strUid = filter.replaceAll("\n", "");
            if (isNumber(strUid)) {
                int uid = Integer.valueOf(strUid);
                filter = String.format("u0_a%d", uid - 10000);
                return filter;
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    private static boolean isNumber(String str) {
        if (str == null || str.length() == 0) {
            return false;
        }
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    private static String exec(String command) {
        BufferedOutputStream bufferedOutputStream = null;
        BufferedInputStream bufferedInputStream = null;
        Process process = null;
        String outputStr;
        try {
            process = Runtime.getRuntime().exec("sh");
            bufferedOutputStream = new BufferedOutputStream(process.getOutputStream());

            bufferedInputStream = new BufferedInputStream(process.getInputStream());
            bufferedOutputStream.write(command.getBytes());
            bufferedOutputStream.write('\n');
            bufferedOutputStream.flush();
            bufferedOutputStream.close();

            process.waitFor();

            outputStr = getStrFromBufferInputSteam(bufferedInputStream);
            return outputStr;
        } catch (Exception e) {
            return null;
        } finally {
            if (bufferedOutputStream != null) {
                try {
                    bufferedOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bufferedInputStream != null) {
                try {
                    bufferedInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (process != null) {
                process.destroy();
            }
        }
    }

    private static String getStrFromBufferInputSteam(BufferedInputStream bufferedInputStream) {
        if (null == bufferedInputStream) {
            return "";
        }
        int BUFFER_SIZE = 512;
        byte[] buffer = new byte[BUFFER_SIZE];
        StringBuilder result = new StringBuilder();
        try {
            while (true) {
                int read = bufferedInputStream.read(buffer);
                if (read > 0) {
                    result.append(new String(buffer, 0, read));
                }
                if (read < BUFFER_SIZE) {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result.toString();
    }
}

改正后,根据包名判断。

    private static void checkUID(Context ctx) {
        String pkgName = ctx.getPackageName();
        String filter = getUidStrFormat();
        Log.i(TAG, "checkUID uid is -> " + filter);

        if (filter == null) {
            return;
        }
        String result = exec("ps");
        if (result == null || result.isEmpty()) {
            return;
        }

        String[] lines = result.split("\n");
        if (lines.length <= 0) {
            return;
        }

        int exitDirCount = 0;
        int exitRawProcess = 0;

        Log.i(TAG, "checkUID size : " + lines.length);
        for (int i = 0; i < lines.length; i++) {
            Log.i(TAG, "checkUID is -> " + lines[i]);
            if (lines[i].contains(filter)) {
                int pkgStartIndex = lines[i].lastIndexOf(" ");
                String processName = lines[i].substring(pkgStartIndex <= 0 ? 0 : pkgStartIndex + 1, lines[i].length());
                File dataFile = new File(String.format("/data/data/%s", processName, Locale.CHINA));
                if (dataFile.exists()) {
                    exitDirCount++;
                }
                if (processName.contains(pkgName)) {
                    exitRawProcess++;
                }
            }
        }
        if (exitDirCount > 1 || exitRawProcess == 0) {
            Log.i(TAG, "is IN Virtual App. Dir count -> " + exitDirCount + " , rawPro -> " + exitRawProcess);
        } else {
            Log.i(TAG, "not IN Virtual App. Dir count -> " + exitDirCount + " , rawPro -> " + exitRawProcess);
        }
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355

推荐阅读更多精彩内容