134 lines
5.0 KiB
Python
134 lines
5.0 KiB
Python
#!/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("完成!")
|