/** * android-wechat-sender-frida.js — 基于 Frida Daemon 的微信消息发送 * * 原理:写入队列文件 /data/local/tmp/frida_daemon/queue.jsonl * 由常驻微信进程的 Frida daemon 读取并发送 * * 前提: * 1. frida-server 运行中 * 2. frida_daemon.js 已注入微信进程(通过 Mac 端 frida CLI) * 3. 队列目录 /data/local/tmp/frida_daemon/ 存在且可写 * * 注意:发送为 fire-and-forget,daemon 会异步处理队列。 * 如需确认送达,可通过 sqlcipher 查询 message 表。 */ const fs = require('fs'); const QUEUE_DIR = '/data/local/tmp/frida_daemon'; const QUEUE_FILE = QUEUE_DIR + '/queue.jsonl'; function ensureDir() { try { if (!fs.existsSync(QUEUE_DIR)) { fs.mkdirSync(QUEUE_DIR, { recursive: true }); fs.chmodSync(QUEUE_DIR, 0o777); } } catch (e) { // ignore } } /** * 使用 Frida daemon 发送文本消息(fire-and-forget) * @param {string} toUser — wxid / 群聊ID * @param {string} content — 消息内容 * @returns {Promise<{ok: boolean, error?: string}>} */ async function sendTextMessageFrida(toUser, content) { if (!toUser || !content) { return { ok: false, error: 'toUser and content are required' }; } ensureDir(); const id = 'msg_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8); const payload = JSON.stringify({ talker: toUser, content, id }) + '\n'; try { fs.writeFileSync(QUEUE_FILE, payload); fs.chmodSync(QUEUE_FILE, 0o666); } catch (e) { return { ok: false, error: `Failed to write queue: ${e.message}` }; } // Fire-and-forget: daemon will process asynchronously // 给 daemon 一点时间处理(通常 < 1s) await new Promise(r => setTimeout(r, 500)); return { ok: true }; } module.exports = { sendTextMessageFrida };