[
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n.externalNativeBuild\n"
  },
  {
    "path": ".idea/compiler.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <resourceExtensions />\n    <wildcardResourcePatterns>\n      <entry name=\"!?*.java\" />\n      <entry name=\"!?*.form\" />\n      <entry name=\"!?*.class\" />\n      <entry name=\"!?*.groovy\" />\n      <entry name=\"!?*.scala\" />\n      <entry name=\"!?*.flex\" />\n      <entry name=\"!?*.kt\" />\n      <entry name=\"!?*.clj\" />\n      <entry name=\"!?*.aj\" />\n    </wildcardResourcePatterns>\n    <annotationProcessing>\n      <profile default=\"true\" name=\"Default\" enabled=\"false\">\n        <processorPath useClasspath=\"true\" />\n      </profile>\n    </annotationProcessing>\n  </component>\n</project>"
  },
  {
    "path": ".idea/copyright/profiles_settings.xml",
    "content": "<component name=\"CopyrightManager\">\n  <settings default=\"\" />\n</component>"
  },
  {
    "path": ".idea/gradle.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"GradleSettings\">\n    <option name=\"linkedExternalProjectsSettings\">\n      <GradleProjectSettings>\n        <option name=\"distributionType\" value=\"DEFAULT_WRAPPED\" />\n        <option name=\"externalProjectPath\" value=\"$PROJECT_DIR$\" />\n        <option name=\"modules\">\n          <set>\n            <option value=\"$PROJECT_DIR$\" />\n            <option value=\"$PROJECT_DIR$/app\" />\n          </set>\n        </option>\n        <option name=\"resolveModulePerSourceSet\" value=\"false\" />\n      </GradleProjectSettings>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/misc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"EntryPointsManager\">\n    <entry_points version=\"2.0\" />\n  </component>\n  <component name=\"NullableNotNullManager\">\n    <option name=\"myDefaultNullable\" value=\"android.support.annotation.Nullable\" />\n    <option name=\"myDefaultNotNull\" value=\"android.support.annotation.NonNull\" />\n    <option name=\"myNullables\">\n      <value>\n        <list size=\"4\">\n          <item index=\"0\" class=\"java.lang.String\" itemvalue=\"org.jetbrains.annotations.Nullable\" />\n          <item index=\"1\" class=\"java.lang.String\" itemvalue=\"javax.annotation.Nullable\" />\n          <item index=\"2\" class=\"java.lang.String\" itemvalue=\"edu.umd.cs.findbugs.annotations.Nullable\" />\n          <item index=\"3\" class=\"java.lang.String\" itemvalue=\"android.support.annotation.Nullable\" />\n        </list>\n      </value>\n    </option>\n    <option name=\"myNotNulls\">\n      <value>\n        <list size=\"4\">\n          <item index=\"0\" class=\"java.lang.String\" itemvalue=\"org.jetbrains.annotations.NotNull\" />\n          <item index=\"1\" class=\"java.lang.String\" itemvalue=\"javax.annotation.Nonnull\" />\n          <item index=\"2\" class=\"java.lang.String\" itemvalue=\"edu.umd.cs.findbugs.annotations.NonNull\" />\n          <item index=\"3\" class=\"java.lang.String\" itemvalue=\"android.support.annotation.NonNull\" />\n        </list>\n      </value>\n    </option>\n  </component>\n  <component name=\"ProjectLevelVcsManager\" settingsEditedManually=\"false\">\n    <OptionsSetting value=\"true\" id=\"Add\" />\n    <OptionsSetting value=\"true\" id=\"Remove\" />\n    <OptionsSetting value=\"true\" id=\"Checkout\" />\n    <OptionsSetting value=\"true\" id=\"Update\" />\n    <OptionsSetting value=\"true\" id=\"Status\" />\n    <OptionsSetting value=\"true\" id=\"Edit\" />\n    <ConfirmationsSetting value=\"0\" id=\"Add\" />\n    <ConfirmationsSetting value=\"0\" id=\"Remove\" />\n  </component>\n  <component name=\"ProjectRootManager\" version=\"2\" languageLevel=\"JDK_1_7\" default=\"true\" assert-keyword=\"true\" jdk-15=\"true\" project-jdk-name=\"1.8\" project-jdk-type=\"JavaSDK\">\n    <output url=\"file://$PROJECT_DIR$/build/classes\" />\n  </component>\n  <component name=\"ProjectType\">\n    <option name=\"id\" value=\"Android\" />\n  </component>\n</project>"
  },
  {
    "path": ".idea/modules.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n      <module fileurl=\"file://$PROJECT_DIR$/Anti-Emulator.iml\" filepath=\"$PROJECT_DIR$/Anti-Emulator.iml\" />\n      <module fileurl=\"file://$PROJECT_DIR$/app/app.iml\" filepath=\"$PROJECT_DIR$/app/app.iml\" />\n    </modules>\n  </component>\n</project>"
  },
  {
    "path": ".idea/runConfigurations.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <option name=\"ignoredProducers\">\n      <set>\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer\" />\n        <option value=\"org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer\" />\n      </set>\n    </option>\n  </component>\n</project>"
  },
  {
    "path": ".idea/vcs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping directory=\"$PROJECT_DIR$\" vcs=\"Git\" />\n  </component>\n</project>"
  },
  {
    "path": "README.md",
    "content": "# Anti-Emulator\nAndroid Anti Emulator \n基于模拟器特征文件的检测方式，利用jni和java共同实现。\n\n####原理分析\n[文章地址](http://mp.weixin.qq.com/s/sl33d2pnyLMJ-fUY_DfBDw)\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.4.1)\n\nadd_library(native-lib SHARED src/main/cpp/native-lib.cpp )\n\nfind_library(log-lib log )\n\ntarget_link_libraries(native-lib ${log-lib} )\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.0\"\n    defaultConfig {\n        applicationId \"com.qtfreet.anticheckemulator\"\n        minSdkVersion 15\n        targetSdkVersion 25\n        versionCode 1\n        versionName \"1.0\"\n        testInstrumentationRunner \"android.support.test.runner.AndroidJUnitRunner\"\n        externalNativeBuild {\n            cmake {\n                cppFlags \"-fexceptions\"\n                cppFlags \"-O3\"\n            }\n        }\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n    externalNativeBuild {\n        cmake {\n            path \"CMakeLists.txt\"\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {\n        exclude group: 'com.android.support', module: 'support-annotations'\n    })\n    compile 'com.android.support:appcompat-v7:25.0.1'\n    testCompile 'junit:junit:4.12'\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in D:\\sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "app/src/androidTest/java/com/qtfreet/anticheckemulator/ExampleInstrumentedTest.java",
    "content": "package com.qtfreet.anticheckemulator;\n\nimport android.content.Context;\nimport android.support.test.InstrumentationRegistry;\nimport android.support.test.runner.AndroidJUnit4;\n\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\n\nimport static org.junit.Assert.*;\n\n/**\n * Instrumentation test, which will execute on an Android device.\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\n@RunWith(AndroidJUnit4.class)\npublic class ExampleInstrumentedTest {\n    @Test\n    public void useAppContext() throws Exception {\n        // Context of the app under test.\n        Context appContext = InstrumentationRegistry.getTargetContext();\n\n        assertEquals(\"com.qtfreet.anticheckemulator\", appContext.getPackageName());\n    }\n}\n"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.qtfreet.anticheckemulator\">\n\n    <uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\" />\n    <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />\n    <uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />\n    <uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />\n    <uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/cpp/native-lib.cpp",
    "content": "#include <jni.h>\n#include <string>\n#include <sys/stat.h>\n#include <sys/system_properties.h>\n#include <android/log.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <sys/socket.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#include <errno.h>\n#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, \"qtfreet00\", __VA_ARGS__)\n\n\nextern \"C\" {\n\nint i = 0;\n\nchar *jstringToChar(JNIEnv *env, jstring jstr) {\n    if (jstr == NULL) {\n        return NULL;\n\n    }\n    char *rtn = new char;\n    jclass clsstring = env->FindClass(\"java/lang/String\");\n    jstring strencode = env->NewStringUTF(\"utf-8\");\n    jmethodID mid = env->GetMethodID(clsstring, \"getBytes\", \"(Ljava/lang/String;)[B\");\n    jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);\n    jsize alen = env->GetArrayLength(barr);\n    jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);\n    if (alen > 0) {\n        rtn = (char *) malloc(alen + 1);\n        memcpy(rtn, ba, alen);\n        rtn[alen] = 0;\n\n    } else {\n        rtn = \"\";\n\n    }\n\n    /**资源清理**/\n    env->ReleaseByteArrayElements(barr, ba, 0);\n    if (clsstring != NULL) {\n        env->DeleteLocalRef(clsstring);\n        clsstring = NULL;\n\n    }\n    if (strencode != NULL) {\n        env->DeleteLocalRef(strencode);\n        strencode = NULL;\n\n    }\n    mid = NULL;\n    return rtn;\n}\n\njstring chartoJstring(JNIEnv *env, const char *pat) {\n    jclass strClass = env->FindClass(\"Ljava/lang/String;\");\n    jmethodID ctorID = env->GetMethodID(strClass, \"<init>\", \"([BLjava/lang/String;)V\");\n    jbyteArray bytes = env->NewByteArray(strlen(pat));\n    env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte *) pat);\n    jstring encoding = env->NewStringUTF(\"utf-8\");\n    return (jstring) env->NewObject(strClass, ctorID, bytes, encoding);\n}\n\n\njobject getApplication(JNIEnv *env) {\n    jclass localClass = env->FindClass(\"android/app/ActivityThread\");\n    if (localClass != NULL) {\n        jmethodID getapplication = env->GetStaticMethodID(localClass, \"currentApplication\",\n                                                          \"()Landroid/app/Application;\");\n        if (getapplication != NULL) {\n            jobject application = env->CallStaticObjectMethod(localClass, getapplication);\n            return application;\n        }\n        return NULL;\n    }\n    return NULL;\n}\n\n\nchar *verifySign(JNIEnv *env) {\n    //此处用于获取app签名\n    jobject context = getApplication(env);\n    jclass activity = env->GetObjectClass(context);\n    // 得到 getPackageManager 方法的 ID\n    jmethodID methodID_func = env->GetMethodID(activity, \"getPackageManager\",\n                                               \"()Landroid/content/pm/PackageManager;\");\n    // 获得PackageManager对象\n    jobject packageManager = env->CallObjectMethod(context, methodID_func);\n    jclass packageManagerclass = env->GetObjectClass(packageManager);\n    //得到 getPackageName 方法的 ID\n    jmethodID methodID_pack = env->GetMethodID(activity, \"getPackageName\", \"()Ljava/lang/String;\");\n    //获取包名\n    jstring name_str = static_cast<jstring>(env->CallObjectMethod(context, methodID_pack));\n    // 得到 getPackageInfo 方法的 ID\n    jmethodID methodID_pm = env->GetMethodID(packageManagerclass, \"getPackageInfo\",\n                                             \"(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;\");\n    // 获得应用包的信息\n    jobject package_info = env->CallObjectMethod(packageManager, methodID_pm, name_str, 64);\n    // 获得 PackageInfo 类\n    jclass package_infoclass = env->GetObjectClass(package_info);\n    // 获得签名数组属性的 ID\n    jfieldID fieldID_signatures = env->GetFieldID(package_infoclass, \"signatures\",\n                                                  \"[Landroid/content/pm/Signature;\");\n    // 得到签名数组，待修改\n    jobject signatur = env->GetObjectField(package_info, fieldID_signatures);\n    jobjectArray signatures = reinterpret_cast<jobjectArray>(signatur);\n    // 得到签名\n    jobject signature = env->GetObjectArrayElement(signatures, 0);\n    // 获得 Signature 类，待修改\n    jclass signature_clazz = env->GetObjectClass(signature);\n    //获取sign\n    jmethodID toCharString = env->GetMethodID(signature_clazz, \"toCharsString\",\n                                              \"()Ljava/lang/String;\");\n    //获取签名字符；或者其他进行验证操作\n    jstring signstr = static_cast<jstring>(env->CallObjectMethod(signature, toCharString));\n    char *ch = jstringToChar(env, signstr);\n    //输入签名字符串，这里可以进行相关验证\n    return ch;\n}\n\n\njstring getDeviceID(JNIEnv *env, jobject instance) {\n    jobject mContext = getApplication(env);\n    if (mContext == NULL) {\n        return (env)->NewStringUTF(\"unknown\");\n    }\n    jclass cls_context = (env)->FindClass(\"android/content/Context\");\n    if (cls_context == 0) {\n        return (env)->NewStringUTF(\"unknown\");\n    }\n    jmethodID getSystemService = (env)->GetMethodID(cls_context,\n                                                    \"getSystemService\",\n                                                    \"(Ljava/lang/String;)Ljava/lang/Object;\");\n    if (getSystemService == 0) {\n        return (env)->NewStringUTF(\"unknown\");\n    }\n    jfieldID TELEPHONY_SERVICE = (env)->GetStaticFieldID(cls_context,\n                                                         \"TELEPHONY_SERVICE\", \"Ljava/lang/String;\");\n    if (TELEPHONY_SERVICE == 0) {\n        return (env)->NewStringUTF(\"unknown\");\n    }\n    jobject str = (env)->GetStaticObjectField(cls_context, TELEPHONY_SERVICE);\n    jobject telephonymanager = (env)->CallObjectMethod(mContext,\n                                                       getSystemService, str);\n    if (telephonymanager == 0) {\n        return (env)->NewStringUTF(\"unknown\");\n    }\n    jclass cls_tm = (env)->FindClass(\"android/telephony/TelephonyManager\");\n    if (cls_tm == 0) {\n        return (env)->NewStringUTF(\"unknown\");\n    }\n    jmethodID getDeviceId = (env)->GetMethodID(cls_tm, \"getDeviceId\",\n                                               \"()Ljava/lang/String;\");\n    if (getDeviceId == 0) {\n        return (env)->NewStringUTF(\"unknown\");\n    }\n    jstring deviceid = static_cast<jstring>((env)->CallObjectMethod(telephonymanager, getDeviceId));\n    char *ch = jstringToChar(env, deviceid);\n    return deviceid;\n}\n\nchar *getCpuInfo() { //获取cpu型号\n    //此处在测试时去判断cpu型号是否是intel core，至强或者奔腾，AMD系列，x86手机cpu型号为intel atom，arm一般为联发科，高通，麒麟等等\n    //如是判断为前者，则认为当前环境为模拟器\n\n    char *info = new char[128];\n    memset(info, 0, 128);\n//    char *res = new char[256];\n//    memset(res,0,256);\n    char *split = \":\";\n    char *cmd = \"/proc/cpuinfo\";\n    FILE *ptr;\n    if ((ptr = fopen(cmd, \"r\")) != NULL) {\n        while (fgets(info, 128, ptr)) {\n            char *tmp = NULL;\n            //去掉换行符\n            if (tmp = strstr(info, \"\\n\"))\n                *tmp = '\\0';\n            //去掉回车符\n            if (tmp = strstr(info, \"\\r\"))\n                *tmp = '\\0';\n            if (strstr(info,\n                       \"Hardware\")) {  //真机一般会获取到hardware，示例：Qualcomm MSM 8974 HAMMERHEAD (Flattened Device Tree)\n                strtok(info, split);\n                char *s = strtok(NULL, split);\n                return s;\n            } else if (strstr(info,\n                              \"model name\")) { //测试了一个模拟器，取到的是model_name，示例：Intel(R) Core(TM) i5-4590 CPU @ 3.30GHz\n                strtok(info, split);\n                char *s = strtok(NULL, split);\n                //x86架构的移动处理器为Intel(R) Atom(TM)\n                if (strstr(s, \"Intel(R) Core(TM)\") || strstr(s, \"Intel(R) Pentium(R)\") ||\n                    strstr(s, \"Intel(R) Xeon(R)\") ||\n                    strstr(s, \"AMD\")) { //分别为最常见的酷睿，奔腾，至强，AMD处理器\n\n                }\n                LOGE(\"the cpu native info is %s\", s);\n                return s;\n            }\n        }\n    } else {\n        LOGE(\"NULLLLLLLLL\");\n    }\n}\n\nchar *\ngetVersionInfo() {\n//获取设备版本，真机示例：Linux version 3.4.0-cyanogenmod (ls@ywk) (gcc version 4.7 (GCC) ) #1 SMP PREEMPT Tue Apr 12 11:38:13 CST 2016\n// 海马玩：   Linux version 3.4.0-qemu+ (droid4x@CA) (gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) ) #25 SMP PREEMPT Tue Sep 22 15:50:48\n    //腾讯模拟器中包含了tencent字眼\n    char *info = new char[256];\n    memset(info, 0, 256);\n    char *cmd = \"/proc/version\";\n    FILE *ptr;\n    if ((ptr = fopen(cmd, \"r\")) != NULL) {\n        while (fgets(info, 256, ptr)) {\n            char *tmp = NULL;\n            if (tmp = strstr(info, \"\\n\"))\n                *tmp = '\\0';\n            //去掉回车符\n            if (tmp = strstr(info, \"\\r\"))\n                *tmp = '\\0';\n            //包含qemu+或者tencent均为模拟器\n            LOGE(\"the kernel info is %s\", info);\n            return info;\n        }\n    } else {\n        LOGE(\"NULLLLLLLLL\");\n        return NULL;\n    }\n}\n\nvoid antiFile(char *res) {\n    struct stat buf;\n    int result = stat(res, &buf) == 0 ? 1 : 0;\n    if (result) {\n        LOGE(\"%s  exsits, emulator!\", res);\n        //     kill(getpid(),SIGKILL);\n        i++;\n    }\n}\n\nvoid antiProperty(char *res) {\n    char buff[PROP_VALUE_MAX];\n    memset(buff, 0, PROP_VALUE_MAX);\n    int result =\n            __system_property_get(res, (char *) &buff) > 0 ? 1 : 0; //返回命令行内容的长度\n    if (result != 0) {\n        LOGE(\"%s %s  exsits, emulator!\", res, buff);\n        //  kill(getpid(),SIGKILL);\n        i++;\n    }\n}\n\nvoid antiPropertyValueContains(char *res, char *val) {\n    char buff[PROP_VALUE_MAX + 1];\n    memset(buff, 0, PROP_VALUE_MAX + 1);\n    int lman = __system_property_get(res, buff);\n    if (lman > 0) {\n        if (strstr(buff, val) != NULL) { // match!\n            LOGE(\"%s property value contains %s . Emulator!\", res, val);\n            i++;\n        }\n    }\n}\n\nvoid getDeviceInfo() {\n    char buff[PROP_VALUE_MAX];\n    memset(buff, 0, PROP_VALUE_MAX);\n    __system_property_get(\"ro.product.name\", (char *) &buff);\n    LOGE(\"the model name is %s\", buff);\n    if (!strcmp(buff, \"ChangWan\")) {\n        //  kill(getpid(),SIGKILL);\n\n    } else if (!strcmp(buff, \"Droid4X\")) {                     //非0均为模拟器\n        //  kill(getpid(),SIGKILL);\n    } else if (!strcmp(buff, \"lgshouyou\")) {\n        // kill(getpid(),SIGKILL);\n    } else if (!strcmp(buff, \"nox\")) {\n        //  kill(getpid(),SIGKILL);\n    } else if (!strcmp(buff, \"ttVM_Hdragon\")) {\n        //  kill(getpid(),SIGKILL);\n    }\n\n}\n\n\nchar *SocketTest(char *c) {\n    struct sockaddr_in serv_addr;\n    char buff[1024];\n    char res[4096];\n    memset(res, 0, 4096);\n    memset(buff, 0, 1024);\n    memset(&serv_addr, 0, sizeof(serv_addr));\n\n    char *addr = \"107.151.180.166\";\n    int socketfd = socket(AF_INET, SOCK_STREAM, 0);\n    if (socketfd == -1) {\n        LOGE(\"create error\");\n        LOGE(\"error (errno=%d)\", errno);\n        exit(1);\n    }\n    serv_addr.sin_family = AF_INET;\n    serv_addr.sin_port = htons(6666);\n    serv_addr.sin_addr.s_addr = inet_addr(addr);\n    if (serv_addr.sin_addr.s_addr == INADDR_NONE) {\n        struct hostent *host = gethostbyname(addr);\n        if (host == NULL) {\n            LOGE(\"error (errno=%d)\", errno);\n            exit(1);\n        }\n        serv_addr.sin_addr.s_addr = ((struct in_addr *) host->h_addr)->s_addr;\n    }\n    memset(serv_addr.sin_zero, 0, sizeof(serv_addr.sin_zero));\n    int conn = connect(socketfd, (struct sockaddr *) &serv_addr, sizeof(struct sockaddr));\n    if (conn == -1) {\n        LOGE(\"connect error\");\n        LOGE(\"error (errno=%d)\", errno);\n        exit(1);\n    }\n    int sen = send(socketfd, c, strlen(c), 0);\n    if (sen == -1) {\n        LOGE(\"send errorrr\");\n        LOGE(\"error (errno=%d)\", errno);\n        exit(1);\n    }\n    while (recv(socketfd, buff, 1023, 0) > 0) {\n        LOGE(\"%s\", buff);\n        strcpy(res, buff);\n    }\n    close(socketfd);\n    LOGE(\"send successssss\");\n    return res;\n\n}\n\n/*逍遥模拟器\n * 12-13 12:20:58.671 1615-1615/? E/qtfreet00: the /system/bin/microvirt-prop is exist\n12-13 12:20:58.671 1615-1615/? E/qtfreet00: the /system/bin/microvirtd is exist\n12-13 12:20:58.671 1615-1615/? E/qtfreet00: the init.svc.vbox86-setup result is stopped\n12-13 12:20:58.671 1615-1615/? E/qtfreet00: the init.svc.microvirtd result is running*/\n\njint check(JNIEnv *env, jobject instance) {\n\n    antiFile(\"/system/bin/qemu_props\"); //检测原生模拟器\n    // antiFile(\"/system/bin/qemud\");  //小米会检测出此项\n    antiFile(\"/system/bin/androVM-prop\");\n    antiFile(\"/system/bin/microvirt-prop\");//逍遥\n    antiFile(\"/system/lib/libdroid4x.so\"); //海马玩\n    antiFile(\"/system/bin/windroyed\");//文卓爷\n    antiFile(\"/system/bin/microvirtd\");//逍遥\n    antiFile(\"/system/bin/nox-prop\"); //夜神\n    antiFile(\"/system/bin/ttVM-prop\"); //天天\n    antiFile(\"/system/bin/droid4x-prop\"); //海马玩\n    antiFile(\"/data/.bluestacks.prop\");//bluestacks\n    antiProperty(\"init.svc.vbox86-setup\"); //基于vitrualbox\n    antiProperty(\"init.svc.droid4x\"); //海马玩\n    antiProperty(\"init.svc.qemud\");\n    antiProperty(\"init.svc.su_kpbs_daemon\");\n    antiProperty(\"init.svc.noxd\"); //夜神\n    antiProperty(\"init.svc.ttVM_x86-setup\"); //天天\n    antiProperty(\"init.svc.xxkmsg\");\n    antiProperty(\"init.svc.microvirtd\");//逍遥\n//    antiProperty(\"ro.secure\");   //检测selinux是否被关闭，一般手机均开启此选项\n    antiProperty(\"ro.kernel.android.qemud\");\n    //  antiProperty(\"ro.kernel.qemu.gles\"); //三星SM-G5500误报此项\n    antiProperty(\"androVM.vbox_dpi\");\n    antiProperty(\"androVM.vbox_graph_mode\");\n    antiPropertyValueContains(\"ro.product.manufacturer\",\n                              \"Genymotion\"); // Genymotion check ,thx alinbaturn\n    return i;\n}\n\njstring getCpuinfo(JNIEnv *env, jobject instance) {\n\n    char *res = getCpuInfo();\n\n    return env->NewStringUTF(res);\n}\n\njstring getKernelVersion(JNIEnv *env, jobject /* this */) {\n\n    char *res = getVersionInfo();\n\n    return env->NewStringUTF(res);\n}\n\njstring getApkSign(JNIEnv *env, jobject /* this */) {\n\n    char *res = verifySign(env);\n\n    return env->NewStringUTF(res);\n}\nstatic const char *gClassName = \"com/qtfreet/anticheckemulator/emulator/JniAnti\";\nstatic JNINativeMethod gMethods[] = {\n        {\"getApkSign\",       \"()Ljava/lang/String;\", (void *) getApkSign},\n        {\"getKernelVersion\", \"()Ljava/lang/String;\", (void *) getKernelVersion},\n        {\"getCpuinfo\",       \"()Ljava/lang/String;\", (void *) getCpuinfo},\n        {\"getDeviceID\",      \"()Ljava/lang/String;\", (void *) getDeviceID},\n        {\"checkAntiFile\",    \"()I\",                  (void *) check},\n};\n\nstatic int registerNativeMethods(JNIEnv *env, const char *className,\n                                 JNINativeMethod *gMethods, int numMethods) {\n    jclass clazz;\n    clazz = env->FindClass(className);\n    if (clazz == NULL) {\n        return JNI_FALSE;\n    }\n    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {\n        return JNI_FALSE;\n    }\n    return JNI_TRUE;\n}\nJNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {\n    JNIEnv *env = NULL;\n    jint result = -1;\n\n    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {\n        return -1;\n    }\n    //目前已知问题，检测/sys/class/thermal/和bluetooth-jni.so不稳定，存在兼容性问题\n    getDeviceInfo();\n\n    if (registerNativeMethods(env, gClassName, gMethods,\n                              sizeof(gMethods) / sizeof(gMethods[0])) == JNI_FALSE) {\n        return -1;\n    }\n\n    return JNI_VERSION_1_6;\n}\n}\n"
  },
  {
    "path": "app/src/main/java/com/qtfreet/anticheckemulator/MainActivity.java",
    "content": "package com.qtfreet.anticheckemulator;\n\nimport android.opengl.GLSurfaceView;\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\nimport android.text.TextUtils;\nimport android.util.Log;\nimport android.widget.TextView;\n\nimport com.qtfreet.anticheckemulator.emulator.Check;\nimport com.qtfreet.anticheckemulator.emulator.JniAnti;\nimport com.qtfreet.anticheckemulator.utils.Util;\n\npublic class MainActivity extends AppCompatActivity {\n\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        TextView tv = (TextView) findViewById(R.id.sample_text);\n        GLSurfaceView gl = (GLSurfaceView) findViewById(R.id.hwGPU);\n        gl.setRenderMode(0);  //此处是为了加载显卡信息\n        Log.e(\"qtfreet000\", \"APK签名：\" + JniAnti.getApkSign());\n        Log.e(\"qtfreet000\", \"程序包名：\" + Check.getPackageName(this));\n        Log.e(\"qtfreet000\", \"CPU信息：\" + JniAnti.getCpuinfo());\n        Log.e(\"qtfreet000\", \"CPU频率：\" + Check.getCpuFrequency());\n        Log.e(\"qtfreet000\", \"CPU核心数量：\" + Check.getCpuCore());\n        Log.e(\"qtfreet000\", \"内核信息：\" + JniAnti.getKernelVersion());\n        Log.e(\"qtfreet000\", \"设备ID：\" + JniAnti.getDeviceID());\n        Log.e(\"qtfreet000\", \"已安装App：\" + Check.getInstalledApps(this));\n        Log.e(\"qtfreet000\", \"MAC地址：\" + Check.getMacAddress(this));\n        Log.e(\"qtfreet000\", \"内存大小：\" + Check.getMemorySize());\n        // Log.e(\"qtfreet000\", \"存在重力感应器：\" + Check.checkGravity(this));  //这点不靠谱，很多手机还是检测不出来\n        Log.e(\"qtfreet000\", \"设备厂商：\" + Check.getModelBrand());\n        Log.e(\"qtfreet000\", \"设备型号：\" + Check.getModelName());\n        Log.e(\"qtfreet000\", \"支持GPS：\" + Check.hasGPSDevice(this));\n        Log.e(\"qtfreet000\", \"支持多点触控：\" + Check.checkMultiTouch(this));\n        Log.e(\"qtfreet000\", \"电池温度：\" + Check.getBatteryTemp(this));\n        Log.e(\"qtfreet000\", \"电池电压：\" + Check.getBatteryVolt(this));\n        Log.e(\"qtfreet000\", \"模拟器特征数量：\" + JniAnti.checkAntiFile());\n\n\n        String cpu = JniAnti.getCpuinfo();\n        String cpuFreq = Util.convertSize(Check.getCpuMaxFrequency());\n        String kernel = JniAnti.getKernelVersion();\n        boolean gravity = Check.checkGravity(this);\n        String temp = Check.getBatteryTemp(this);\n        String volt = Check.getBatteryVolt(this);\n        int check = JniAnti.checkAntiFile();\n        boolean gps = Check.hasGPSDevice(this);\n        StringBuilder sb = new StringBuilder();\n        if (cpu.contains(\"Genuine Intel(R)\") || cpu.contains(\"Intel(R) Core(TM)\") || cpu.contains(\"Intel(R) Pentium(R)\") || cpu.contains(\"Intel(R) Xeon(R)\") || cpu.contains(\"AMD\")) {\n            sb.append(\"特征一：\" + cpu + \"\\n\");\n        }\n        if (kernel.contains(\"qemu+\") || kernel.contains(\"tencent\") || kernel.contains(\"virtualbox\")) {\n            sb.append(\"特征二：\" + kernel + \"\\n\");\n        }\n        if (gravity == false) {\n            sb.append(\"特征三：\" + \"无重力感应器\\n\");\n        }\n        if (TextUtils.isEmpty(temp)) {\n            sb.append(\"特征四：\" + \"无电池温度\\n\");\n        }\n        if (TextUtils.isEmpty(volt)) {\n            sb.append(\"特征五：\" + \"无电池电压\\n\");\n        }\n        if (check > 0) {\n            sb.append(\"特征六：\" + \"模拟器特征文件\\n\");\n        }\n        if (gps == false) {\n            sb.append(\"特征七：\" + \"无gps\\n\");\n        }\n        if (cpuFreq.equals(\"0M\")) {\n            sb.append(\"特征八：\" + \"cpu无频率\\n\");\n        }\n        tv.setText(sb.toString());\n\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/qtfreet/anticheckemulator/emulator/Check.java",
    "content": "package com.qtfreet.anticheckemulator.emulator;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.content.pm.PackageInfo;\nimport android.hardware.Sensor;\nimport android.hardware.SensorManager;\nimport android.location.LocationManager;\nimport android.net.wifi.WifiInfo;\nimport android.net.wifi.WifiManager;\nimport android.os.Build;\nimport android.telephony.TelephonyManager;\n\nimport com.qtfreet.anticheckemulator.utils.Util;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileFilter;\nimport java.io.FileNotFoundException;\nimport java.io.FileReader;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.regex.Pattern;\n\nimport static android.content.Context.SENSOR_SERVICE;\nimport static android.hardware.Sensor.TYPE_GRAVITY;\nimport static com.qtfreet.anticheckemulator.utils.Util.tempToStr;\n\n/**\n * Created by qtfreet on 2016/12/22.\n */\n\npublic class Check {\n    private final static String CPUFREQ_CPUINFO_MAX_FREQ = \"/cpufreq/cpuinfo_max_freq\";\n    private final static String CPUFREQ_CPUINFO_MIN_FREQ = \"/cpufreq/cpuinfo_min_freq\";\n    private final static String CPUFREQ_SCALING_CUR_FREQ = \"/cpufreq/scaling_cur_freq\";\n\n\n    public static boolean checkGravity(Context context) {\n        boolean z = false;\n        List<Sensor> defaultSensor = ((SensorManager) context.getSystemService(SENSOR_SERVICE)).getSensorList(Sensor.TYPE_ALL);\n        for (Sensor sensor : defaultSensor) {\n            if (sensor.getType() == TYPE_GRAVITY) { //不能使用getName去判断是否存在重力感应器，应交与系统判断\n                z = true;\n                break;\n            }\n        }\n        return z;\n    }\n\n\n    public static List<String> getAllSensors(Context context) {\n        List<String> list = new ArrayList<>();\n        List<Sensor> defaultSensor = ((SensorManager) context.getSystemService(SENSOR_SERVICE)).getSensorList(Sensor.TYPE_ALL);\n        for (Sensor sensor : defaultSensor) {\n            list.add(sensor.getName());\n        }\n        return list;\n    }\n\n\n    public static int getVersionCode(Context context) {\n        try {\n            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);\n            if (packageInfo != null) {\n                return packageInfo.versionCode;\n            }\n            return 0;\n        } catch (Throwable th) {\n            return 0;\n        }\n    }\n\n    public static String getVersionName(Context context) {\n        try {\n            PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);\n            if (packageInfo != null) {\n                return packageInfo.versionName;\n            }\n            return null;\n        } catch (Throwable th) {\n            return null;\n        }\n    }\n\n\n    public static String getInstalledApps(Context context) {\n        List<PackageInfo> installedPackages = context.getPackageManager().getInstalledPackages(0);\n        HashMap<String, String> map = new HashMap<>();\n        for (PackageInfo p : installedPackages) {\n            String packageName = p.packageName;\n            String versionName = p.versionName;\n            map.put(packageName, versionName);\n        }\n        return Util.hashMapToStringNoSort(map);\n\n    }\n\n    public static String getPackageName(Context context) {\n        return context.getPackageName();\n    }\n\n\n    public static boolean checkMultiTouch(Context context) {\n        boolean z = false;\n        try {\n            z = context.getPackageManager().hasSystemFeature(\"android.hardware.touchscreen.multitouch\");\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return z;\n\n    }\n\n    public static String getModelName() {\n        return Build.MODEL;  //Mumu为网易模拟器\n    }\n\n    public static String getModelBrand() {\n        return Build.BRAND;\n    }\n\n\n    public static String getMacAddress(Context context) {\n        String str = \"\";\n        try {\n            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);\n            if (wifiManager != null) {\n                WifiInfo connectionInfo = wifiManager.getConnectionInfo();\n                return connectionInfo == null ? \"\" : connectionInfo.getMacAddress();\n            }\n        } catch (Throwable th) {\n        }\n        return str;\n\n    }\n\n    public static String getDeviceID(Context context) {\n        String str = null;\n        TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);\n        if (telephonyManager == null) {\n            return str;\n        }\n        str = telephonyManager.getDeviceId();\n        return str;\n    }\n\n    public static String getMemorySize() {\n        String dir = \"/proc/meminfo\";\n\n        FileReader fr = null;\n        int size = 0;\n        try {\n            fr = new FileReader(dir);\n            BufferedReader br = new BufferedReader(fr, 2048);\n            String memoryLine = br.readLine();\n            String subMemoryLine = memoryLine.substring(memoryLine.indexOf(\"MemTotal:\"));\n            br.close();\n            long j = Long.parseLong(subMemoryLine.substring(subMemoryLine.indexOf(58) + 1, subMemoryLine.indexOf(\"kB\")).trim());\n            size = (int) (j / 1024);\n        } catch (FileNotFoundException e) {\n            // e.printStackTrace();\n        } catch (IOException e) {\n            //  e.printStackTrace();\n        }\n\n        if (size < 768) {\n            return size + \"M\";\n        }\n        if (size < 1024) {\n            return \"1G\";\n        }\n        return String.format(\"%.1fG\", new Object[]{Float.valueOf(((float) size) / 1024.0f)});\n    }\n\n    public static int getCpuCore() {\n        try {\n            return new File(\"/sys/devices/system/cpu/\").listFiles(new FileFilter() {\n                @Override\n                public boolean accept(File pathname) {\n                    return Pattern.matches(\"cpu[0-9]\", pathname.getName());\n                }\n            }).length;\n\n        } catch (Exception e) {\n            return 0;\n        }\n    }\n\n\n    public static boolean hasGPSDevice(Context context) {\n        final LocationManager mgr = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);\n        if (mgr == null)\n            return false;\n        final List<String> providers = mgr.getAllProviders();\n        if (providers == null)\n            return false;\n        return providers.contains(LocationManager.GPS_PROVIDER);\n    }\n\n    public static String getCpuFrequency() {\n        String frequency = Util.convertSize(getCpuMaxFrequency());\n        String model = Build.MODEL;\n        if (Build.BRAND.equalsIgnoreCase(\"samsung\") && (model.equalsIgnoreCase(\"sch-i959\") || model.equalsIgnoreCase(\"gt-i9500\"))) {\n            frequency = frequency + \" \" + \"四核+四核\";\n            return frequency;\n        }\n        switch (getCpuCore()) {\n            case 1:\n                frequency = frequency + \" \" + \"单核\";\n                break;\n            case 2:\n                frequency = frequency + \" \" + \"双核\";\n                break;\n            case 4:\n                frequency = frequency + \" \" + \"四核\";\n                break;\n            case 6:\n                frequency = frequency + \" \" + \"六核\";\n                break;\n            case 8:\n                frequency = frequency + \" \" + \"八核\";\n                break;\n\n        }\n        return frequency.trim();\n    }\n\n    public static int getCpuMaxFrequency() {\n        File file = new File(\"/sys/devices/system/cpu\");\n        if (!file.exists()) {\n            return 0;\n        }\n        File[] listFiles = file.listFiles(new FileFilter() {\n            @Override\n            public boolean accept(File pathname) {\n                return Pattern.matches(\"cpu[0-9]\", pathname.getName());\n            }\n        });\n        if (listFiles == null || listFiles.length <= 0) {\n            return 0;\n        }\n        List arrayList = new ArrayList();\n        for (File absolutePath : listFiles) {\n            String path = absolutePath.getAbsolutePath();\n            try {\n                int max = Math.max(Math.max(Integer.parseInt(Util.readFile(path + CPUFREQ_CPUINFO_MAX_FREQ)), Integer.parseInt(Util.readFile(path + CPUFREQ_SCALING_CUR_FREQ))), Integer.parseInt(Util.readFile(path + CPUFREQ_CPUINFO_MIN_FREQ)));\n                if (max > 0) {\n                    arrayList.add(Integer.valueOf(max));\n                }\n            } catch (Throwable th) {\n            }\n        }\n        if (arrayList.isEmpty()) {\n            return 0;\n        }\n        Collections.sort(arrayList);\n        return ((Integer) arrayList.get(arrayList.size() - 1)).intValue();\n    }\n\n//\n//    public static String getCameraPixels(Context context, int size) {\n//        if (size == -1) {\n//            return null;\n//        }\n//        Camera camera = Camera.open(size);\n//        Camera.Parameters parameters = camera.getParameters();\n//        List<Camera.Size> localList = parameters.getSupportedPictureSizes();\n//        if (localList != null) {\n//            int[] heights = new int[localList.size()];\n//            int[] widths = new int[localList.size()];\n//            for (int i = 0; i < localList.size(); i++) {\n//                Camera.Size s = localList.get(i);\n//                int sizehieght = s.height;\n//                int sizewidth = s.width;\n//                heights[i] = sizehieght;\n//                widths[i] = sizewidth;\n//            }\n//            int pixels = getMaxNumber(heights) * getMaxNumber(widths);\n//            camera.release();\n//            return String.valueOf(pixels / 10000) + \" 万\";\n//        }\n//        return null;\n//\n//    }\n//\n//    private static int getMaxNumber(int[] paramArray) {\n//        int temp = paramArray[0];\n//        for (int i = 0; i < paramArray.length; i++) {\n//            if (temp < paramArray[i]) {\n//                temp = paramArray[i];\n//            }\n//        }\n//        return temp;\n//    }\n//\n//    public static int HasBackCamera() {\n//        int numberOfCameras = Camera.getNumberOfCameras();\n//        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();\n//        for (int i = 0; i < numberOfCameras; i++) {\n//            Camera.getCameraInfo(i, cameraInfo);\n//            if (cameraInfo.facing == 0) {\n//                return i;\n//            }\n//        }\n//        return -1;\n//    }\n//\n//    public static int HasFrontCamera() {\n//        int numberOfCameras = Camera.getNumberOfCameras();\n//        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();\n//        for (int i = 0; i < numberOfCameras; i++) {\n//            Camera.getCameraInfo(i, cameraInfo);\n//            if (cameraInfo.facing == 1) {\n//                return i;\n//            }\n//        }\n//        return -1;\n//    }\n\n    public static String getBatteryTemp(Context act) {\n        if (act == null) {\n            return null;\n        }\n        Intent batteryStatus = act.registerReceiver(null, new IntentFilter(\"android.intent.action.BATTERY_CHANGED\"));\n        if (batteryStatus == null) {\n            return null;\n        }\n        int temp = batteryStatus.getIntExtra(\"temperature\", -1);\n        if (temp > 0) {\n            return tempToStr(((float) temp) / 10.0f, 1);\n        }\n        return null;\n    }\n\n    public static String getBatteryVolt(Context act) {\n        if (act == null) {\n            return null;\n        }\n        Intent batteryStatus = act.registerReceiver(null, new IntentFilter(\"android.intent.action.BATTERY_CHANGED\"));\n        if (batteryStatus == null) {\n            return null;\n        }\n        int volt = batteryStatus.getIntExtra(\"voltage\", -1);\n        if (volt > 0) {\n            return String.valueOf(volt);\n        }\n        return null;\n    }\n\n    public static String toInfoString(Context context) {\n        HashMap<String, String> map = new HashMap<>();\n        map.put(\"cpuinfo\", JniAnti.getCpuinfo());\n        map.put(\"kernelVersion\", JniAnti.getKernelVersion());\n        map.put(\"deviceId\", JniAnti.getDeviceID());\n//        map.put(\"ApkSign\", JniAnti.getApkSign());\n        map.put(\"cpuCore\", String.valueOf(getCpuCore()));\n        map.put(\"cpuFreq\", getCpuFrequency());\n        map.put(\"Gravity\", String.valueOf(checkGravity(context)));\n        map.put(\"BatteryVolt\", getBatteryVolt(context));\n        map.put(\"BatteryTemp\", getBatteryTemp(context));\n        map.put(\"gps\", String.valueOf(hasGPSDevice(context)));\n        //map.put(\"installedApps\",getInstalledApps(context));\n        map.put(\"ModelBrand\", getModelBrand());\n        map.put(\"ModelName\", getModelName());\n        map.put(\"MacAddress\", getMacAddress(context));\n        String s = Util.hashMapToStringSort(map);\n        return s;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/qtfreet/anticheckemulator/emulator/GLSurfaceView.java",
    "content": "package com.qtfreet.anticheckemulator.emulator;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\n\n/**\n * Created by qtfreet on 2016/12/23.\n */\n\npublic class GLSurfaceView extends android.opengl.GLSurfaceView {\n\n    public GLSurfaceView(Context context) {\n        super(context);\n        init();\n    }\n\n    public GLSurfaceView(Context context, AttributeSet attributeSet) {\n        super(context, attributeSet);\n        init();\n    }\n\n    private void init() {\n        setEGLConfigChooser(8, 8, 8, 8, 16, 0);\n        GpuRender gpuRender = new GpuRender();\n        setRenderer(gpuRender);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/qtfreet/anticheckemulator/emulator/GpuRender.java",
    "content": "package com.qtfreet.anticheckemulator.emulator;\n\nimport android.opengl.GLSurfaceView;\nimport android.util.Log;\n\nimport javax.microedition.khronos.egl.EGLConfig;\nimport javax.microedition.khronos.opengles.GL10;\n\n/**\n * Created by qtfreet on 2016/12/23.\n */\n\npublic class GpuRender implements GLSurfaceView.Renderer {\n    @Override\n    public void onSurfaceCreated(GL10 gl, EGLConfig config) {\n        gl.glClearColor(8.0f, 8.0f, 8.0f, 0.0f);\n        String vendor = gl.glGetString(GL10.GL_VENDOR);\n        String renderer = gl.glGetString(GL10.GL_RENDERER);\n        Log.e(\"qtfreet000\", \"显卡信息：\" + vendor + \" \" + renderer);\n    }\n\n    @Override\n    public void onSurfaceChanged(GL10 gl, int width, int height) {\n\n    }\n\n    @Override\n    public void onDrawFrame(GL10 gl) {\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/qtfreet/anticheckemulator/emulator/JniAnti.java",
    "content": "package com.qtfreet.anticheckemulator.emulator;\n\n/**\n * Created by qtfreet on 2016/12/22.\n */\n\npublic class JniAnti {\n    static {\n        System.loadLibrary(\"native-lib\");\n    }\n\n    public static native String getCpuinfo();\n\n    public static native String getApkSign();\n\n    public static native String getKernelVersion();\n\n    public static native String getDeviceID(); //优测测试时提示没有权限读取read_phone_state，这里已经Mainifest注册\n\n    public static native int checkAntiFile();\n}\n"
  },
  {
    "path": "app/src/main/java/com/qtfreet/anticheckemulator/utils/Util.java",
    "content": "package com.qtfreet.anticheckemulator.utils;\n\nimport java.io.BufferedReader;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Created by qtfreet on 2017/2/7.\n */\n\npublic class Util {\n    public static String hashMapToStringNoSort(HashMap<String, String> paramMap) {\n        Set<String> listKeys = paramMap.keySet();\n        int length = listKeys.size();\n        List<String> list = new ArrayList();\n        for (String add : listKeys) {\n            list.add(add);\n        }\n        String kvString = \"\";\n        for (int i = 0; i < length; i++) {\n            String key = list.get(i);\n            if (i == length - 1) {\n                kvString = kvString + key + \"=\" + paramMap.get(key);\n            } else {\n                kvString = kvString + key + \"=\" + paramMap.get(key) + \"&\";\n            }\n        }\n        return kvString;\n    }\n\n    public static String hashMapToStringSort(HashMap<String, String> paramMap) {\n        Set<String> listKeys = paramMap.keySet();\n        int length = listKeys.size();\n        List<String> list = new ArrayList();\n        for (String add : listKeys) {\n            list.add(add);\n        }\n        Collections.sort(list); //进行排序\n        String kvString = \"\";\n        for (int i = 0; i < length; i++) {\n            String key = list.get(i);\n            if (i == length - 1) {\n                kvString = kvString + key + \"=\" + paramMap.get(key);\n            } else {\n                kvString = kvString + key + \"=\" + (paramMap.get(key)) + \"&\";\n            }\n        }\n        return kvString;\n    }\n\n    public static String readFile(String str) {\n        File file = new File(str);\n        StringBuilder sb = new StringBuilder();\n        if (file.exists()) {\n            try {\n                String line = null;\n                FileInputStream fileInputStream = new FileInputStream(file);\n                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream));\n                while ((line = bufferedReader.readLine()) != null) {\n                    sb.append(line);\n                }\n                bufferedReader.close();\n                fileInputStream.close();\n                return sb.toString();\n            } catch (FileNotFoundException e) {\n                e.printStackTrace();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n        return \"\";\n    }\n\n    public static String convertSize(int i) {\n        int size = i / 1000;\n        if (size > 360 && size < 440) {\n            return \"400M\";\n        }\n        if (size > 460 && size < 540) {\n            return \"500M\";\n        }\n        if (size > 560 && size < 640) {\n            return \"600M\";\n        }\n        if (size > 660 && size < 740) {\n            return \"700M\";\n        }\n        if (size > 760 && size < 840) {\n            return \"800M\";\n        }\n        if (size > 860 && size < 940) {\n            return \"900M\";\n        }\n        if (size > 960 && size < 1040) {\n            return \"1G\";\n        }\n        if (size < 1000) {\n            return String.format(\"%dM\", new Object[]{Integer.valueOf(size)});\n        }\n        return String.format(\"%.1fG\", new Object[]{Float.valueOf(((float) size) / 1000.0f)});\n    }\n\n    public static String tempToStr(float temp, int tempSetting) {\n        if (temp <= 0.0f) {\n            return \"\";\n        }\n        if (tempSetting == 2) {\n            return String.format(\"%.1f°F\", new Object[]{Float.valueOf(((9.0f * temp) + 160.0f) / 5.0f)});\n        }\n        return String.format(\"%.1f°C\", new Object[]{Float.valueOf(temp)});\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/activity_main\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    tools:context=\"com.qtfreet.anticheckemulator.MainActivity\">\n\n    <TextView\n        android:id=\"@+id/sample_text\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Hello World!\" />\n\n    <com.qtfreet.anticheckemulator.emulator.GLSurfaceView\n        android:id=\"@+id/hwGPU\"\n        android:layout_width=\"1dip\"\n        android:layout_height=\"1dip\"\n        android:layout_below=\"@+id/sample_text\" />\n\n</RelativeLayout>\n"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">AntiCheckEmulator</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/test/java/com/qtfreet/anticheckemulator/ExampleUnitTest.java",
    "content": "package com.qtfreet.anticheckemulator;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * Example local unit test, which will execute on the development machine (host).\n *\n * @see <a href=\"http://d.android.com/tools/testing\">Testing documentation</a>\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.3.0-beta3'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Tue Dec 27 10:06:56 CST 2016\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-3.3-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "## Project-wide Gradle settings.\n#\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n#\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx1024m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n#\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n#Mon Dec 12 16:39:56 CST 2016\nsystemProp.http.proxyHost=127.0.0.1\norg.gradle.jvmargs=-Xmx1536m\nsystemProp.http.proxyPort=1080\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app'\n"
  }
]