{"id":28568612,"url":"https://github.com/cyrus-studio/frida_thread","last_synced_at":"2025-06-25T07:36:09.592Z","repository":{"id":286988359,"uuid":"963200549","full_name":"CYRUS-STUDIO/frida_thread","owner":"CYRUS-STUDIO","description":"Frida 调用 kill 命令挂起\u0026恢复 Android 线程（Frida uses the `kill` command to suspend \u0026 resume Android threads.）","archived":false,"fork":false,"pushed_at":"2025-04-09T10:19:36.000Z","size":6,"stargazers_count":1,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-10T16:41:15.624Z","etag":null,"topics":["frida","kill","thread","threads"],"latest_commit_sha":null,"homepage":"https://cyrus-studio.github.io/blog/posts/frida-%E8%B0%83%E7%94%A8-kill-%E5%91%BD%E4%BB%A4%E6%8C%82%E8%B5%B7%E6%81%A2%E5%A4%8D-android-%E7%BA%BF%E7%A8%8B/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CYRUS-STUDIO.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-04-09T10:07:01.000Z","updated_at":"2025-04-10T01:06:25.000Z","dependencies_parsed_at":"2025-04-09T11:34:20.973Z","dependency_job_id":null,"html_url":"https://github.com/CYRUS-STUDIO/frida_thread","commit_stats":null,"previous_names":["cyrus-studio/frida_thread"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/CYRUS-STUDIO/frida_thread","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CYRUS-STUDIO%2Ffrida_thread","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CYRUS-STUDIO%2Ffrida_thread/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CYRUS-STUDIO%2Ffrida_thread/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CYRUS-STUDIO%2Ffrida_thread/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CYRUS-STUDIO","download_url":"https://codeload.github.com/CYRUS-STUDIO/frida_thread/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CYRUS-STUDIO%2Ffrida_thread/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261827764,"owners_count":23215809,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["frida","kill","thread","threads"],"created_at":"2025-06-10T16:30:31.378Z","updated_at":"2025-06-25T07:36:09.566Z","avatar_url":"https://github.com/CYRUS-STUDIO.png","language":"JavaScript","readme":"\u003e 版权归作者所有，如有转发，请注明文章出处：\u003chttps://cyrus-studio.github.io/blog/\u003e\n\n\n\n# **Android 线程相关命令**\n\n\n\n## **获取 PID**\n\n\n\n```\nadb shell pidof com.shizhuang.duapp\n```\n\n\n## **查看线程信息**\n\n\n\n### **方法一：进入 /proc/\u003cpid\u003e/task**\n\n\n\n进入 adb shell 执行下面命令\n\n```\ncd /proc/$(pidof com.shizhuang.duapp)/task\nls\n```\n这个目录中每一个子目录的名字就是该 App 的一个线程的 TID（Thread ID）。\n\n\n\n你还可以进一步查看每个线程的状态：\n\n```\ncat /proc/$(pidof com.shizhuang.duapp)/task/\u003ctid\u003e/status\n```\n\n\n例如：\n\n```\ncat /proc/$(pidof com.shizhuang.duapp)/task/22432/status\n```\n\n\n### **方法二：使用 top 或 htop 查看线程**\n\n\n\n使用 top 查看线程信息\n\n```\ntop -H -p $(pidof com.shizhuang.duapp)\n```\n- -H 表示以线程方式查看\n\n- -p 指定 PID\n\n\n\n![word/media/image1.png](https://gitee.com/cyrus-studio/images/raw/master/fcba0742df92aa7ac76c23b9782248eb.png)\n\n\n或者使用 htop 查看线程信息\n\n```\nhtop -p $(pidof com.shizhuang.duapp)\n```\n\n\n\n\n![word/media/image2.png](https://gitee.com/cyrus-studio/images/raw/master/38cf170942d92deb8a21006ba4127500.png)\n\n\n## **通过 kill 命令 停止  / 挂起 / 恢复线程**\n\n\n\nkill 是 Linux 系统中用来向进程发送信号的命令，最常用于终止进程。虽然它名字叫 “kill”，但它可以发送多种信号，不只是“终止”。\n\n\n\n进入 adb shell，比如线程/进程 id 为 22432\n\n```\n# 停止指定进程/线程 \nkill 22432\n\n# 强制停止进程/线程\nkill -9 22432\n\n# 强制停止 com.cyrus.example\nkill -9 $(pidof com.cyrus.example)\n\n# 挂起进程/线程\nkill -19 22432\n\n# 继续进程/线程\nkill -18 22432\n```\n\n\nkill 命令详细介绍：[https://man7.org/linux/man-pages/man1/kill.1.html](https://man7.org/linux/man-pages/man1/kill.1.html)\n\n\n\n常见信号类型（默认是 SIGTERM）：\n\n| 信号名 | 数值 | 含义 |\n|--- | --- | ---|\n| SIGHUP | 1 | 挂起信号，通常用于重启进程配置 |\n| SIGINT | 2 | 中断信号，类似 Ctrl+C |\n| SIGQUIT | 3 | 退出信号，类似 Ctrl+\\ |\n| SIGKILL | 9 | 强制终止信号（无法捕获） |\n| SIGTERM | 15 | 终止信号（可捕获、默认） |\n| SIGSTOP | 19 | 暂停进程（无法捕获） |\n| SIGCONT | 18 | 恢复被暂停的进程 |\n\n\n# **使用 Frida 调用 kill 命令**\n\n\n\nkill 在 C 语言中是定义在 \u003csignal.h\u003e 中的一个标准函数，它本质上是一个系统调用的封装函数。\n\n\n\nkill 函数（C 标准库中的定义）\n\n```\n#include \u003csignal.h\u003e\n\nint kill(pid_t pid, int sig);\n```\n- pid：要发送信号的进程 ID。\n\n- sig：要发送的信号编号，比如 SIGKILL, SIGTERM, SIGSTOP 等。\n\n- 返回值：返回 0 表示成功。返回 -1 表示失败，并设置 errno。\n\n\n\n在底层，kill() 实际上会触发系统调用（比如 Linux 的 syscall kill），让内核发送信号给指定的进程。\n\n\n\n它是 UNIX/Linux 系统里最常用的进程间通信（IPC）手段之一。\n\n\n\n## **1. JS + NativeFunction 调用 libc 中的 kill**\n\n\n\n查找 libc 中的 kill 函数，并使用 NativeFunction 封装引用\n\n```\nconst killPtr = Module.findExportByName(null, 'kill');\nconst kill = new NativeFunction(killPtr, 'int', ['int', 'int']);\n```\n\n\n## **2. 在 JS 中调用这个函数**\n\n\n\n挂起线程\n\n```\n// 挂起进程\nconst result = kill(22432, 19);\n\nif (result === 0) {\n    console.log(\"✅ Signal sent!\");\n} else {\n    console.log(\"❌ Failed to send signal.\");\n}\n```\n\n\n恢复线程\n\n```\n// 恢复线程\nconst result = kill(22432, 18);\n\nif (result === 0) {\n    console.log(\"✅ Signal sent!\");\n} else {\n    console.log(\"❌ Failed to send signal.\");\n}\n```\n\n\n## **3. suspendThread / resumeThread**\n\n\n\n封装 suspendThread / resumeThread 函数用于挂起和恢复线程。\n\n\n\nkill.js：\n\n```\n// 加载 libc 中的 kill 函数\nconst killPtr = Module.findExportByName(null, 'kill');\nconst kill = new NativeFunction(killPtr, 'int', ['int', 'int']);\n\n// 信号常量\nconst SIGSTOP = 19;  // 暂停进程（不可被捕获）\nconst SIGCONT = 18;  // 继续执行进程\n\n// 封装 suspend/resume 函数\nfunction suspendThread(pid) {\n    const result = kill(pid, SIGSTOP);\n    if (result === 0) {\n        console.log(`✅ 成功挂起 PID=${pid}`);\n    } else {\n        console.log(`❌ 挂起失败 PID=${pid}`);\n    }\n}\n\nfunction resumeThread(pid) {\n    const result = kill(pid, SIGCONT);\n    if (result === 0) {\n        console.log(`✅ 成功恢复 PID=${pid}`);\n    } else {\n        console.log(`❌ 恢复失败 PID=${pid}`);\n    }\n}\n```\n\n\n执行脚本：\n\n```\nfrida -H 127.0.0.1:1234 -F -l kill.js\n```\n\n\n调用示例：\n\n```\n // 挂起线程 \nsuspendThread(22432);  // 替换为目标线程或进程的 PID\n\n// 恢复线程\nresumeThread(22432);\n```\n\n\n\n\n![word/media/image3.png](https://gitee.com/cyrus-studio/images/raw/master/cc16bd103b76e7c97bf05419bc8fe2dc.png)\n\n\n# **suspendOtherThread**\n\n\n\n实现一个 suspendOtherThread 函数，挂起除了 excludeList 中指定名字的所有线程。\n\n\n\n## **1. 读取线程列表**\n\n\n\n遍历 /proc/${pid}/task/ 目录下所有目录的名称得到 线程id\n\n```\nconst taskDir = `/proc/${pid}/task/`;\n\nvar dirList = Java.use('java.io.File').$new(taskDir).listFiles()\n\nfor (let i = 0; i \u003c dirList.length; i++) {\n\n    // 线程id\n    const tid = parseInt(dirList[i].getName());\n  \n}\n```\n\n\n## **2. 读取线程名称**\n\n\n\n线程名称就在 /proc/${pid}/task/${tid}/comm 文件中，读取 comm 文件内容得到线程名称。\n\n```\n/**\n * 读取文件内容并返回字符串\n *\n * @param path 文件路径\n * @returns {string|null} 文件内容\n */\nfunction readFileAsString(path) {\n    const File = Java.use(\"java.io.File\");\n    const FileInputStream = Java.use(\"java.io.FileInputStream\");\n    const InputStreamReader = Java.use(\"java.io.InputStreamReader\");\n    const BufferedReader = Java.use(\"java.io.BufferedReader\");\n    const StringBuilder = Java.use(\"java.lang.StringBuilder\");\n\n    const file = File.$new(path);\n    if (!file.exists()) {\n        console.log(`❌ 文件不存在: ${path}`);\n        return null;\n    }\n\n    const fis = FileInputStream.$new(file);\n    const isr = InputStreamReader.$new(fis, \"UTF-8\");\n    const reader = BufferedReader.$new(isr);\n    const sb = StringBuilder.$new();\n\n    let line;\n    while ((line = reader.readLine()) !== null) {\n        sb.append(line);\n    }\n\n    reader.close();\n    return sb.toString();\n}\n\n/**\n * comm 文件内容就是线程名称\n *\n * @param pid   进程 id\n * @param tid   线程 id\n * @returns {string} 线程名称\n */\nfunction readComm(pid, tid) {\n    const path = `/proc/${pid}/task/${tid}/comm`;\n    return readFileAsString(path);\n}\n```\n\n\n相关文档：\n\n- [https://docs.oracle.com/javase/8/docs/api/java/io/File.html](https://docs.oracle.com/javase/8/docs/api/java/io/File.html)\n\n- [https://frida.re/docs/javascript-api/#file](https://frida.re/docs/javascript-api/#file)\n\n\n\n## **3. 挂起线程**\n\n\n\n挂起除了 excludeList 中指定名字的所有线程\n\n```\nfunction suspendOtherThread(pid, excludeList) {\n    Java.perform(function () {\n        const taskDir = `/proc/${pid}/task/`;\n\n        var dirList = Java.use('java.io.File').$new(taskDir).listFiles()\n\n        for (let i = 0; i \u003c dirList.length; i++) {\n\n            const tid = parseInt(dirList[i].getName());\n            if (isNaN(tid)) continue;\n\n            const threadName = readComm(pid, tid);\n            if (!threadName) continue;\n\n            // 只要 threadName 包含 excludeList 中的任意关键字，就会被排除（跳过不挂起）\n            if (excludeList.some(keyword =\u003e threadName.includes(keyword))) {\n                console.log(`🟢 跳过线程 \"${threadName}\" (TID=${tid})`);\n            } else {\n                console.log(`🛑 挂起线程 \"${threadName}\" (TID=${tid})`);\n                suspendThread(tid);\n            }\n        }\n    })\n}\n```\n\n\n## **4. 调用示例**\n\n\n\n```\n// 示例：只保留 excludeList 中指定的线程运行，其它全部挂起\nconst pid = Process.id;\nconst excludeList = [\n    \"main\",\n    \"RenderThread\",\n    \"m.cyrus.example\",\n    \"frida\",\n];\n\nsuspendOtherThread(pid, excludeList);\n```\n\n\n执行脚本\n\n```\nfrida -H 127.0.0.1:1234 -F -l kill.js\n```\n\n\n效果如下：\n\n\n\n![word/media/image4.png](https://gitee.com/cyrus-studio/images/raw/master/799bc1eeed91370cbf8ff43d9b8c0715.png)\n\n\n# **resumeOtherThread**\n\n\n\n恢复线程也是类似。\n\n```\n/**\n * 恢复除了 excludeList 中指定名字的所有线程\n * @param {number} pid - 当前进程 PID\n * @param {string[]} excludeList - 不需要恢复的线程名字数组\n */\nfunction resumeOtherThread(pid, excludeList) {\n    Java.perform(function () {\n        const taskDir = `/proc/${pid}/task/`;\n\n        var dirList = Java.use('java.io.File').$new(taskDir).listFiles()\n\n        for (let i = 0; i \u003c dirList.length; i++) {\n\n            const tid = parseInt(dirList[i].getName());\n            if (isNaN(tid)) continue;\n\n            const threadName = readComm(pid, tid);\n            if (!threadName) continue;\n\n            // 只要 threadName 包含 excludeList 中的任意关键字，就会被排除（跳过不恢复）\n            if (excludeList.some(keyword =\u003e threadName.includes(keyword))) {\n                console.log(`🟢 跳过线程 \"${threadName}\" (TID=${tid})`);\n            } else {\n                console.log(`🔄 恢复线程 \"${threadName}\" (TID=${tid})`);\n                resumeThread(tid);\n            }\n        }\n    })\n}\n```\n\n\n执行脚本\n\n```\nfrida -H 127.0.0.1:1234 -F -l kill.js\n```\n\n\n调用示例：\n\n```\n// 示例：只保留 excludeList 中指定的线程运行，其它全部挂起\nconst pid = Process.id;\nconst excludeList = [\n    \"main\",\n    \"RenderThread\",\n    \"m.cyrus.example\",\n    \"frida\",\n];\n\nresumeOtherThread(pid, excludeList);\n```\n\n\n输出如下：\n\n```\n🟢 跳过线程 \"m.cyrus.example\" (TID=31263)\n🔄 恢复线程 \"Jit thread pool\" (TID=31269)\n✅ 成功恢复 PID=31269\n🔄 恢复线程 \"Signal Catcher\" (TID=31274)\n✅ 成功恢复 PID=31274\n🔄 恢复线程 \"ADB-JDWP Connec\" (TID=31275)\n✅ 成功恢复 PID=31275\n🔄 恢复线程 \"HeapTaskDaemon\" (TID=31276)\n✅ 成功恢复 PID=31276\n🔄 恢复线程 \"ReferenceQueueD\" (TID=31277)\n✅ 成功恢复 PID=31277\n🔄 恢复线程 \"FinalizerDaemon\" (TID=31278)\n✅ 成功恢复 PID=31278\n🔄 恢复线程 \"FinalizerWatchd\" (TID=31279)\n✅ 成功恢复 PID=31279\n🔄 恢复线程 \"Binder:31263_1\" (TID=31280)\n✅ 成功恢复 PID=31280\n🔄 恢复线程 \"Binder:31263_2\" (TID=31281)\n✅ 成功恢复 PID=31281\n🔄 恢复线程 \"Binder:31263_3\" (TID=31282)\n✅ 成功恢复 PID=31282\n🔄 恢复线程 \"Profile Saver\" (TID=31283)\n✅ 成功恢复 PID=31283\n🟢 跳过线程 \"RenderThread\" (TID=31284)\n🔄 恢复线程 \"Binder:31263_4\" (TID=31287)\n✅ 成功恢复 PID=31287\n🟢 跳过线程 \"m.cyrus.example\" (TID=31293)\n🟢 跳过线程 \"gmain\" (TID=31294)\n🔄 恢复线程 \"gdbus\" (TID=31296)\n✅ 成功恢复 PID=31296\n🔄 恢复线程 \"Thread-20\" (TID=31297)\n✅ 成功恢复 PID=31297\n🟢 跳过线程 \"m.cyrus.example\" (TID=31263)\n🔄 恢复线程 \"Jit thread pool\" (TID=31269)\n✅ 成功恢复 PID=31269\n🔄 恢复线程 \"Signal Catcher\" (TID=31274)\n✅ 成功恢复 PID=31274\n🔄 恢复线程 \"ADB-JDWP Connec\" (TID=31275)\n✅ 成功恢复 PID=31275\n🔄 恢复线程 \"HeapTaskDaemon\" (TID=31276)\n✅ 成功恢复 PID=31276\n🔄 恢复线程 \"ReferenceQueueD\" (TID=31277)\n✅ 成功恢复 PID=31277\n🔄 恢复线程 \"FinalizerDaemon\" (TID=31278)\n✅ 成功恢复 PID=31278\n🔄 恢复线程 \"FinalizerWatchd\" (TID=31279)\n✅ 成功恢复 PID=31279\n🔄 恢复线程 \"Binder:31263_1\" (TID=31280)\n✅ 成功恢复 PID=31280\n🔄 恢复线程 \"Binder:31263_2\" (TID=31281)\n✅ 成功恢复 PID=31281\n🔄 恢复线程 \"Binder:31263_3\" (TID=31282)\n✅ 成功恢复 PID=31282\n🔄 恢复线程 \"Profile Saver\" (TID=31283)\n✅ 成功恢复 PID=31283\n🟢 跳过线程 \"RenderThread\" (TID=31284)\n🔄 恢复线程 \"Binder:31263_4\" (TID=31287)\n✅ 成功恢复 PID=31287\n🟢 跳过线程 \"m.cyrus.example\" (TID=31293)\n🟢 跳过线程 \"gmain\" (TID=31294)\n🔄 恢复线程 \"gdbus\" (TID=31296)\n✅ 成功恢复 PID=31296\n🔄 恢复线程 \"Thread-38\" (TID=31297)\n✅ 成功恢复 PID=31297\n```\n\n\n# **完整源码**\n\n\n\n```\n// 加载 libc 中的 kill 函数\nconst killPtr = Module.findExportByName(null, 'kill');\nconst kill = new NativeFunction(killPtr, 'int', ['int', 'int']);\n\n// 信号常量\nconst SIGSTOP = 19;  // 暂停进程（不可被捕获）\nconst SIGCONT = 18;  // 继续执行进程\n\n/**\n * 挂起线程\n *\n * @param pid 线程 id\n */\nfunction suspendThread(pid) {\n    const result = kill(pid, SIGSTOP);\n    if (result === 0) {\n        console.log(`✅ 成功挂起 PID=${pid}`);\n    } else {\n        console.log(`❌ 挂起失败 PID=${pid}`);\n    }\n}\n\n/**\n * 恢复线程\n *\n * @param pid 线程 id\n */\nfunction resumeThread(pid) {\n    const result = kill(pid, SIGCONT);\n    if (result === 0) {\n        console.log(`✅ 成功恢复 PID=${pid}`);\n    } else {\n        console.log(`❌ 恢复失败 PID=${pid}`);\n    }\n}\n\n/**\n * 读取文件内容并返回字符串\n *\n * @param path 文件路径\n * @returns {string|null} 文件内容\n */\nfunction readFileAsString(path) {\n    const File = Java.use(\"java.io.File\");\n    const FileInputStream = Java.use(\"java.io.FileInputStream\");\n    const InputStreamReader = Java.use(\"java.io.InputStreamReader\");\n    const BufferedReader = Java.use(\"java.io.BufferedReader\");\n    const StringBuilder = Java.use(\"java.lang.StringBuilder\");\n\n    const file = File.$new(path);\n    if (!file.exists()) {\n        console.log(`❌ 文件不存在: ${path}`);\n        return null;\n    }\n\n    const fis = FileInputStream.$new(file);\n    const isr = InputStreamReader.$new(fis, \"UTF-8\");\n    const reader = BufferedReader.$new(isr);\n    const sb = StringBuilder.$new();\n\n    let line;\n    while ((line = reader.readLine()) !== null) {\n        sb.append(line);\n    }\n\n    reader.close();\n    return sb.toString();\n}\n\n/**\n * comm 文件内容就是线程名称\n *\n * @param pid   进程 id\n * @param tid   线程 id\n * @returns {string} 线程名称\n */\nfunction readComm(pid, tid) {\n    const path = `/proc/${pid}/task/${tid}/comm`;\n    return readFileAsString(path);\n}\n\n/**\n * 挂起除了 excludeList 中指定名字的所有线程\n * @param {number} pid - 当前进程 PID\n * @param {string[]} excludeList - 不需要挂起的线程名字数组\n */\nfunction suspendOtherThread(pid, excludeList) {\n    Java.perform(function () {\n        const taskDir = `/proc/${pid}/task/`;\n\n        var dirList = Java.use('java.io.File').$new(taskDir).listFiles()\n\n        for (let i = 0; i \u003c dirList.length; i++) {\n\n            const tid = parseInt(dirList[i].getName());\n            if (isNaN(tid)) continue;\n\n            const threadName = readComm(pid, tid);\n            if (!threadName) continue;\n\n            // 只要 threadName 包含 excludeList 中的任意关键字，就会被排除（跳过不挂起）\n            if (excludeList.some(keyword =\u003e threadName.includes(keyword))) {\n                console.log(`🟢 跳过线程 \"${threadName}\" (TID=${tid})`);\n            } else {\n                console.log(`🛑 挂起线程 \"${threadName}\" (TID=${tid})`);\n                suspendThread(tid);\n            }\n        }\n    })\n}\n\n/**\n * 恢复除了 excludeList 中指定名字的所有线程\n * @param {number} pid - 当前进程 PID\n * @param {string[]} excludeList - 不需要恢复的线程名字数组\n */\nfunction resumeOtherThread(pid, excludeList) {\n    Java.perform(function () {\n        const taskDir = `/proc/${pid}/task/`;\n\n        var dirList = Java.use('java.io.File').$new(taskDir).listFiles()\n\n        for (let i = 0; i \u003c dirList.length; i++) {\n\n            const tid = parseInt(dirList[i].getName());\n            if (isNaN(tid)) continue;\n\n            const threadName = readComm(pid, tid);\n            if (!threadName) continue;\n\n            // 只要 threadName 包含 excludeList 中的任意关键字，就会被排除（跳过不恢复）\n            if (excludeList.some(keyword =\u003e threadName.includes(keyword))) {\n                console.log(`🟢 跳过线程 \"${threadName}\" (TID=${tid})`);\n            } else {\n                console.log(`🔄 恢复线程 \"${threadName}\" (TID=${tid})`);\n                resumeThread(tid);\n            }\n        }\n    })\n}\n\n// 示例：只保留 excludeList 中指定的线程运行，其它全部挂起\nconst pid = Process.id;\nconst excludeList = [\n    \"main\",\n    \"RenderThread\",\n    \"m.cyrus.example\",\n    \"frida\",\n];\n\n// suspendOtherThread(pid, excludeList);\nresumeOtherThread(pid, excludeList);\n```\n\n\n执行脚本\n\n```\nfrida -H 127.0.0.1:1234 -F -l kill.js\n```\n\n\n开源地址：[https://github.com/CYRUS-STUDIO/frida_thread](https://github.com/CYRUS-STUDIO/frida_thread)\n\n\n\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyrus-studio%2Ffrida_thread","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcyrus-studio%2Ffrida_thread","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcyrus-studio%2Ffrida_thread/lists"}