当前位置:   article > 正文

安卓逆向环境检测--模拟器_模拟器检测

模拟器检测

一、通过 android/os/Build 类检测虚拟机

  1. UNEXPORT bool AntiEmulator::check_Build(JNIEnv *env) {
  2. char* sig = "Ljava/lang/String;";
  3. Field* field = new Field("android/os/Build", env);
  4. bool ret = false;
  5. // HARDWARE
  6. jstring HARDWARE = field->get_static_jstring_field("HARDWARE", sig);
  7. char *cHARDWARE = const_cast<char *>(env->GetStringUTFChars(HARDWARE, NULL));
  8. if (Str::strstr(cHARDWARE, "vbox86") != nullptr ||
  9. Str::strstr(cHARDWARE, "nox") != nullptr ||
  10. Str::strstr(cHARDWARE, "ttVM_x86") != nullptr ) {//是模拟器 不通过
  11. LOGI("check_Build => check FINGERPRINT find emulator => FINGERPRINT:%s", cHARDWARE);
  12. ret = true;
  13. }
  14. LOGI("HARDWARE:%s", cHARDWARE);
  15. // FINGERPRINT
  16. jstring FINGERPRINT = field->get_static_jstring_field("FINGERPRINT", sig);
  17. char *cFINGERPRINT = const_cast<char *>(env->GetStringUTFChars(FINGERPRINT, NULL));
  18. if (Str::strstr(cFINGERPRINT, "Android") != nullptr || Str::strstr(cFINGERPRINT, "unknown") != nullptr ||
  19. Str::strstr(cFINGERPRINT, "generic/sdk/generic") != nullptr ||
  20. Str::strstr(cFINGERPRINT, "generic_x86/sdk_x86/generic_x86") != nullptr ||
  21. Str::strstr(cFINGERPRINT, "Andy") != nullptr ||
  22. Str::strstr(cFINGERPRINT, "ttVM_Hdragon") != nullptr ||
  23. Str::strstr(cFINGERPRINT, "generic/google_sdk/generic") != nullptr ||
  24. Str::strstr(cFINGERPRINT, "vbox86p") != nullptr ||
  25. Str::strstr(cFINGERPRINT, "generic/vbox86p/vbox86p") != nullptr) {//是模拟器 不通过
  26. LOGI("check_Build => check FINGERPRINT find emulator => FINGERPRINT:%s", cFINGERPRINT);
  27. ret = true;
  28. }
  29. LOGI("FINGERPRINT:%s", cFINGERPRINT);
  30. // MODEL
  31. jstring MODEL = field->get_static_jstring_field("MODEL", sig);
  32. char *cMODEL = const_cast<char *>(env->GetStringUTFChars(MODEL, NULL));
  33. if (Str::strstr(cMODEL, "google_sdk") != nullptr || Str::strstr(cMODEL, "Emulator") != nullptr ||
  34. Str::strstr(cMODEL, "Droid4X") != nullptr ||
  35. Str::strstr(cMODEL, "TiantianVM") != nullptr ||
  36. Str::strstr(cMODEL, "Andy") != nullptr ||
  37. Str::strstr(cMODEL, "Android SDK built for x86_64") != nullptr ||
  38. Str::strstr(cMODEL, "Android SDK built for x86") != nullptr) {//是模拟器 不通过
  39. LOGI("check_Build => check MODEL find emulator => MODEL:%s", cMODEL);
  40. ret = true;
  41. }
  42. LOGI("MODEL:%s", cMODEL);
  43. // MANUFACTURER
  44. jstring MANUFACTURER = field->get_static_jstring_field("MANUFACTURER", sig);
  45. char *cMANUFACTURER = const_cast<char *>(env->GetStringUTFChars(MANUFACTURER, NULL));
  46. if (Str::strstr(cMANUFACTURER, "Genymotion") != nullptr ||
  47. Str::strstr(cMANUFACTURER, "Andy") != nullptr ||
  48. Str::strstr(cMANUFACTURER, "nox") != nullptr ||
  49. Str::strstr(cMANUFACTURER, "TiantianVM") != nullptr) {//是模拟器 不通过
  50. LOGI("check_Build => check MANUFACTURER find emulator => MANUFACTURER:%s", cMANUFACTURER);
  51. ret = true;
  52. }
  53. LOGI("MANUFACTURER:%s", cMANUFACTURER);
  54. // PRODUCT
  55. jstring PRODUCT = field->get_static_jstring_field("PRODUCT", sig);
  56. char *cPRODUCT = const_cast<char *>(env->GetStringUTFChars(PRODUCT, NULL));
  57. if (Str::strstr(cPRODUCT, "sdk") != nullptr ||
  58. Str::strstr(cPRODUCT, "Andy") != nullptr ||
  59. Str::strstr(cPRODUCT, "Droid4X") != nullptr ||
  60. Str::strstr(cPRODUCT, "nox") != nullptr ||
  61. Str::strstr(cPRODUCT, "vbox86p") != nullptr ) {//是模拟器 不通过
  62. LOGI("check_Build => check PRODUCT find emulator => PRODUCT:%s", cPRODUCT);
  63. ret = true;
  64. }
  65. LOGI("PRODUCT:%s", cPRODUCT);
  66. // BRAND DEVICE
  67. jstring BRAND = field->get_static_jstring_field("BRAND", sig);
  68. char *cBRAND = const_cast<char *>(env->GetStringUTFChars(BRAND, NULL));
  69. jstring DEVICE = field->get_static_jstring_field("DEVICE", sig);
  70. char *cDEVICE = const_cast<char *>(env->GetStringUTFChars(DEVICE, NULL));
  71. if ((Str::strstr(cBRAND, "generic") != nullptr && Str::strstr(cDEVICE, "generic") == cDEVICE) ||
  72. Str::strstr(cBRAND, "Andy") != nullptr ||
  73. Str::strstr(cBRAND, "Droid4X") != nullptr ||
  74. Str::strstr(cBRAND, "nox") != nullptr ||
  75. Str::strstr(cBRAND, "vbox86p") != nullptr ) {//是模拟器 不通过
  76. LOGI("check_Build => check BRAND find emulator => BRAND:%s", cBRAND);
  77. LOGI("check_Build => check DEVICE find emulator => DEVICE:%s", cDEVICE);
  78. ret = true;
  79. }
  80. LOGI("BRAND:%s", cBRAND);
  81. LOGI("DEVICE:%s", cDEVICE);
  82. env->ReleaseStringUTFChars(HARDWARE, cHARDWARE);
  83. env->ReleaseStringUTFChars(FINGERPRINT, cFINGERPRINT);
  84. env->ReleaseStringUTFChars(MODEL, cMODEL);
  85. env->ReleaseStringUTFChars(MANUFACTURER, cMANUFACTURER);
  86. env->ReleaseStringUTFChars(PRODUCT, cPRODUCT);
  87. env->ReleaseStringUTFChars(BRAND, cBRAND);
  88. env->ReleaseStringUTFChars(DEVICE, cDEVICE);
  89. return ret;
  90. }

二、通过检查prop.build文件中的字段来判断是否为模拟器

  1. UNEXPORT bool AntiEmulator::check_prop() {
  2. char tmp[1024] = {0};
  3. // ro.kernel.qemu
  4. File::read_property("ro.kernel.qemu", reinterpret_cast<char *>(&tmp));
  5. if (Str::strcmp(tmp, "1") == 0){
  6. return true;
  7. }
  8. LOGI("check_prop ro.kernel.qemu -> %s", tmp);
  9. // ro.product.model
  10. File::read_property("ro.product.model", reinterpret_cast<char *>(&tmp));
  11. if (Str::strstr(tmp, "sdk") != nullptr || Str::strstr(tmp, "Android SDK") != nullptr){
  12. return true;
  13. }
  14. LOGI("check_prop ro.product.model -> %s", tmp);
  15. // ro.product.cpu.abi
  16. File::read_property("ro.product.cpu.abi", reinterpret_cast<char *>(&tmp));
  17. if (Str::strcmp(tmp, "x86") == 0){
  18. return true;
  19. }
  20. LOGI("check_prop ro.product.cpu.abi -> %s", tmp);
  21. return false;
  22. }

三、检查是否存在一些模拟器框架文件

  1. UNEXPORT void AntiEmulator::check_file() {
  2. char *(path[]) = {
  3. "/system/bin/androVM-prop", //检测androidVM
  4. "/system/bin/microvirt-prop", //检测逍遥模拟器--新版本找不到特征
  5. "/system/lib/libdroid4x.so", //检测海马模拟器
  6. "/system/bin/windroyed", //检测文卓爷模拟器
  7. "/system/bin/nox-prop", //检测夜神模拟器--某些版本找不到特征
  8. "/system/lib/libnoxspeedup.so",//检测夜神模拟器
  9. "/system/bin/ttVM-prop", //检测天天模拟器
  10. "/data/.bluestacks.prop", //检测bluestacks模拟器 51模拟器
  11. "/system/bin/duosconfig", //检测AMIDuOS模拟器
  12. "/system/etc/xxzs_prop.sh", //检测星星模拟器
  13. "/system/etc/mumu-configs/device-prop-configs/mumu.config", //网易MuMu模拟器
  14. "/system/priv-app/ldAppStore", //雷电模拟器
  15. "/system/bin/ldinit", //雷电模拟器
  16. "/system/bin/ldmountsf", //雷电模拟器
  17. "/system/app/AntStore", //小蚁模拟器
  18. "/system/app/AntLauncher", //小蚁模拟器
  19. "vmos.prop", //vmos虚拟机
  20. "fstab.titan", //光速虚拟机
  21. "init.titan.rc", //光速虚拟机
  22. "x8.prop", //x8沙箱和51虚拟机
  23. "/system/lib/libc_malloc_debug_qemu.so", //AVD QEMU
  24. "/system/bin/microvirtd",
  25. "/dev/socket/qemud",
  26. "/dev/qemu_pipe"};
  27. for (int i = 0; i < sizeof(path) / sizeof(char*); i++){
  28. if (Syscall::check_file_or_dir_exists(path[i])){
  29. LOGI("check_file %s file existing", path[i]);
  30. // TODO 风险
  31. }
  32. }
  33. }

四、检测cpu温度,一般模拟器没有此文件:/sys/class/thermal/thermal_zone...

  1. UNEXPORT void AntiEmulator::check_cpu_temp() {
  2. DIR *dirptr = NULL; //当前手机的温度检测,手机下均有thermal_zone文件
  3. int count = 0;
  4. struct dirent *entry;
  5. if ((dirptr = opendir("/sys/class/thermal/")) != NULL) {
  6. while (entry = readdir(dirptr)) {
  7. if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) {
  8. continue;
  9. }
  10. char *tmp = entry->d_name;
  11. if (Str::strstr(tmp, "thermal_zone") != NULL) {
  12. count++;
  13. }
  14. }
  15. closedir(dirptr);
  16. } else {
  17. LOGE("AntiEmulator::check_cpu_temp open thermal fail");
  18. }
  19. if (count == 0){
  20. // TODO 此时为模拟器
  21. }
  22. LOGI("AntiEmulator::check_cpu_temp count=%d", count);
  23. }

五、读取 /proc/cpuinfo,真机一般会获取到hardware

  1. UNEXPORT void AntiEmulator::check_cpu() {
  2. string str = Syscall::readFile((char*)"/proc/cpuinfo");
  3. char* split = (char*)"\n";
  4. string strs = str + split; // 在字符串末尾也加入分隔符,方便截取最后一段
  5. size_t pos = strs.find(split);
  6. while (pos != strs.npos)
  7. {
  8. string temp = strs.substr(0, pos);
  9. if (Str::strstr(const_cast<char *>(temp.c_str()), "Hardware") != NULL){
  10. LOGI("AntiEmulator::check_cpu find %s", temp.c_str());
  11. return;
  12. }
  13. //去掉已分割的字符串,在剩下的字符串中进行分割
  14. strs = strs.substr(pos + 1, strs.size());
  15. pos = strs.find(split);
  16. }
  17. // TODO 没找到 Hardware,说明为模拟器
  18. }

六、读取 /proc/version,模拟器一般有qemu,tencent

  1. UNEXPORT void AntiEmulator::check_version() {
  2. string str = Syscall::readFile((char*)"/proc/version");
  3. char* split = (char*)"\n";
  4. string strs = str + split; // 在字符串末尾也加入分隔符,方便截取最后一段
  5. size_t pos = strs.find(split);
  6. while (pos != strs.npos)
  7. {
  8. string temp = strs.substr(0, pos);
  9. if (Str::strstr(const_cast<char *>(temp.c_str()), "qemu") != NULL ||
  10. Str::strstr(const_cast<char *>(temp.c_str()), "qemu") != NULL){
  11. // TODO 发现模拟器
  12. LOGI("AntiEmulator::check_version find %s", temp.c_str());
  13. return;
  14. }
  15. //去掉已分割的字符串,在剩下的字符串中进行分割
  16. strs = strs.substr(pos + 1, strs.size());
  17. pos = strs.find(split);
  18. }
  19. }

七、检查传感器个数,少于20个认为是模拟器

  1. UNEXPORT void AntiEmulator::check_sensor(JNIEnv *env) {
  2. jobject context = AntiEmulator::getApplicationContext(env);
  3. LOGI("check_sensor context %p", context);
  4. jstring sensor = env->NewStringUTF("sensor");
  5. jobject objService = Method::callMethodObject(env, context,
  6. "android/content/Context",
  7. "getSystemService",
  8. "(Ljava/lang/String;)Ljava/lang/Object;",
  9. sensor);
  10. env->DeleteLocalRef(sensor);
  11. LOGI("check_sensor objService %p", objService);
  12. jobject sensorlist = Method::callMethodObject(env, objService,
  13. "android/hardware/SensorManager",
  14. "getSensorList",
  15. "(I)Ljava/util/List;",
  16. -1);
  17. LOGI("check_sensor sensorlist %p", sensorlist);
  18. jint len = Method::callMethodInt(env, sensorlist, "java/util/List", "size", "()I");
  19. LOGI("check_sensor sensorlist len=%d", len);
  20. if (len < 20){
  21. // todo 传感器少于20 认为当前环境为非真机环境
  22. }
  23. }

八、检查摄像头个数

  1. UNEXPORT void AntiEmulator::check_camera(JNIEnv *env) {
  2. jobject context = AntiEmulator::getApplicationContext(env);
  3. LOGI("check_camera context %p", context);
  4. jstring camera = env->NewStringUTF("camera");
  5. jobject objService = Method::callMethodObject(env, context,
  6. "android/content/Context",
  7. "getSystemService",
  8. "(Ljava/lang/String;)Ljava/lang/Object;",
  9. camera);
  10. env->DeleteLocalRef(camera);
  11. LOGI("check_camera objService %p", objService);
  12. jobjectArray cameralist = static_cast<jobjectArray>(Method::callMethodObject(env, objService,
  13. "android/hardware/camera2/CameraManager",
  14. "getCameraIdList",
  15. "()[Ljava/lang/String;"));
  16. LOGI("check_camera cameralist %p", cameralist);
  17. int len = env->GetArrayLength(cameralist);
  18. LOGI("check_camera cameralist len %d", len);
  19. if (len < 2){
  20. // todo 摄像头少于2 认为当前环境为非真机环境
  21. }
  22. // for (int i = 0; i < len + 1; i++){
  23. // jobject ca = env->GetObjectArrayElement(cameralist, i);
  24. // LOGI("check_camera camera -> %d : %p", i, ca);
  25. // }
  26. }

九、检查mounts文件,检测里面是否包含docker关键字 ,防止一些云手机搞虚拟化,通过使用docker进行挂载

  1. UNEXPORT void AntiEmulator::check_mounts() {
  2. char *(path[]) = {"/proc/mounts", "/proc/self/mountstats", "/proc/self/mountinfo"};
  3. for (int i = 0; i < sizeof(path) / sizeof(char*); i++){
  4. string status = Syscall::readFile(path[i]);
  5. if (status == "null"){
  6. break;
  7. }
  8. size_t pos = status.find("\n");
  9. while (pos != status.npos)
  10. {
  11. string temp = status.substr(0, pos);
  12. if (Str::strstr(const_cast<char *>(temp.c_str()), (char*)"docker") != nullptr){
  13. //TODO 发现docker, 可能存在云手机挂载docker
  14. }
  15. //去掉已分割的字符串,在剩下的字符串中进行分割
  16. status = status.substr(pos + 1, status.size());
  17. pos = status.find("\n");
  18. }
  19. }
  20. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/261806
推荐阅读
相关标签
  

闽ICP备14008679号