安卓逆向环境检测--沙盒

一、maps检测(检测一些多开沙盒的so)


UNEXPORT bool AntiSandBox::scan_line_maps(char *map) {
    if (Str::strstr(map, "libepic.so") != NULL && Str::strstr(map, "libva++.so") != NULL){ //VirtualXposed
        return true;
    }
    if (Str::strstr(map, "app_ratel_runtime") != NULL && Str::strstr(map, "ratel_container-driver.jar") != NULL){ //Ratel
        return true;
    }
    return false;
}


UNEXPORT void AntiSandBox::read_line_scan_map(string str){
    char* split = (char*)"\n";
    string strs = str + split; // 在字符串末尾也加入分隔符,方便截取最后一段
    size_t pos = strs.find(split);
    while (pos != strs.npos)
    {
        string temp = strs.substr(0, pos);
        //LOGI("read_line_scan maps -> %s", temp.c_str());
        if (AntiSandBox::scan_line_maps(const_cast<char *>(temp.c_str()))){
            //TODO
            LOGI("---------------------------read_line_scan_map find VA -> %s", temp.c_str());
            return;
        }
        //去掉已分割的字符串,在剩下的字符串中进行分割
        strs = strs.substr(pos + 1, strs.size());
        pos = strs.find(split);
    }
}

UNEXPORT void AntiSandBox::check_maps() {
    Thread::lock_mutex();
    Env::thread_share_switch_maps = true;
    Thread::unLock_mutex();
    string str = Syscall::readFile((char*)"/proc/self/maps");
    Thread::lock_mutex();
    Env::thread_share_switch_maps = false;
    Thread::unLock_mutex();
    if (str != "null"){
        AntiSandBox::read_line_scan_map(str);
    }
}

二、so路径检测(多开app会将应用的so加载到自己的应用目录下,所以检测so的路径就能发现其路径在多开框架的路径下)


UNEXPORT bool AntiSandBox::scan_line_so_path(char *map) {
    if (Str::strstr(map, globalEnv->pkgname) != NULL){
        if (Str::strstr(map, ".so") != NULL){
            if (Str::strstr(map, "/virtual/data/user/0/") != NULL){ //存在VA框架的虚拟路径
                return true;
            }
        }
    }
    return false;
}

UNEXPORT void AntiSandBox::read_line_scan_so_path(string str) {
    char* split = (char*)"\n";
    string strs = str + split; // 在字符串末尾也加入分隔符,方便截取最后一段
    size_t pos = strs.find(split);
    while (pos != strs.npos)
    {
        string temp = strs.substr(0, pos);
        //LOGI("read_line_scan maps -> %s", temp.c_str());
        if (AntiSandBox::scan_line_so_path(const_cast<char *>(temp.c_str()))){
            //TODO 发现VA
            LOGI("---------------------------read_line_scan_so_path find VA -> %s", temp.c_str());
            return;
        }
        // 去掉已分割的字符串,在剩下的字符串中进行分割
        strs = strs.substr(pos + 1, strs.size());
        pos = strs.find(split);
    }
}

//*****************************************************************************************************
UNEXPORT void AntiSandBox::check_so_path() {
    Thread::lock_mutex();
    Env::thread_share_switch_maps = true;
    Thread::unLock_mutex();
    string str = Syscall::readFile((char*)"/proc/self/maps");
    Thread::lock_mutex();
    Env::thread_share_switch_maps = false;
    Thread::unLock_mutex();
    if (str != "null"){
        AntiSandBox::read_line_scan_so_path(str);
    }
}

三、检测uid

// 软多开,一般绕不过uid,还是用宿主的uid,如果满足同一uid下的两个进程对应的包名

UNEXPORT void AntiSandBox::check_uid() {
    LOGI("------------------> 0 ");
    vector<char*> ret;
    char cmd[512] = {0};
    int count = 0;
    sprintf(cmd, "%s %s", "ps | grep", globalEnv->pkgname); //globalEnv->pkgname);
    LOGI("------------------> 1 ");
    if (Shell::run_shell(cmd, ret) != -1) {
        LOGI("------------------> 2 ");
        for (int i = 0; i < ret.size(); i++){
            LOGI("------------------> 3 ");
            if (Str::strstr(ret[i], globalEnv->pkgname) != nullptr
                && Str::strstr(ret[i], ":") == nullptr){
                count++;
                LOGI("check_uid -> %s count=%d", ret[i], count);
            }
            free(ret[i]);
        }
    }
    LOGI("------------------> 4 ");
    if (ret.size() == 0){
        // TODO 在VA进程中无法获取自己的ps信息,还和系统版本有关
    }
    if (count > 1){
        // TODO 有两个进程同uid
    }
}

四、进程检测

UNEXPORT void AntiSandBox::check_ps() {
    vector<char*> ret;
    if (Shell::run_shell("ps -ef", ret) != -1) {
        for (int i = 0; i < ret.size(); i++){
            char* tmp = ret[i];
            LOGI("check_ps -> %s", tmp);

            if (i > 2){
                /*
                    check_ps -> UID            PID  PPID C STIME TTY          TIME CMD
                    check_ps -> u0_a759      22017   740 3 17:16:15 ?     00:00:00 com.serven.scorpion.bit64:helper
                    check_ps -> u0_a759      22132   740 60 17:16:31 ?    00:00:00 com.yooha.antisdk
                    check_ps -> u0_a759      22176 22132 2 17:16:32 ?     00:00:00 ps -ef
                 */

                // TODO 检测到有其他进程(必要时需要排除掉是否是自身进程)

            }
            free(ret[i]);
        }
    }
}

五、检测datadir权限

void AntiSandBox::check_dir(JNIEnv *env) {
    jobject context = AntiSandBox::getApplicationContext(env);
    LOGI("check_dir context %p", context);

    jobject objDir = Method::callMethodObject(env, context,
                                                           "android/content/Context",
                                                           "getFilesDir",
                                                           "()Ljava/io/File;");
    LOGI("check_dir objDir %p", objDir);

    jstring jsDir = static_cast<jstring>(Method::callMethodObject(env, objDir,
                                                                  "java/io/File",
                                                                  "getAbsolutePath",
                                                                  "()Ljava/lang/String;"));
    jboolean jb = false;
    const char* charPkg = (env->GetStringUTFChars(jsDir, &jb));
    LOGI("check_dir jsDir  ------------------------> < %s >", charPkg);

    string temp;
    temp.append(charPkg);
    size_t pos = temp.rfind("/");
    temp = temp.substr(0, pos);
    LOGI("check_dir tmp  ------------------------> < %s >", temp.c_str());

    AntiSandBox::access_dir(temp);
    AntiSandBox::canRead_dir(env, temp);
    env->ReleaseStringUTFChars(jsDir, charPkg);
}

/**
 * 方法一
 */
void AntiSandBox::access_dir(string datadir) {
    if (access((datadir + "/../").c_str(), R_OK) == 0){
//        多开环境日志如下:
//        check_dir jsDir  ------------------------> < /data/user/0/com.serven.scorpion.bit64/virtual/data/user/0/com.yooha.antisdk/files >
//        check_dir tmp  ------------------------> < /data/user/0/com.serven.scorpion.bit64/virtual/data/user/0/com.yooha.antisdk > 06-05 11:32:00.972 18886 18886 I yooha-anti-ndk: access_dir  ------------------------> find sandbox
        // TODO 多开环境
        LOGI("access_dir  ------------------------> find sandbox");
    }
}
/**
 * 方法二
 */
void AntiSandBox::canRead_dir(JNIEnv *env, string datadir) {
    string path = datadir + (char*)"/..";
    LOGI("canRead_dir path = %s", path.c_str());

    jstring jsPath = env->NewStringUTF(path.c_str());
    jobject pathFile = NewObject::new_object(env, "java/io/File", "(Ljava/lang/String;)V", jsPath);
    LOGI("canRead_dir pathFile = %p", pathFile);

    jboolean read = Method::callMethodBoolean(env, pathFile,
                                              "java/io/File",
                                              "canRead",
                                              "()Z");
    if (read){
        // TODO 多开环境
        LOGI("canRead_dir  ------------------------> find sandbox");
    }
    env->DeleteLocalRef(jsPath);
}

六、检测AM

UNEXPORT void AntiSandBox::check_proxy(JNIEnv *env) {
    Field* field = new Field("android/app/ActivityManager", env);
    jobject objIActivityManagerSingleton = field->get_static_object_field("IActivityManagerSingleton", "Landroid/util/Singleton;");
    LOGI("check_proxy objIActivityManagerSingleton %p", objIActivityManagerSingleton);

    jobject objSingleton = Method::callMethodObject(env, objIActivityManagerSingleton,
                                              "android/util/Singleton",
                                              "get",
                                              "()Ljava/lang/Object;");
    LOGI("check_proxy objSingleton %p", objSingleton);

    jclass clsProxy = env->FindClass("java/lang/reflect/Proxy");
    LOGI("check_proxy clsProxy %p", clsProxy);

    jboolean jb = Method::callMethodBoolean(env, clsProxy,
                                                    "java/lang/Class",
                                                    "isInstance",
                                                    "(Ljava/lang/Object;)Z",
                                                        objSingleton);
    if (jb){
        // TODO 正常的环境,AM不可能是一个代理实例。通过判断AM是否是Proxy,便可直接判断环境是否正常
        LOGI("check_proxy js true ------------------------> find sandbox");
    }
}

七、检测 Context#mBasePackageName mOpPackageName

UNEXPORT void AntiSandBox::check_pkgName(JNIEnv *env) {
    jobject context = AntiSandBox::getApplicationContext(env);
    LOGI("check_pkgName context %p", context);

    jstring jsBasePackageName = static_cast<jstring>(Method::callMethodObject(env, context,
                                                                              "android/content/Context",
                                                                              "getBasePackageName",
                                                                              "()Ljava/lang/String;"));
    LOGI("check_pkgName jsBasePackageName %p", jsBasePackageName);

    jboolean jb = false;
    const char* charBasePackageName = (env->GetStringUTFChars(jsBasePackageName, &jb));
    LOGI("check_pkgName charBasePackageName  ------------------------> < %s >", charBasePackageName);

    jstring jsOpPackageName = static_cast<jstring>(Method::callMethodObject(env, context,
                                                                              "android/content/Context",
                                                                              "getOpPackageName",
                                                                              "()Ljava/lang/String;"));
    LOGI("check_pkgName jsOpPackageName %p", jsOpPackageName);

    const char* charOpPackageName = (env->GetStringUTFChars(jsOpPackageName, &jb));
    LOGI("check_pkgName charOpPackageName  ------------------------> < %s >", charOpPackageName);

    if (Str::strcmp("com.yooha.antisdk", const_cast<char *>(charBasePackageName)) != 0 || Str::strcmp("com.yooha.antisdk", const_cast<char *>(charOpPackageName)) != 0){
        // TODO 检测到双开框架的包名
        LOGI("check_pkgName  ------------------------> find sandbox");
    }
    env->ReleaseStringUTFChars(jsBasePackageName, charBasePackageName);
    env->ReleaseStringUTFChars(jsOpPackageName, charOpPackageName);
}

八、检测ActivityThread#mInstrumentation

void AntiSandBox::check_mInstrumentation(JNIEnv *env) {
    Field* field = new Field("android/app/ActivityThread", env);
    jobject objActivityThread = field->get_static_object_field("sCurrentActivityThread", "Landroid/app/ActivityThread;");
    LOGI("check_mInstrumentation objActivityThread %p", objActivityThread);

    jobject objInstrumentation = Method::callMethodObject(env, objActivityThread,
                                                    "android/app/ActivityThread",
                                                    "getInstrumentation",
                                                    "()Landroid/app/Instrumentation;");
    LOGI("check_mInstrumentation objInstrumentation %p", objInstrumentation);

    jobject clsInstrumentation = Method::callMethodObject(env, objInstrumentation, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
    LOGI("check_mInstrumentation clsInstrumentation %p", clsInstrumentation);

    jstring clsInstrumentationName = static_cast<jstring>(Method::callMethodObject(env,
                                                                                   clsInstrumentation,
                                                                                   "java/lang/Class",
                                                                                   "getName",
                                                                                   "()Ljava/lang/String;"));
    LOGI("check_mInstrumentation clsInstrumentationName %p", clsInstrumentationName);

    jboolean jb = false;
    const char* charclsInstrumentationName = (env->GetStringUTFChars(clsInstrumentationName, &jb));
    LOGI("check_mInstrumentation charclsInstrumentationName %s", charclsInstrumentationName);

    if (Str::strcmp("android.app.Instrumentation", const_cast<char *>(charclsInstrumentationName)) != 0 ){
        // TODO 检测到双开框架的包名
        LOGI("check_mInstrumentation  ------------------------> find sandbox");
    }

    env->ReleaseStringUTFChars(clsInstrumentationName, charclsInstrumentationName);
}

九、检测PMS

void AntiSandBox::check_pms(JNIEnv *env) {
    Field* field = new Field("android/app/ActivityThread", env);
    jobject objIPackageManager = field->get_static_object_field("sPackageManager", "Landroid/content/pm/IPackageManager;");
    LOGI("check_pms objIPackageManager %p", objIPackageManager);

    jobject clsIPackageManager = Method::callMethodObject(env, objIPackageManager, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
    LOGI("check_pms clsIPackageManager %p", clsIPackageManager);

    jstring clsIPackageManagerName = static_cast<jstring>(Method::callMethodObject(env,
                                                                                   clsIPackageManager,
                                                                                   "java/lang/Class",
                                                                                   "getName",
                                                                                   "()Ljava/lang/String;"));
    LOGI("check_pms clsIPackageManagerName %p", clsIPackageManagerName);

    jboolean jb = false;
    const char* charclsIPackageManagerName = (env->GetStringUTFChars(clsIPackageManagerName, &jb));
    LOGI("check_pms charclsIPackageManagerName %s", charclsIPackageManagerName);

    if (Str::strcmp("android.content.pm.IPackageManager$Stub$Proxy", const_cast<char *>(charclsIPackageManagerName)) != 0 ){
        // TODO 检测到双开框架
        LOGI("check_pms  ------------------------> find sandbox");
    }

    env->ReleaseStringUTFChars(clsIPackageManagerName, charclsIPackageManagerName);
}

十、检测ActivityThread$H#mCallback

void AntiSandBox::check_ActivityThread_H_mCallback(JNIEnv *env) {
    Field* field = new Field("android/app/ActivityThread", env);
    jobject objActivityThread = field->get_static_object_field("sCurrentActivityThread", "Landroid/app/ActivityThread;");
    LOGI("check_ActivityThread_H_mCallback objActivityThread %p", objActivityThread);

    jobject objHandler = Method::callMethodObject(env, objActivityThread,
                                                          "android/app/ActivityThread",
                                                          "getHandler",
                                                          "()Landroid/os/Handler;");
    LOGI("check_ActivityThread_H_mCallback objHandler %p", objHandler);

    Field* fieldHandler = new Field("android/os/Handler", env);
    jobject objmCakkback = fieldHandler->get_object_field(objHandler, "mCallback", "Landroid/os/Handler$Callback;");
    LOGI("check_ActivityThread_H_mCallback objmCakkback %p", objmCakkback);

    if (objmCakkback != nullptr){
        // TODO 正常情况下 ActivityThread$H.mCallback = null
        LOGI("check_ActivityThread_H_mCallback ------------------------> find sandbox");
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
iOS和安卓的沙盒是用来保护应用程序数据的安全性的一种机制。它们的主要区别如下: 1. 安全性:iOS的沙盒机制相对安卓更加严格。iOS要求应用程序在自己的沙盒内运行,限制了应用之间的直接访问和交互。而安卓的沙盒机制相对较弱,应用程序可以更容易地访问和共享数据。 2. 文件系统结构:iOS的沙盒机制将每个应用程序的文件分隔为多个目录,包括应用程序包、文档目录、缓存目录等。每个目录只能由特定的应用程序进行访问和写入。而安卓的沙盒机制通常是基于应用的用户ID,并且应用程序可以自由地向沙盒中的文件系统写入和访问。 3. 权限管理:iOS的沙盒机制通过权限管理来限制应用程序对系统资源的访问。应用程序需要在安装时声明所需的访问权限,并由用户在使用时授予。而安卓的沙盒机制在应用程序安装时会一次性获取所有权限,并且用户只能在软件设置中进行修改。 4. 应用程序的更新:iOS的沙盒机制要求每个应用程序都在单独的容器中运行,因此应用程序的更新通常是通过替换整个应用程序包来完成的。而安卓的沙盒机制允许应用程序在更新时只替换其中的部分文件,从而减少下载和更新时间。 综上所述,iOS和安卓的沙盒机制在安全性、文件系统结构、权限管理和应用程序更新方面存在一些差异。iOS的沙盒机制相对更严格,保护了应用程序和用户数据的安全性,但也可能限制了应用程序之间的交互。而安卓的沙盒机制相对较弱,允许应用程序更自由地访问和共享数据,但也可能增加了安全隐患。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值