Android 反仪器化与 SSL Pinning 绕过 (Frida/Objection)

Reading time: 8 minutes

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks

本页面提供了一个实用的工作流程,用于对检测/阻止 instrumentation 的 Android 应用或强制 TLS pinning 的应用恢复动态分析。重点是快速分类、常见检测点,以及可复制粘贴的 hooks/策略,以尽可能在不重新打包的情况下绕过它们。

Detection Surface (what apps check)

  • Root 检测:su binary、Magisk paths、getprop values、常见 root packages
  • Frida/debugger 检测(Java):Debug.isDebuggerConnected(), ActivityManager.getRunningAppProcesses(), getRunningServices(), scanning /proc, classpath, loaded libs
  • Native anti‑debug:ptrace(), syscalls, anti‑attach, breakpoints, inline hooks
  • 早期初始化检测:Application.onCreate() 或 process start hooks,如果检测到 instrumentation 则崩溃
  • TLS pinning:custom TrustManager/HostnameVerifier, OkHttp CertificatePinner, Conscrypt pinning, native pins

Step 1 — Quick win: hide root with Magisk DenyList

  • 在 Magisk 中启用 Zygisk
  • 启用 DenyList,并添加目标包
  • 重启并重新测试

许多应用仅查找明显的指示器(su/Magisk paths/getprop)。DenyList 常常能中和这些简单的检测。

References:

  • Magisk (Zygisk & DenyList): https://github.com/topjohnwu/Magisk

Step 2 — 30‑second Frida Codeshare tests

在深入之前先尝试常用的即插即用脚本:

  • anti-root-bypass.js
  • anti-frida-detection.js
  • hide_frida_gum.js

Example:

bash
frida -U -f com.example.app -l anti-frida-detection.js

这些通常对 Java 的 root/debug 检查、process/service 扫描和本地 ptrace() 进行 stub。 在防护较弱的应用上很有用;针对加固的目标可能需要定制化的 hooks。

  • Codeshare: https://codeshare.frida.re/

第 3 步 — 通过延迟附加绕过初始化检测器

许多检测只在 process spawn/onCreate() 期间运行。Spawn‑time injection (-f) 或 gadgets 会被发现;在 UI 加载后再附加可以绕过检测。

bash
# Launch the app normally (launcher/adb), wait for UI, then attach
frida -U -n com.example.app
# Or with Objection to attach to running process
aobjection --gadget com.example.app explore  # if using gadget

如果这有效,保持会话稳定并继续进行 map 和 stub 检查。

第4步 — 通过 Jadx 和字符串搜索映射检测逻辑

在 Jadx 中用于静态初筛的关键字:

  • "frida", "gum", "root", "magisk", "ptrace", "su", "getprop", "debugger"

典型的 Java 模式:

java
public boolean isFridaDetected() {
return getRunningServices().contains("frida");
}

常见需要审查/hook 的 API:

  • android.os.Debug.isDebuggerConnected
  • android.app.ActivityManager.getRunningAppProcesses / getRunningServices
  • java.lang.System.loadLibrary / System.load (native bridge)
  • java.lang.Runtime.exec / ProcessBuilder (probing commands)
  • android.os.SystemProperties.get (root/emulator heuristics)

第5步 — 使用 Frida (Java) 进行运行时存根

覆盖自定义保护以返回安全值而无需重新打包:

js
Java.perform(() => {
const Checks = Java.use('com.example.security.Checks');
Checks.isFridaDetected.implementation = function () { return false; };

// Neutralize debugger checks
const Debug = Java.use('android.os.Debug');
Debug.isDebuggerConnected.implementation = function () { return false; };

// Example: kill ActivityManager scans
const AM = Java.use('android.app.ActivityManager');
AM.getRunningAppProcesses.implementation = function () { return java.util.Collections.emptyList(); };
});

要排查早期崩溃吗?在它崩溃前转储类,以识别可能用于检测的命名空间:

js
Java.perform(() => {
Java.enumerateLoadedClasses({
onMatch: n => console.log(n),
onComplete: () => console.log('Done')
});
});

记录并禁用可疑方法以确认执行流程:

js
Java.perform(() => {
const Det = Java.use('com.example.security.DetectionManager');
Det.checkFrida.implementation = function () {
console.log('checkFrida() called');
return false;
};
});

Step 6 — 当 Java hooks 失效时,跟踪 JNI/native 路径

跟踪 JNI 入口点以定位 native loaders 和 detection init:

bash
frida-trace -n com.example.app -i "JNI_OnLoad"

快速对捆绑的 .so 文件进行本机初筛:

bash
# List exported symbols & JNI
nm -D libfoo.so | head
objdump -T libfoo.so | grep Java_
strings -n 6 libfoo.so | egrep -i 'frida|ptrace|gum|magisk|su|root'

交互式/本地 reversing:

  • Ghidra: https://ghidra-sre.org/
  • r2frida: https://github.com/nowsecure/r2frida

示例:禁用 ptrace 以绕过 libc 中的简单 anti‑debug:

js
const ptrace = Module.findExportByName(null, 'ptrace');
if (ptrace) {
Interceptor.replace(ptrace, new NativeCallback(function () {
return -1; // pretend failure
}, 'int', ['int', 'int', 'pointer', 'pointer']));
}

另见: Reversing Native Libraries

步骤 7 — Objection patching (embed gadget / strip basics)

如果你更倾向于使用 repacking 而不是 runtime hooks,可尝试:

bash
objection patchapk --source app.apk

注意:

  • 需要 apktool;请按照官方指南确保使用当前版本以避免构建问题: https://apktool.org/docs/install
  • Gadget injection 允许在没有 root 的情况下进行 instrumentation,但仍可能被更严格的 init‑time checks 检测到。

References:

  • Objection: https://github.com/sensepost/objection

第8步 — 后备:修补 TLS pinning 以实现网络可见性

如果 instrumentation 被阻止,你仍然可以通过静态移除 pinning 来检查流量:

bash
apk-mitm app.apk
# Then install the patched APK and proxy via Burp/mitmproxy
  • 工具: https://github.com/shroudedcode/apk-mitm
  • 有关网络配置 CA‑trust 技巧(以及 Android 7+ 的 user CA trust),请参阅:

Make APK Accept CA Certificate

Install Burp Certificate

常用命令速查表

bash
# List processes and attach
frida-ps -Uai
frida -U -n com.example.app

# Spawn with a script (may trigger detectors)
frida -U -f com.example.app -l anti-frida-detection.js

# Trace native init
frida-trace -n com.example.app -i "JNI_OnLoad"

# Objection runtime
objection --gadget com.example.app explore

# Static TLS pinning removal
apk-mitm app.apk

提示与注意事项

  • 当应用在启动时崩溃时,优先选择 attaching late 而不是 spawning
  • 一些检测会在关键流程(例如 payment、auth)中再次运行 — 在导航过程中保持 hooks active
  • 结合 static 和 dynamic:在 Jadx 中进行 string hunt 以 shortlist classes;然后 hook methods 在运行时验证
  • 加固的应用可能使用 packers 和 native TLS pinning — 预计需要 reverse native code

参考资料

tip

学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE) 学习和实践 Azure 黑客技术:HackTricks Training Azure Red Team Expert (AzRTE)

支持 HackTricks