- AI 技能
- AI 插件
- 人工智能
【免费下载链接】agentic-awesome-skills
AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600+ agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.
本手册是 Agentic Awesome Skills 仓库中
apk-reverse技能的 Frida 实战脚本速查(对应关联文档 frida-cookbook.md),按场景分类整理了可直接复制使用的 JavaScript 注入脚本,覆盖 Java 方法 Hook、加密/签名捕获、网络请求监听、SSL Pinning 与 Root 检测绕过、反调试与模拟器对抗、数据存储监听以及脱壳等核心场景。读者学完本手册后,将能够在授权范围内独立完成 Android 应用的动态行为分析、敏感数据抓取与安全检测绕过,并与仓库中的 jadx / apktool / adb 静态分析链路形成完整的动静结合逆向流程。
⚠️ 授权使用声明:本手册及所属
apk-reverse技能仅用于教育学习或经系统所有者明确书面授权的安全评估。对未授权目标执行探测、Hook、注入、提取数据等操作属于违法行为,仓库官方文档(SKILL.md)明确要求:运行任何针对目标的命令前,必须先确认目标、确认书面授权与范围、展示待执行命令并等待明确确认;未获确认时只能保持只读并提供防御性建议,优先使用沙箱、一次性虚拟机或受控实验环境。
一、前置准备:Frida 环境与三种注入方式
在复制本手册的脚本之前,需要先完成 Frida 工具链的准备。apk-reverse技能的官方文档(SKILL.md)确认了本机已验证可用的 CLI 工具,其中frida-ps版本为17.9.6,配合adb使用。
1. 安装与设备检查
# 安装 Frida 与命令行工具(依赖 Python) pip install frida-tools # 查看版本 frida-ps --version # 查看已连接的 USB / 网络设备 adb devices # 查看设备上正在运行的进程 frida-ps -UFrida 在 Android 上通过两种方式与目标进程通信:attach 模式(注入到已运行的进程)和spawn 模式(以挂起状态启动进程,在入口处注入后放行),后者能覆盖应用启动早期的检测逻辑。
2. 常用注入命令
# attach 到正在运行的 App(-U 指定 USB 设备,-l 指定脚本) frida -U com.example.app -l hook.js # spawn 模式:冷启动 App 并从第一行代码开始注入 frida -U -f com.example.app -l hook.js # 启动但不暂停(-f 默认会暂停等待 attach,加 --no-pause 直接运行) frida -U -f com.example.app -l hook.js --no-pause # 快速追踪匹配任意证书相关方法(无需手写脚本) frida-trace -U -f com.example.app -j '*!*certificate*'frida-trace -j的 glob 语法可以一次追踪多个类的方法,适合在不确定具体方法名时的快速定位。若需要稳定复用注入流程,apk-reverse技能提供了封装脚本scripts/frida-run.ps1,通过-Spawn -Package com.example.app -ScriptPath "D:\hooks\test.js"等参数统一管理设备、进程与 spawn/attach 模式,避免手写参数时混淆-f、-n、-U。
3. 在宿主设备上启动 frida-server
adb push frida-server /data/local/tmp/ adb shell chmod 755 /data/local/tmp/frida-server adb shell su -c /data/local/tmp/frida-server &提示:frida-server 的架构必须与设备 CPU 匹配(arm64 / arm / x86),且设备需要 root 或可用的 ptrace 权限;模拟器通常使用 x86_64 版本的 frida-server。
二、通用 Hook 模板:Java 方法、构造函数与方法枚举
无论目标功能是什么,以下三个模板是所有 Java 层 Hook 的基础。它们都要求在Java.perform()回调内执行,这是 Frida 确保代码运行在 Java 运行时线程上的标准入口。
1. Hook 任意 Java 方法
Java.perform(function() { var TargetClass = Java.use("com.target.ClassName"); // Hook 无参方法 TargetClass.methodName.implementation = function() { console.log("[*] methodName called"); var ret = this.methodName(); console.log("[*] return: " + ret); return ret; }; // Hook 有参方法:overload 参数类型用于区分重载 TargetClass.methodName.overload('java.lang.String', 'int').implementation = function(str, num) { console.log("[*] methodName(" + str + ", " + num + ")"); var ret = this.methodName(str, num); console.log("[*] return: " + ret); return ret; }; });要点说明:
Java.use("com.target.ClassName")通过完整类名获取类包装对象;类名必须与 jadx 反编译结果完全一致。overload(...)必须按参数类型精确声明(基本类型如int直接用关键字,引用类型用完整类名),否则重载方法会报错;也可以调用TargetClass.methodName.overloads遍历所有重载。- 在
implementation内部调用this.methodName(...)会触发被替换前的原实现,因此先打印入参、调用原方法、再打印返回值是标准的三段式写法。 - 若需要修改返回值实现绕过,只需在
return前替换返回值即可(例如把false改成true)。
2. Hook 构造函数
Java.perform(function() { var TargetClass = Java.use("com.target.ClassName"); TargetClass.$init.overload('java.lang.String').implementation = function(arg) { console.log("[*] new ClassName(" + arg + ")"); this.$init(arg); }; });Frida 用$init表示 Java 构造函数(对应<init>),在构造函数内可以捕获对象初始化时传入的密钥、URL、token 等关键参数——这是提取运行时敏感配置的高效手段,例如SecretKeySpec构造时的密钥字节。
3. 枚举所有方法
Java.perform(function() { var TargetClass = Java.use("com.target.ClassName"); var methods = TargetClass.class.getDeclaredMethods(); methods.forEach(function(method) { console.log(method.toString()); }); });通过反射列出类的全部声明方法(含私有方法),便于在静态分析不完整时快速确认目标类的方法清单与签名,再决定针对哪个方法写 Hook。
三、加密/签名 Hook:AES、MD5/SHA 与 HMAC
逆向中最高频的需求是捕获加密密钥、IV 与原始明文/密文。仓库同目录的 android-advanced.md 也指出:定位关键逻辑时应从 crypto 库函数(AES/MD5/SHA)调用追踪,Java 层只是 JNI 包装时再转向 native 层。
1. Hook AES 加解密(含密钥与 IV 捕获)
Java.perform(function() { var Cipher = Java.use("javax.crypto.Cipher"); Cipher.doFinal.overload('[B').implementation = function(input) { var mode = this.getOpmode ? this.getOpmode() : "?"; console.log("[Cipher.doFinal] mode=" + mode); console.log(" input: " + bytesToHex(input)); var result = this.doFinal(input); console.log(" output: " + bytesToHex(result)); return result; }; // 捕获密钥 var SecretKeySpec = Java.use("javax.crypto.spec.SecretKeySpec"); SecretKeySpec.$init.overload('[B', 'java.lang.String').implementation = function(key, algo) { console.log("[SecretKeySpec] algo=" + algo + " key=" + bytesToHex(key)); this.$init(key, algo); }; // 捕获 IV var IvParameterSpec = Java.use("javax.crypto.spec.IvParameterSpec"); IvParameterSpec.$init.overload('[B').implementation = function(iv) { console.log("[IvParameterSpec] iv=" + bytesToHex(iv)); this.$init(iv); }; }); function bytesToHex(bytes) { var hex = []; for (var i = 0; i < bytes.length; i++) { hex.push(('0' + (bytes[i] & 0xFF).toString(16)).slice(-2)); } return hex.join(''); }说明:
'[B'是 JNI 类型描述符,表示byte[]数组;getOpmode()返回当前操作模式(1 为加密ENCRYPT_MODE,2 为解密DECRYPT_MODE),据此可区分密文与明文流向。- 由于
SecretKeySpec与IvParameterSpec在加密前必然构造,Hook 其构造函数即可在密钥真正参与运算前截获明文密钥与 IV,配合Cipher.doFinal的输入输出形成完整的加解密证据链。 - 注意
bytesToHex在加密章节中即被调用,它定义在脚本末尾——得益于 JavaScript 函数声明提升(function hoisting),这种"先使用、后定义"的写法是合法的。
2. Hook MD5/SHA
Java.perform(function() { var MessageDigest = Java.use("java.security.MessageDigest"); MessageDigest.digest.overload('[B').implementation = function(input) { console.log("[MessageDigest.digest] algo=" + this.getAlgorithm()); console.log(" input: " + bytesToHex(input)); var result = this.digest(input); console.log(" hash: " + bytesToHex(result)); return result; }; MessageDigest.digest.overload().implementation = function() { console.log("[MessageDigest.digest] algo=" + this.getAlgorithm()); var result = this.digest(); console.log(" hash: " + bytesToHex(result)); return result; }; });MessageDigest同时服务 MD5、SHA-1、SHA-256 等算法,getAlgorithm()会返回实际使用的算法名。此脚本同时覆盖了digest(byte[])(一步到位计算)与digest()(配合update()分块喂入数据)两种重载,避免漏抓流式哈希场景。
3. Hook HMAC
Java.perform(function() { var Mac = Java.use("javax.crypto.Mac"); Mac.doFinal.overload('[B').implementation = function(input) { console.log("[Mac.doFinal] algo=" + this.getAlgorithm()); console.log(" input: " + bytesToHex(input)); var result = this.doFinal(input); console.log(" mac: " + bytesToHex(result)); return result; }; Mac.init.overload('java.security.Key').implementation = function(key) { var keyBytes = key.getEncoded(); console.log("[Mac.init] key=" + bytesToHex(keyBytes)); this.init(key); }; });HMAC(如 HmacSHA256)常用于接口签名,Mac.init(Key)的key.getEncoded()能直接导出对称密钥字节;在doFinal处同时打印输入(待签名数据)与输出(签名值),即可还原签名算法输入输出全貌。
四、网络请求 Hook:OkHttp3、URL 连接与 WebView
抓取 App 的网络流量是分析接口签名、请求头与业务参数的核心手段。仓库 SKILL.md 的"Java 逻辑观察"章节也把okhttp、retrofit、webview列为重点关键词。
1. Hook OkHttp3 请求/响应
Java.perform(function() { var OkHttpClient = Java.use("okhttp3.OkHttpClient"); var Interceptor = Java.use("okhttp3.Interceptor"); // Hook newCall 获取请求 URL var RealCall = Java.use("okhttp3.RealCall"); RealCall.execute.implementation = function() { var request = this.request(); console.log("[OkHttp] " + request.method() + " " + request.url().toString()); var headers = request.headers(); for (var i = 0; i < headers.size(); i++) { console.log(" " + headers.name(i) + ": " + headers.value(i)); } var response = this.execute(); console.log("[OkHttp] Response: " + response.code()); return response; }; });说明:
- OkHttp 的
RealCall.execute()是同步请求入口;this.request()可拿到完整Request对象,进而读取方法、URL 与全部请求头(如 Authorization、X-Sign 等)。 - 若目标使用异步请求(
enqueue),可仿照同样方式 HookRealCall.enqueue。 - 由于 Retrofit 底层基于 OkHttp,此脚本对 Retrofit 请求同样生效;仓库 android-advanced.md 中的框架绕过对照表也印证了这一点。
2. Hook URL 连接
Java.perform(function() { var URL = Java.use("java.net.URL"); URL.openConnection.overload().implementation = function() { console.log("[URL] " + this.toString()); return this.openConnection(); }; });适合未使用 OkHttp、直接基于java.net.HttpURLConnection的老式 App;this.toString()输出完整 URL,从而捕获出站域名与路径。
3. Hook WebView
Java.perform(function() { var WebView = Java.use("android.webkit.WebView"); WebView.loadUrl.overload('java.lang.String').implementation = function(url) { console.log("[WebView.loadUrl] " + url); this.loadUrl(url); }; WebView.evaluateJavascript.implementation = function(script, callback) { console.log("[WebView.evaluateJavascript] " + script.substring(0, 200)); this.evaluateJavascript(script, callback); }; });loadUrl捕获页面跳转 URL;evaluateJavascript截获注入到 WebView 的 JS 代码(截取前 200 字符避免刷屏),可用于分析混合应用(Hybrid App)中 JS 与原生层的交互,例如 H5 页面携带的 token 或签名参数。
五、绕过类 Hook:SSL Pinning、Root 检测、反调试与模拟器
绕过类脚本是整个速查手册中使用风险最高、也是最常用的部分。仓库同目录的 frida-bypass-kit.md 给出了一套集成的"FridaBypassKit"思路(Root 检测、SSL Pinning、模拟器检测、反调试四大绕过能力),并建议"先跑完整 Bypass Kit,再针对性调整";本节的脚本则是按检测点逐个击破的精准版。
1. 通用 SSL Pinning 绕过
Java.perform(function() { // OkHttp3 CertificatePinner try { var CertificatePinner = Java.use("okhttp3.CertificatePinner"); CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() { console.log("[*] SSL Pinning bypassed (OkHttp3)"); }; } catch(e) {} // TrustManagerImpl try { var TrustManagerImpl = Java.use("com.android.org.conscrypt.TrustManagerImpl"); TrustManagerImpl.verifyChain.implementation = function(untrustedChain) { console.log("[*] SSL Pinning bypassed (TrustManagerImpl)"); return untrustedChain; }; } catch(e) {} // X509TrustManager try { var X509TrustManager = Java.use("javax.net.ssl.X509TrustManager"); var TrustManager = Java.registerClass({ name: "com.bypass.TrustManager", implements: [X509TrustManager], methods: { checkClientTrusted: function() {}, checkServerTrusted: function() {}, getAcceptedIssuers: function() { return []; } } }); } catch(e) {} // Network Security Config (Android 7+) try { var NetworkSecurityConfig = Java.use("android.security.net.config.NetworkSecurityConfig"); NetworkSecurityConfig.isCleartextTrafficPermitted.implementation = function() { return true; }; } catch(e) {} });分层原理:
- CertificatePinner.check:OkHttp 的证书固定核心方法,将方法体替换为空实现即可让 OkHttp 跳过固定证书校验;
- TrustManagerImpl.verifyChain:Android 系统 Conscrypt 实现中的证书链验证方法,直接返回原始
untrustedChain跳过校验;仓库 frida-bypass-kit.md 还提到应同时 HookcheckTrustedRecursive()以兼容不同 Android 版本的调用链; - registerClass 注册自定义 TrustManager:通过
Java.registerClass动态构造一个"信任一切"的X509TrustManager,供后续SSLContext.init(null, [TrustManager.$new()], null)替换使用(参见 android-advanced.md 中的 SSLContext 替换写法); - NetworkSecurityConfig:Android 7.0+ 默认禁止明文流量(cleartext),Hook
isCleartextTrafficPermitted返回true可放行 HTTP 明文流量,便于在代理中观察未加密数据。 - 每个
try/catch都保证某层类不存在(如 App 未使用 OkHttp)时脚本整体不崩溃,这是通用型脚本的标准容错写法。
2. 通用 Root 检测绕过
Java.perform(function() { // File.exists 绕过 var File = Java.use("java.io.File"); var rootPaths = ["su", "Superuser", "magisk", "busybox", "xposed", "/system/xbin/su", "/system/bin/su", "/sbin/su", "/data/local/xbin/su", "/data/local/bin/su"]; File.exists.implementation = function() { var path = this.getAbsolutePath(); for (var i = 0; i < rootPaths.length; i++) { if (path.toLowerCase().indexOf(rootPaths[i].toLowerCase()) !== -1) { console.log("[Root] Blocked: " + path); return false; } } return this.exists(); }; // Runtime.exec 绕过 var Runtime = Java.use("java.lang.Runtime"); Runtime.exec.overload('java.lang.String').implementation = function(cmd) { if (cmd.indexOf("su") !== -1 || cmd.indexOf("which") !== -1) { console.log("[Root] Blocked exec: " + cmd); throw Java.use("java.io.IOException").$new("Permission denied"); } return this.exec(cmd); }; // Build.TAGS 绕过 var Build = Java.use("android.os.Build"); Build.TAGS.value = "release-keys"; });- 黑名单覆盖了常见 root 相关文件路径与关键字(
su、Superuser、magisk、busybox、xposed);对路径做小写归一化避免大小写绕过。 Runtime.exec拦截su与which命令,直接抛IOException模拟"无权限",阻断基于命令执行的 root 探测。Build.TAGS改为"release-keys"伪造官方签名构建特征。仓库 android-advanced.md 补充了更多检测面:/proc/self/mounts中的 magisk 痕迹、/data/adb/目录探测、SafetyNet/Play Integrity(需 Magisk Hide / Zygisk + Shamiko 层处理)、opendir/access文件系统探测等,可按需扩展。
3. 反调试绕过
Java.perform(function() { // Debug.isDebuggerConnected var Debug = Java.use("android.os.Debug"); Debug.isDebuggerConnected.implementation = function() { console.log("[AntiDebug] isDebuggerConnected → false"); return false; }; // TracerPid 检测绕过(native 层) var fopen = Module.findExportByName("libc.so", "fopen"); Interceptor.attach(fopen, { onEnter: function(args) { this.path = args[0].readUtf8String(); }, onLeave: function(retval) { if (this.path && this.path.indexOf("/proc/") !== -1 && this.path.indexOf("/status") !== -1) { // 可以进一步 hook fgets 修改 TracerPid } } }); });- Java 层:
Debug.isDebuggerConnected()是 App 最常见的调试器探测点,替换为返回false即可。 - native 层:
/proc/self/status中的TracerPid非 0 表示正被调试。脚本通过Module.findExportByName("libc.so", "fopen")与Interceptor.attach监听对/proc/.../status文件的打开,注释处可进一步 Hookfgets将读到的TracerPid内容改写为 0。仓库 tools-dynamic.md 提供了更通用的 native 反调试范例:Hookptrace(PTRACE_TRACEME)在onLeave中retval.replace(ptr(0)),以及 Hookclock_gettime冻结时间戳以对抗基于耗时的检测。
4. 模拟器检测绕过
Java.perform(function() { var Build = Java.use("android.os.Build"); Build.FINGERPRINT.value = "google/walleye/walleye:8.1.0/OPM1.171019.011/4448085:user/release-keys"; Build.MODEL.value = "Pixel 2"; Build.MANUFACTURER.value = "Google"; Build.BRAND.value = "google"; Build.DEVICE.value = "walleye"; Build.PRODUCT.value = "walleye"; Build.HARDWARE.value = "walleye"; // TelephonyManager var TelephonyManager = Java.use("android.telephony.TelephonyManager"); TelephonyManager.getDeviceId.implementation = function() { return "352099001761481"; }; TelephonyManager.getSubscriberId.implementation = function() { return "310260000000000"; }; TelephonyManager.getSimSerialNumber.implementation = function() { return "89014103211118510720"; }; });- 通过修改
Build系列静态字段(FINGERPRINT、MODEL、MANUFACTURER等),把设备伪装成 Pixel 2 真机,绕过基于 Build 信息的模拟器指纹检测。 - 通过伪造
getDeviceId(IMEI)、getSubscriberId(IMSI)、getSimSerialNumber(ICCID)等 TelephonyManager 返回值,绕过基于"无 SIM 卡/无蜂窝信息"的模拟器判定。仓库 frida-bypass-kit.md 将伪造运营商名称与电话号码也归入这一类别。
六、数据存储 Hook:SharedPreferences 与 SQLite
分析本地存储能直接获取 token、会话、配置等敏感数据,是理解 App 数据模型的捷径。
1. Hook SharedPreferences
Java.perform(function() { var SharedPreferencesImpl = Java.use("android.app.SharedPreferencesImpl"); SharedPreferencesImpl.getString.implementation = function(key, defValue) { var value = this.getString(key, defValue); console.log("[SP.get] " + key + " = " + value); return value; }; var Editor = Java.use("android.app.SharedPreferencesImpl$EditorImpl"); Editor.putString.implementation = function(key, value) { console.log("[SP.put] " + key + " = " + value); return this.putString(key, value); }; });同时监听读取(getString)与写入(putString)两个方向:写入方向能捕获 App 保存 token/配置的时机与明文值,读取方向能看到各业务模块实际消费了哪些配置。类名SharedPreferencesImpl$EditorImpl中的$是 Java 内部类在 Frida 类名中的标准写法。
2. Hook SQLite
Java.perform(function() { var SQLiteDatabase = Java.use("android.database.sqlite.SQLiteDatabase"); SQLiteDatabase.rawQuery.implementation = function(sql, args) { console.log("[SQL] " + sql); if (args) console.log(" args: " + JSON.stringify(args)); return this.rawQuery(sql, args); }; SQLiteDatabase.execSQL.overload('java.lang.String').implementation = function(sql) { console.log("[SQL.exec] " + sql); this.execSQL(sql); }; });rawQuery覆盖查询类 SQL(并打印绑定参数),execSQL覆盖建表/写入类 SQL。通过完整 SQL 日志可还原数据库表结构与业务数据流,也可定位 App 是否将敏感信息明文落库。
七、脱壳 Hook:DEX Dump 与 ClassLoader 追踪
对加固(加壳)App,静态反编译拿不到真实业务代码,需要在运行时从内存中还原 DEX。仓库 android-advanced.md 的"加固/壳识别与脱壳"章节列出了 360 加固(libjiagu.so)、腾讯乐固(libshell*.so)、梆梆加固(libDexHelper.so)等常见加固的特征,并指出通用方案包括 FART、Frida DEX Dump、BlackDex 与手动 dump。
1. 通用 DEX Dump(枚举 ClassLoader)
Java.perform(function() { Java.enumerateClassLoaders({ onMatch: function(loader) { try { var pathList = Java.cast(loader, Java.use("dalvik.system.BaseDexClassLoader")).pathList.value; var dexElements = pathList.dexElements.value; for (var i = 0; i < dexElements.length; i++) { var dexFile = dexElements[i].dexFile.value; if (dexFile) { console.log("[DEX] " + dexFile.getName()); // 可以进一步 dump dex 内容 } } } catch(e) {} }, onComplete: function() {} }); });原理:每个 ClassLoader 内部持有pathList(DexPathList),其dexElements数组中的每个元素包含DexFile引用;加固壳在运行时通过自定义 ClassLoader 加载解密后的 DEX,因此遍历全部 ClassLoader 即可定位到"活"的 DEX 文件对象,再读取其内存区域保存为文件即可完成脱壳(脚本注释处即为 dump 扩展点)。Java.cast用于把未知类型的安全转换。
2. Hook ClassLoader.loadClass
Java.perform(function() { var ClassLoader = Java.use("java.lang.ClassLoader"); ClassLoader.loadClass.overload('java.lang.String').implementation = function(name) { if (name.indexOf("com.target") !== -1) { console.log("[ClassLoader] " + name); } return this.loadClass(name); }; });通过监听loadClass的类名入参,可以按包名前缀过滤出加固 App 在运行期实际加载的业务类清单,辅助确认脱壳时机(应在目标类首次加载之后 dump)以及还原加固 App 的真实类结构。
八、实用工具函数
以下四个函数是编写复杂 Hook 脚本的通用基础设施,可直接复制进任意脚本使用:
// 字节数组转十六进制 function bytesToHex(bytes) { if (!bytes) return "null"; var hex = []; for (var i = 0; i < bytes.length; i++) { hex.push(('0' + (bytes[i] & 0xFF).toString(16)).slice(-2)); } return hex.join(''); } // 打印调用栈 function printStack() { console.log(Java.use("android.util.Log").getStackTraceString( Java.use("java.lang.Throwable").$new())); } // 打印对象所有字段 function printFields(obj) { var fields = obj.class.getDeclaredFields(); fields.forEach(function(field) { field.setAccessible(true); try { console.log(" " + field.getName() + " = " + field.get(obj)); } catch(e) {} }); } // 搜索内存中的类实例 function findInstances(className) { Java.choose(className, { onMatch: function(instance) { console.log("[Instance] " + instance); printFields(instance); }, onComplete: function() {} }); }bytesToHex:加解密/Hash 场景的必备转换函数,& 0xFF处理负数 byte 值,slice(-2)保证两位输出。printStack:借助android.util.Log.getStackTraceString打印当前调用栈,用于定位某个方法由谁调用(反向追踪调用链)。printFields:反射打印对象全部字段(含私有字段,先setAccessible(true)),常用于在Java.choose命中的实例上提取内存中的敏感状态。findInstances:基于Java.choose在堆中搜索指定类的所有存活实例并打印字段,适合在不知道对象引用时"大海捞针"式定位(例如查找持有密钥的配置类实例)。仓库 tools-dynamic.md 还展示了 native 层的对应能力:Process.enumerateRanges+Memory.scan扫描内存特征、Memory.patchCode指令级补丁,可与之配合使用。
九、在 apk-reverse 工作流中的实战建议
本手册是apk-reverse技能动态分析环节的核心素材库,建议按照官方推荐工作流(SKILL.md)的节奏使用:
- 先静态后动态:先用
jadx -d jadx_out app.apk反编译、apktool d app.apk -o apktool_out解包,读完AndroidManifest.xml与主入口类(MainActivity、Application、登录/网络/加密/风控相关类)后,再决定 Hook 哪些类与方法;不要在没有看过 manifest 和主入口前就写 Hook。 - 按信号选择脚本:参考 frida-bypass-kit.md 的场景映射——App 检测到 root 拒绝运行 → Root 检测绕过;抓包时 HTTPS 看不到明文 → SSL Pinning 绕过;App 检测到模拟器拒绝运行 → 模拟器检测绕过;附加 Frida 后 App 崩溃 → 反调试绕过。推荐先用完整的 Bypass 框架跑一遍,再针对具体检测点用本手册的精准脚本微调。
- 先观察后修改:遵循"先 Hook Java 层,再看是否需要 native Hook;先打印参数与返回值,再决定是否主动修改返回值"的原则,避免过早修改返回值破坏程序状态。
- Java 不完整时转向 native:如果核心签名逻辑在
.so中(如System.loadLibrary()后关键逻辑消失、证书校验/风控在.so中),应结合 android-advanced.md 的 native Hook 方法(Module.findExportByName("libc.so", "open")、Module.findBaseAddress("libsecurity.so").add(offset))继续深入,并切换到ida-reverse/radare2做静态配合。 - 注意反检测对抗:目标 App 本身可能检测 Frida(如扫描
/proc/self/maps中的 frida-agent、探测默认端口 27042、检查线程名gmain/gdbus、检测函数序言被改写等,详见 anti-analysis.md)。此时需要更早加载注入(frida-gadget 方式)、Hook 检测函数本身或更换环境。 - 产出可复现证据:按技能输出要求,最终应说明 Hook 了哪个类/方法/导出函数、捕获了哪些参数与返回值、确认了哪些敏感点(登录、签名、root、SSL、WebView、JNI),形成可复现的命令/脚本/报告证据链。
十、参考资源
本手册脚本精选自社区知名的 Frida 脚本集合,包括:Frida 官方 API 参考文档;Frida CodeShare 社区脚本分享平台(可在线浏览他人提交的通用 Hook 脚本);awesome-frida 资源大全(按用途分类收录大量 Frida 工具与脚本);frida-codeshare-scripts 脚本收集仓库;Objection(基于 Frida 的运行时探索封装工具,可快速执行免写脚本的常见操作);r2frida(radare2 与 Frida 的集成,支持在 r2 界面中直接对目标进程做动态分析)。以上资源均可作为本手册脚本的补充与灵感来源,使用时请核对其对应 Frida 版本兼容性,并始终在授权范围内使用。
- AI 技能
- AI 插件
- 人工智能
【免费下载链接】agentic-awesome-skills
AAS Core is the local, agent-first control plane for complete catalog discovery, agent-owned selection, stack validation, and planning, backed by 2,600+ agentic skills. Includes CLI, local MCP, catalog, plugins, and Workbench.
相关推荐
agentic-awesome-skills 之 Android 高级逆向实战:Native SO 分析、Frida 动态对抗与加固脱壳全指南
agentic awesome skills 之 Android 高级逆向实战:Native SO 分析、Frida 动态对抗与加固脱壳全指南 本文是 agen
AI 技能AI 插件人工智能hooker 逆向工作台实战手册:基于 Frida 的 Android 通杀 Hook、自动化脚本生成与嵌入式 WebServer 全解析
hooker 逆向工作台实战手册:基于 Frida 的 Android 通杀 Hook、自动化脚本生成与嵌入式 WebServer 全解析 hooker 是一个
应用安全移动开发开发工具OWASP MASTG 实战:Android UnCrackable L1 逆向挑战——从 APK 静态分析到动态 Hook 提取隐藏密钥
OWASP MASTG 实战:Android UnCrackable L1 逆向挑战——从 APK 静态分析到动态 Hook 提取隐藏密钥 UnCrackabl
文档教程网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考