#!/usr/bin/env python3 # 工作手机 · Frida 主控通道·实机冒烟脚本(一次性跑完 8 项验证) # 用法:python3 sdk/scripts/_hook_smoke.py import json, sys, urllib.request, urllib.parse, time DEVICE = sys.argv[1] if len(sys.argv) > 1 else 'xgfe65eimrrofyws' BASE = 'http://127.0.0.1:8899' def get(path, params=None): url = f'{BASE}{path}' if params: url += '?' + urllib.parse.urlencode(params) with urllib.request.urlopen(url, timeout=60) as r: return json.loads(r.read()) def post(path, body): req = urllib.request.Request( f'{BASE}{path}', data=json.dumps(body).encode(), headers={'Content-Type': 'application/json'}, method='POST', ) with urllib.request.urlopen(req, timeout=120) as r: return json.loads(r.read()) def section(title): print('\n' + '=' * 60) print(f' {title}') print('=' * 60) def show(label, value, limit=200): s = json.dumps(value, ensure_ascii=False) if len(s) > limit: s = s[:limit] + ' …(truncated)' print(f'{label} → {s}') # 1) probe section('1) /api/v3/hook/probe — Hook 探测') probe = get(f'/api/v3/hook/probe/{DEVICE}') show('supports_hook', probe.get('supports_hook')) show('frida_version', probe.get('frida_version')) show('wechat_version', probe.get('wechat_version')) show('profile.nickname', probe.get('profile', {}).get('profile', {}).get('nickname')) # 2) actions 清单 section('2) /api/v3/hook/actions — 全部动作清单') acts = get('/api/v3/hook/actions') show('total_actions', acts.get('total_actions')) show('total_modules', acts.get('total_modules')) # 3) 一次性取数 section('3) /api/v3/hook/data — 取微信资料/联系人/群/消息/标签') data = get(f'/api/v3/hook/data/{DEVICE}', {'modules': 'profile,contacts,groups,messages,labels'}) core = data.get('data', {}) def _list(node, key1, key2=None): inner = node.get('data', node) if key2 and isinstance(inner, dict) and key2 in inner: return inner[key2] if isinstance(inner, dict) and key1 in inner: return inner[key1] if isinstance(inner, dict) and 'data' in inner and isinstance(inner['data'], list): return inner['data'] return inner if isinstance(inner, list) else [] contacts = _list(core['contacts'], 'contacts') groups = _list(core['groups'], 'groups') messages = _list(core['messages'], 'messages') labels = _list(core['labels'], 'labels') print(f'contacts : {len(contacts)} 条') print(f'groups : {len(groups)} 个') print(f'messages : {len(messages)} 条') print(f'labels : {len(labels)} 个') remark = [c for c in contacts if c.get('remark')] namedgrp = [g for g in groups if g.get('name')] print(f' - 有备注联系人: {len(remark)} | 例子:', ', '.join((c.get('remark') or '?')[:24] for c in remark[:5])) print(f' - 已命名群 : {len(namedgrp)} | 例子:', ', '.join((g.get('name') or '?')[:24] for g in namedgrp[:5])) print(f' - 标签 : {len(labels)} | 例子:', ', '.join((l.get('name') or '?')[:18] for l in labels[:8])) # 4) hookStatus / getMoments / getWechatVersion 直调 section('4) /api/v3/hook/execute — hookStatus + getWechatVersion') hs = post('/api/v3/hook/execute', { 'device_id': DEVICE, 'platform': 'wechat', 'action': 'get_hook_status', 'params': {}, 'hook_only': True }) show('hookStatus', hs) gv = post('/api/v3/hook/execute', { 'device_id': DEVICE, 'platform': 'wechat', 'action': 'get_wechat_version', 'params': {}, 'hook_only': True }) show('getWechatVersion', gv) # 5) 朋友圈 section('5) /api/v3/hook/execute — getMoments(limit=3)') mm = post('/api/v3/hook/execute', { 'device_id': DEVICE, 'platform': 'wechat', 'action': 'get_moments', 'params': {'limit': 3}, 'hook_only': True }) show('getMoments', mm, 400) # 6) 真发一条消息到文件传输助手 section('6) /api/v3/hook/execute — send_message → 文件传输助手') ts = time.strftime('%H:%M:%S') send = post('/api/v3/hook/execute', { 'device_id': DEVICE, 'platform': 'wechat', 'action': 'send_message', 'params': { 'to_id': 'filehelper', 'content': f'[E2E] Frida 主控通道 实机冒烟 {ts}', 'msg_type': 'text', }, 'hook_only': True }) show('send_message', send) # 7) 拉一条最近消息证明 read-back section('7) /api/v3/hook/execute — get_recent_messages(limit=1)') rm = post('/api/v3/hook/execute', { 'device_id': DEVICE, 'platform': 'wechat', 'action': 'get_recent_messages', 'params': {'limit': 1}, 'hook_only': True }) show('get_recent_messages', rm, 400) # 8) 走标准 unified channel=hook 的 sendMessage(验证存客宝侧路径) section('8) /api/v3/message/send channel=hook (存客宝标准入口)') um = post('/api/v3/message/send', { 'device_id': DEVICE, 'platform': 'wechat', 'to_id': 'filehelper', 'content': f'[E2E] unified channel=hook {ts}', 'msg_type': 'text', 'channel': 'hook' }) show('unified.sendMessage', um, 400) print('\n ✅ Hook 主控冒烟测试完成')