When to Use / When Not to Use
- Use: when a new script is needed—interception (encryption/network/files), bypass (detection/pinning), tracing (JNI/method calls)
- Use: variants not covered by existing templates—adapt off the [[re-frida/frida-scripts]] templates into target-specific scripts
- Don't use: to run existing scripts → go to [[re-frida]] (this skill only produces scripts; running and process management are in re-frida)
- Don't use: overall analysis of the anti-detection adversarial surface → [[re-analyze/anti-dynamic-workflow]]
- Don't use: problems solvable purely statically—take the [[re-apk]] / [[re-ghidra]] static path first; dynamic is the last resort
- Don't use: when the target is unreachable (no device/no root/no jailbreak, hardening blocks injection)—solve the environment first ([[re-frida]] tool preparation), don't force out a script
Tool Preparation
frida-tools (script authoring and run validation)
- Recommended (upstream path):
python -m pip install -U frida-tools, using a venv or pipx isolated environment is advised - Third-party channels:
brew install fridaand other non-upstream channels; verify version and maintenance status before installing, and do not treat them as equivalent to the pip path - Validation:
frida --version、frida-ps -U(after connecting a device) - Note:
frida(runtime) andfrida-tools(CLI) versions must match; cross-major upgrades (16 → 17) have API removals, see the version group in [[gotchas]] for differences in syntax
python3 (for script debugging)
- Per-platform same as [[re-python]] tool preparation
Decompilation assistance (for reconnaissance)
- jadx ([[re-apk]]) statically produces class/method lists; Ghidra/IDA ([[re-ghidra]] / [[re-ida]]) locate native-side symbols and call sites
- Validation: able to list target classes and method signatures by package name
Target Device/Emulator
- Android real device/emulator + frida-server (at least the same major as the host frida; installation see [[re-frida]] tool preparation); desktop targets directly on the local machine
- For iOS jailbreak environment frida-server see [[re-ios-jb]]
Operating Steps
Follow the four steps "probe → select → adapt → validate": probe before writing, don't guess. Record the path + sha256 of each step's output (characteristics list/script/validation output) (see [[re-triage]]) for report references.
-
Target Reconnaissance:
- Static: target package name/class names/key APIs ([[re-apk]] jadx output), hardening vendor characteristics ([[re-mobile-pack]]), Flutter/RN hybrid structure ([[re-hybrid-app]])
- Dynamic baseline: run once as-is to capture crashes and logs (crash characteristics → protection mechanism mapping, see [[re-analyze/anti-dynamic-workflow]])
- Output: target characteristics list—detection points/fully qualified names of target APIs/input-output forms/number of method overloads
- For uncertain class names/method names, first enumerate with a small script (
Java.enumerateLoadedClasses/Java.use(...).overloads), don't guess names - Record reconnaissance conclusions into the [[re-analyze/analysis-contract]] contract fields (package name/class names/API list) for reuse by scripts and reports
-
Template Selection: match the characteristics list against the [[re-frida/frida-scripts]] template table:
| Target characteristic | Template |
|---|---|
| HTTPS packet capture is encrypted by TLS (BoringSSL) | TLS key logging (SSLKEYLOGFILE) |
| Certificate pinning blocks packet capture | SSL pinning bypass (TrustManager/CertificatePinner) |
| Encryption algorithm/key extraction | Encryption interception (Cipher/SecretKeySpec all overloads) |
| Hardening/runtime decryption | DEX dump (class loading point) / SO dump |
| Mutual TLS client certificate | keystore p12 export |
| JNI dynamic registration needs to be recovered | RegisterNatives + convergence point dual hook |
| Anti-debugging/detection interception | Detection bypass table (root/properties/files/commands) |
- Features do not match any template → combined rewriting (assembling multiple templates) rather than writing from scratch
- After choosing a template, first read the known boundary comments inside the template ([[re-frida/frida-scripts]]) to avoid repeating pitfalls
-
Rewrite:
- Replace placeholders: package name/class name/method name (exact match, Java fully qualified name)
- overload exact matching: first
overloadsenumerate then define one by one or select by parameter type (see pitfall 1) - Structural specification: Java operations wrapped in
Java.perform; save the original reference, with the originalthiscall;Interceptor.attachin onEnter usethis.contextto read registers,changing the return value can only be done in onLeave using the parameterretval.replace(...)——thishas only returnAddress/context/errno/lastError/threadId/depth, nothis.returnValue; and retval is reused across calls, if it needs to be retained firstptr(retval.toString())copy - Output unified JSON (printable ASCII + hex dual format) via
send()transmitted out; each hook bodytry/catch, errors send messages and are not silent - Multiple hooks for the same class merged into one
.implementation(cache silently overwritten, see pitfall 2) - Skeleton reference (minimal Java + native dual-side structure, trimmed to target):
Java.perform(function () { var Cls = Java.use("com.target.Cls"); Cls.method.overload("java.lang.String").implementation = function (s) { try { send({ type: "call", arg: s ? s.toString() : null }); } catch (e) { send({ type: "error", msg: String(e) }); } return this.method(s); // 调原实现(保留原 this) }; }); Interceptor.attach( Process.getModuleByName("libtarget.so").getExportByName("func"), { onEnter: function (args) { send({ type: "native", arg0: args[0].toInt32() }); } } ); - Native side: exported symbols preferred (
Process.getModuleByName(...).getExportByName; old styleModule.getExportByNamesee [[gotchas]] version group); for non-exported functions use call-site hook or memory signature location
-
Verify:
frida -U -f <pkg> -l script.js --pause # spawn + 停在早期代码前 frida -U -f <pkg> -l script.js -o out.json # 输出存文件(大流量/批量时)- Verification checklist: hook attached successfully (no error output) → trigger target path (operate app or reproduce call) → output consistent with static analysis → repeated triggering output stable
- Output JSON parsable, target behavior meets expectations (target call intercepted/bypass effective)
- Failure → return to step 2 to reselect template or refine features; crash → locate according to the [[re-analyze/anti-dynamic-workflow]] crash comparison table; empty output → see [[decision-tree]] troubleshooting branches
Cross-domain combination
- [[re-frida]]: script execution (output of this skill → run by re-frida)
- [[re-mobile]] / [[re-android-native]]: mobile target scenario connection
- [[re-analyze/anti-dynamic-workflow]]: detection surface and crash iteration method
- [[re-frida/frida-scripts]]: template material library (re-frida references)
- [[re-analyze/analysis-contract]]: script output consumed according to the data contract (evidence archiving)
- [[re-ios-jb]]: iOS jailbroken environment execution side
Common pitfalls and traps
- overload mismatch silently fails: symptom — hook produces no output; cause — target method overload signature does not match the definition; countermeasure — first
Java.use(...).<method>.overloadslist all overloads before selecting - Java.use cache overwrite: symptom — only the last of multiple hooks takes effect; cause — multiple assignments to
.implementationon the same class silently overwrite; countermeasure — merge into a single hook - argument index is version-dependent: symptom — native arguments read incorrectly; cause — target version field/argument position changes; countermeasure — verify against the target symbol, do not copy empirical values
- writing scripts without reconnaissance: symptom — script does not match the target; cause — skipping step 1; countermeasure — probe first, then write
- bypass scripts observe only, do not persist: symptom — target state is modified after testing; cause — script contains write operations; countermeasure — scripts only read/log, bypass is used only for observation (red line)
- hook does not take effect when the class is not loaded: symptom — class exists but no output; cause — lazy loading/加固 delayed loading; countermeasure —
Java.chooseor hook the class loading point ([[re-analyze/anti-dynamic-workflow]]) - version-related API error: symptom —
Module.getExportByName is not a function; cause — Frida 17 removed the static Module lookup API; countermeasure — migrate the writing style according to the [[gotchas]] version groups - For the template selection branches and verification troubleshooting tree see [[decision-tree]]; for version differences and boundaries see [[gotchas]]; everything executes inside the sandbox ([[re-analyze/platform-tips]] highest principle), and script output is archived according to the [[re-analyze/analysis-contract]] contract