diff --git a/find_real_send_class.py b/find_real_send_class.py new file mode 100644 index 0000000000..dc6f6a0850 --- /dev/null +++ b/find_real_send_class.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +工作手机SDK - 微信8.0.56真实类名发现脚本 +通过Frida ClassLoader枚举找到真实的消息发送类 +""" +import frida, time, json, subprocess +from datetime import datetime + +PHONE_IP = "192.168.110.80" +FRIDA_PORT = 27042 +WECHAT_PID = 9462 +BASE = "/Users/karuo/Documents/开发/2、私域银行/工作手机" +HOOK_JS = BASE + "/sdk/agent/hook/frida_hook_listener.js" +RESULT_FILE = BASE + "/real_class_discovery_20260518.json" + +# 读取JS文件 +with open(HOOK_JS, encoding="utf-8") as f: + HOOK_SCRIPT = f.read() + +print(f"[{datetime.now().strftime('%H:%M:%S')}] 连接Frida PID={WECHAT_PID}...") +dm = frida.get_device_manager() +device = dm.add_remote_device(f"{PHONE_IP}:{FRIDA_PORT}") +session = device.attach(WECHAT_PID) + +events = [] +def on_message(m, d): + if m.get("type") == "send": + payload = m.get("payload", {}) + events.append(payload) + t = payload.get("type", "") + if t in ("hook_ok", "hook_fail", "ready", "class_found", "wechat_loader", "candidate_found", "candidate_methods", "message_insert"): + print(f" [EVENT:{t}] {json.dumps(payload, ensure_ascii=False)[:120]}") + +script = session.create_script(HOOK_SCRIPT) +script.on("message", on_message) +script.load() +print("[OK] Hook脚本已加载,等待3秒...") +time.sleep(3) +rpc = script.exports_sync + +results = {} + +# ============================================================ +# Step 1: 枚举ClassLoader,找到微信的ClassLoader +# ============================================================ +print("\n" + "="*60) +print("Step 1: 枚举ClassLoader,找到微信ClassLoader") +print("="*60) +r1 = rpc.trigger_send_capture("filehelper", "test") +print(f" ClassLoader数量: {r1.get('loaders_count', '?')}") +time.sleep(1) + +# 打印捕获到的ClassLoader信息 +wechat_loader_info = [e for e in events if e.get("type") == "wechat_loader"] +classloaders = [e for e in events if e.get("type") == "classloaders"] +if classloaders: + loaders = classloaders[-1].get("loaders", []) + print(f" 所有ClassLoader ({len(loaders)}个):") + for l in loaders[:10]: + print(f" {l}") + +# ============================================================ +# Step 2: 用正确ClassLoader批量查找候选类 +# ============================================================ +print("\n" + "="*60) +print("Step 2: 用微信ClassLoader查找消息发送候选类") +print("="*60) + +# 生成候选类列表(a-z, aa-az等) +candidates_modelmulti = [f"com.tencent.mm.modelmulti.{c}" for c in "abcdefghijklmnopqrstuvwxyz"] +candidates_messenger = [f"com.tencent.mm.plugin.messenger.foundation.a.{c}" for c in "abcdefghijklmnopqrstuvwxyz"] +candidates_extra = [ + "com.tencent.mm.model.chat.ChatManager", + "com.tencent.mm.ui.chatting.ChattingUIFragment", + "com.tencent.mm.plugin.messenger.service.MessageService", + "com.tencent.mm.plugin.messenger.ui.ChatUI", + "com.tencent.mm.plugin.chatting.ui.ChattingUI", + "com.tencent.mm.app.Application", + "com.tencent.mm.sdk.platformtools.Util", + "com.tencent.wcdb.database.SQLiteDatabase", + "com.tencent.mm.storage.MicroMsgDBHelper", + "com.tencent.mm.storage.DatabaseHelper", +] + +all_candidates = candidates_modelmulti + candidates_messenger + candidates_extra + +print(f" 检查 {len(all_candidates)} 个候选类...") +r2 = rpc.find_classes_batch(all_candidates) +print(f" 查找结果: success={r2.get('success')}") + +found_classes = {} +if r2.get("success") and r2.get("results"): + for cls, info in r2["results"].items(): + if info.get("exists"): + found_classes[cls] = info + print(f" ✅ {cls}") + if info.get("methods"): + for m in info["methods"][:5]: + print(f" {m}") + +results["found_classes"] = found_classes +print(f"\n 找到 {len(found_classes)} 个存在的类") + +# ============================================================ +# Step 3: 用ClassLoader方式尝试发送消息 +# ============================================================ +print("\n" + "="*60) +print("Step 3: 用ClassLoader方式尝试真实发送消息") +print("="*60) +r3 = rpc.send_message_with_loader({"to_id": "filehelper", "content": f"[ClassLoader测试{int(time.time())}]"}) +print(f" 结果: {json.dumps(r3, ensure_ascii=False)}") +results["send_with_loader"] = r3 + +# ============================================================ +# Step 4: 检查捕获到的事件 +# ============================================================ +print("\n" + "="*60) +print("Step 4: 捕获到的所有事件") +print("="*60) +for e in events: + print(f" [{e.get('type','?')}] {json.dumps(e, ensure_ascii=False)[:100]}") + +# ============================================================ +# 保存结果 +# ============================================================ +with open(RESULT_FILE, "w", encoding="utf-8") as f: + json.dump({"found_classes": found_classes, "events": events, "send_result": r3}, f, ensure_ascii=False, indent=2, default=str) +print(f"\n结果已保存: {RESULT_FILE}") + +script.unload() +session.detach() +print("完成!")