java JDK 介绍

JVM 相关知识

Posted by Song on December 30, 2019

Android Hook 检测

检测是否被 hook https://github.com/song-dev/security-check-android

方案

主流 hook 框架检测

检测 maps 中包含的 fridasubstrateXposed 框架部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
 * 检测主流 hook 框架: frida、Xposed、substrate
 * @return
 */
int frameCheck() {
    char path[BUF_SIZE_32];
    sprintf(path, "/proc/%d/maps", getpid());
    // 读取数据
    FILE *f = NULL;
    char buf[BUF_SIZE_512];
    f = fopen(path, "r");
    if (f != NULL) {
        while (fgets(buf, BUF_SIZE_512, f)) {
            // fgets 当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
            LOGI("maps: %s", buf);
            if (strstr(buf, "frida")
                || strstr(buf, "com.saurik.substrate")
                || strstr(buf, "XposedBridge.jar")) {
                fclose(f);
                return 1;
            }
        }
    }
    fclose(f);
    return 0;
}

可靠

包名检测

检测三大框架对应包名或者文件

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * 检查核心文件,若存在则为危险环境。不一定正在被 hook,但是有风险
 * @return
 */
int pkgCheck() {
    if (exists("/data/data/de.robv.android.xposed.installer")
        || exists("/data/data/com.saurik.substrate")
        || exists("/data/local/tmp/frida-server")) {
        return 1;
    }
    return 0;
}

Xposed 类检测

尝试加载 Xposed 公共类,若可以加载则为 Xposed 环境中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * 尝试加载 Xposed 类
 *
 * @return
 */
public static boolean classCheck() {
    try {
        Class.forName("de.robv.android.xposed.XC_MethodHook");
        return true;
    } catch (Exception e) {
    }
    try {
        Class.forName("de.robv.android.xposed.XposedHelpers");
        return true;
    } catch (Exception e) {
    }
    return false;
}

异常栈检测

检测异常栈是否有可疑框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
 * 检测调用栈中的可疑方法
 */
public static boolean exceptionCheck() {
    try {
        throw new Exception("Deteck hook");
    } catch (Exception e) {
        int zygoteInitCallCount = 0;
        for (StackTraceElement item : e.getStackTrace()) {
            // 检测"com.android.internal.os.ZygoteInit"是否出现两次,如果出现两次,则表明Substrate框架已经安装
            if ("com.android.internal.os.ZygoteInit".equals(item.getClassName())) {
                zygoteInitCallCount++;
                if (zygoteInitCallCount == 2) {
                    LogUtils.i("Substrate is active on the device.");
                    return true;
                }
            }
            if ("com.saurik.substrate.MS$2".equals(item.getClassName()) && "invoke".equals(item.getMethodName())) {
                LogUtils.i("A method on the stack trace has been hooked using Substrate.");
                return true;
            }
            if ("de.robv.android.xposed.XposedBridge".equals(item.getClassName())
                    && "main".equals(item.getMethodName())) {
                LogUtils.i("Xposed is active on the device.");
                return true;
            }
            if ("de.robv.android.xposed.XposedBridge".equals(item.getClassName())
                    && "handleHookedMethod".equals(item.getMethodName())) {
                LogUtils.i("A method on the stack trace has been hooked using Xposed.");
                return true;
            }
        }
    }

    return false;
}

核心 so 检测

检测 substratexhookso 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
 * 检测已加载到内存的 Substrate 核心文件
 * @return
 */
int substrateSoCheck() {
    // 直接加载危险的so
    void *imagehandle = dlopen("libsubstrate-dvm.so", RTLD_GLOBAL | RTLD_NOW);
    if (imagehandle != NULL) {
        void *sym = dlsym(imagehandle, "MSJavaHookMethod");
        if (sym != NULL) {
            dlclose(imagehandle);
            LOGE("find Cydia Substrate");
            //发现Cydia Substrate相关模块
            return 1;
        }
    }
    LOGE("not find Cydia Substrate");
    return 0;
}

/**
 * 检测已加载到内存的 xhook 核心文件
 * @return
 */
int xhookCheck() {
    // 直接加载危险的so
    void *imagehandle = dlopen("libxhook.so", RTLD_GLOBAL | RTLD_NOW);
    if (imagehandle != NULL) {
        void *sym = dlsym(imagehandle, "xhook_register");
        if (sym != NULL) {
            dlclose(imagehandle);
            LOGE("find xhook");
            return 1;
        }
    }
    LOGE("not find xhook");
    return 0;
}

参考

  • https://www.jianshu.com/p/c37b1bdb4757