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 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 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);
        }
    }

你可能感兴趣的:(VirtualApp 沙箱环境检测)