From 38c6301e02a367b3e86868002dcef785e0a94afd Mon Sep 17 00:00:00 2001 From: huji <669898595@qq.com> Date: Mon, 16 Oct 2023 14:49:22 +0800 Subject: [PATCH] add strong frida --- agent/frida/index.ts | 31 ++++++++++++++++++- agent/frida/lib/android.ts | 4 +-- agent/frida/lib/java.ts | 29 ++++++++++++++--- agent/frida/loader.ts | 30 ------------------ src/linktools/assets/android-tools.json | 3 +- src/linktools/cli/commands/android/frida.py | 2 +- .../cli/commands/android/objection.py | 2 +- src/linktools/cli/commands/ios/frida.py | 2 +- src/linktools/cli/commands/ios/objection.py | 2 +- src/linktools/frida/android.py | 17 +++++++--- 10 files changed, 76 insertions(+), 46 deletions(-) delete mode 100644 agent/frida/loader.ts diff --git a/agent/frida/index.ts b/agent/frida/index.ts index c2da5948..edff3afd 100644 --- a/agent/frida/index.ts +++ b/agent/frida/index.ts @@ -128,7 +128,36 @@ class Log { // script loader //////////////////////////////////////////////////////////////////////// -import { ScriptLoader } from "./loader"; +interface Parameters { + [name: string]: any; +} + +interface Script { + filename: string; + source: string; +} + +export class ScriptLoader { + + load(scripts: Script[], parameters: Parameters) { + for (const script of scripts) { + try { + let name = script.filename; + name = name.replace(/[\/\\]/g, '$'); + name = name.replace(/[^A-Za-z0-9_$]+/g, "_"); + name = `fn_${name}`.substring(0, 255); + const func = (0, eval)( + `(function ${name}(parameters) {${script.source}\n})\n` + + `//# sourceURL=${script.filename}` + ) + func(parameters); + } catch (e) { + let message = e.hasOwnProperty("stack") ? e.stack : e; + throw new Error(`Unable to load ${script.filename}: ${message}`); + } + } + } +} const scriptLoader = new ScriptLoader(); diff --git a/agent/frida/lib/android.ts b/agent/frida/lib/android.ts index bb2dc635..eeb70eeb 100644 --- a/agent/frida/lib/android.ts +++ b/agent/frida/lib/android.ts @@ -203,7 +203,7 @@ export class AndroidHelper { } catch (e) { if (helperThis.$useClassCallbackMap == null) { helperThis.$useClassCallbackMap = new Map(); - helperThis.$regiesterUseClassCallback(helperThis.$useClassCallbackMap); + helperThis.$registerUseClassCallback(helperThis.$useClassCallbackMap); } if (helperThis.$useClassCallbackMap.has(className)) { let callbackSet = helperThis.$useClassCallbackMap.get(className); @@ -223,7 +223,7 @@ export class AndroidHelper { $useClassCallbackMap: Map = null; - $regiesterUseClassCallback(map: Map) { + $registerUseClassCallback(map: Map) { const classLoaders = Java.use("java.util.HashSet").$new(); diff --git a/agent/frida/lib/java.ts b/agent/frida/lib/java.ts index 9c90eb29..342985ef 100644 --- a/agent/frida/lib/java.ts +++ b/agent/frida/lib/java.ts @@ -146,11 +146,32 @@ export class JavaHelper { return void 0; } + private $prettyClassName(className: string) { + if (className.startsWith("[L") && className.endsWith(";")) { + return `${className.substring(2, className.length - 1)}[]`; + } else if (className.startsWith("[")) { + switch(className.substring(1, 2)) { + case "B": return "byte[]"; + case "C": return "char[]"; + case "D": return "double[]"; + case "F": return "float[]"; + case "I": return "int[]"; + case "S": return "short[]"; + case "J": return "long[]"; + case "Z": return "boolean[]"; + case "V": return "void[]"; + } + } + return className; + } + /** * 为method添加properties * @param method 方法对象 */ private $defineMethodProperties = {}>(method: Java.Method): void { + const javaHelperThis = this; + Object.defineProperties(method, { className: { configurable: true, @@ -162,13 +183,13 @@ export class JavaHelper { configurable: true, enumerable: true, get() { - const ret = this.returnType.className; - const name = this.className + "." + this.methodName; + const ret = javaHelperThis.$prettyClassName(this.returnType.className); + const name = javaHelperThis.$prettyClassName(this.className) + "." + this.methodName; let args = ""; if (this.argumentTypes.length > 0) { - args = this.argumentTypes[0].className; + args = javaHelperThis.$prettyClassName(this.argumentTypes[0].className); for (let i = 1; i < this.argumentTypes.length; i++) { - args = args + ", " + this.argumentTypes[i].className; + args = args + ", " + javaHelperThis.$prettyClassName(this.argumentTypes[i].className); } } return ret + " " + name + "(" + args + ")"; diff --git a/agent/frida/loader.ts b/agent/frida/loader.ts deleted file mode 100644 index 9dd1a22b..00000000 --- a/agent/frida/loader.ts +++ /dev/null @@ -1,30 +0,0 @@ -interface Parameters { - [name: string]: any; -} - -interface Script { - filename: string; - source: string; -} - -export class ScriptLoader { - - load(scripts: Script[], parameters: Parameters) { - for (const script of scripts) { - try { - let name = script.filename; - name = name.replace(/[\/\\]/g, '$'); - name = name.replace(/[^A-Za-z0-9_$]+/g, "_"); - name = `fn_${name}`.substring(0, 255); - const func = (0, eval)( - `(function ${name}(parameters) {${script.source}\n})\n` + - `//# sourceURL=${script.filename}` - ) - func(parameters); - } catch (e) { - let message = e.hasOwnProperty("stack") ? e.stack : e; - throw new Error(`Unable to load ${script.filename}: ${message}`); - } - } - } -} \ No newline at end of file diff --git a/src/linktools/assets/android-tools.json b/src/linktools/assets/android-tools.json index cdff60b9..a1abc855 100644 --- a/src/linktools/assets/android-tools.json +++ b/src/linktools/assets/android-tools.json @@ -9,7 +9,8 @@ "ANDROID_TOOL_FRIDA_SERVER": [ { "name": "strong-frida-server-{version}-android-{abi}", - "url": "https://github.com/hzzheyang/strongR-frida-android/releases/download/{version}/hluda-server-{version}-android-{abi}.xz" + "url": "https://github.com/hzzheyang/strongR-frida-android/releases/download/{version}/hluda-server-{version}-android-{abi}.xz", + "min_version": "15.1.8" }, { "name": "frida-server-{version}-android-{abi}", diff --git a/src/linktools/cli/commands/android/frida.py b/src/linktools/cli/commands/android/frida.py index a5a113e4..e2a08b09 100755 --- a/src/linktools/cli/commands/android/frida.py +++ b/src/linktools/cli/commands/android/frida.py @@ -106,7 +106,7 @@ def on_session_detached(self, session, reason, crash) -> None: if target_app is None: raise CommandError("Unknown frontmost application") package = target_app.identifier - environ.logger.info(f"Target application: {package}") + environ.logger.info(f"Frida inject target application: {package}") app = Application( server, diff --git a/src/linktools/cli/commands/android/objection.py b/src/linktools/cli/commands/android/objection.py index b5e02e82..f2553a30 100644 --- a/src/linktools/cli/commands/android/objection.py +++ b/src/linktools/cli/commands/android/objection.py @@ -83,7 +83,7 @@ def run(self, args: [str]) -> Optional[int]: if target_app is None: raise CommandError("Unknown frontmost application") package = target_app.identifier - environ.logger.info(f"Target application: {package}") + environ.logger.info(f"Frida inject target application: {package}") objection_args += ["-g", package] objection_args += ["explore"] diff --git a/src/linktools/cli/commands/ios/frida.py b/src/linktools/cli/commands/ios/frida.py index 7c8f973b..6bf66c27 100755 --- a/src/linktools/cli/commands/ios/frida.py +++ b/src/linktools/cli/commands/ios/frida.py @@ -99,7 +99,7 @@ def on_session_detached(self, session, reason, crash) -> None: if target_app is None: raise CommandError("Unknown frontmost application") bundle_id = target_app.identifier - environ.logger.info(f"Target application: {bundle_id}") + environ.logger.info(f"Frida inject target application: {bundle_id}") app = Application( server, diff --git a/src/linktools/cli/commands/ios/objection.py b/src/linktools/cli/commands/ios/objection.py index 5ccea758..5414bd19 100644 --- a/src/linktools/cli/commands/ios/objection.py +++ b/src/linktools/cli/commands/ios/objection.py @@ -75,7 +75,7 @@ def run(self, args: [str]) -> Optional[int]: if target_app is None: raise CommandError("Unknown frontmost application") bundle_id = target_app.identifier - environ.logger.info(f"Target application: {bundle_id}") + environ.logger.info(f"Frida inject target application: {bundle_id}") objection_args += ["-g", bundle_id] objection_args += ["explore"] diff --git a/src/linktools/frida/android.py b/src/linktools/frida/android.py index 2cbf00e7..32061832 100644 --- a/src/linktools/frida/android.py +++ b/src/linktools/frida/android.py @@ -66,7 +66,12 @@ def _start(self): server_path = self._prepare_executable() # 转发端口 - self._forward = self._device.forward(f"tcp:{self._local_port}", f"tcp:{self._remote_port}") + if self._forward is not None: + self._forward.stop() + self._forward = self._device.forward( + f"tcp:{self._local_port}", + f"tcp:{self._remote_port}" + ) # 创建软链 self._device.sudo("mkdir", "-p", self._server_dir) @@ -95,8 +100,9 @@ def _stop(self): self._device.sudo("kill", "-9", process.pid, ignore_errors=True) finally: # 把转发端口给移除了,不然会一直占用这个端口 - utils.ignore_error(self._forward.stop) - self._forward = None + if self._forward is not None: + self._forward.stop() + self._forward = None @classmethod def _get_executables(cls, abi: str, version: str): @@ -104,7 +110,10 @@ def _get_executables(cls, abi: str, version: str): configs = environ.get_config("ANDROID_TOOL_FRIDA_SERVER", type=list) for config in configs: config.update(version=version, abi=abi) - result.append(cls.Executable(config)) + min_version = config.get("min_version", "0.0.0") + max_version = config.get("max_version", "99999.0.0") + if utils.parse_version(min_version) <= utils.parse_version(version) <= utils.parse_version(max_version): + result.append(cls.Executable(config)) return result def _prepare_executable(self):