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