#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 工作手机SDK - 截图验证v2 用ADB截图(可靠),Frida控制微信操作 """ import frida, time, json, os, subprocess from datetime import datetime PHONE_IP = "192.168.110.80" ADB_SERIAL = "192.168.110.80:5555" FRIDA_PORT = 27042 WECHAT_PID = 16816 BASE = "/Users/karuo/Documents/开发/2、私域银行/工作手机" HOOK_SCRIPT = BASE + "/sdk/agent/hook/wechat_hook_v2.js" SCREENSHOT_DIR = BASE + "/开发文档/6、测试/live_verify_20260518/screenshots" RESULT_FILE = BASE + "/verification_screenshot_v2_20260518.json" os.makedirs(SCREENSHOT_DIR, exist_ok=True) def adb_screenshot(name, wait=0.5): """用ADB截图并拉取到本地""" remote = f"/sdcard/{name}.png" local = f"{SCREENSHOT_DIR}/{name}.png" time.sleep(wait) # 截图 r1 = subprocess.run(["adb", "-s", ADB_SERIAL, "shell", "screencap", "-p", remote], capture_output=True, text=True) # 拉取 r2 = subprocess.run(["adb", "-s", ADB_SERIAL, "pull", remote, local], capture_output=True, text=True) size = os.path.getsize(local) if os.path.exists(local) else 0 print(f" [截图] {name}.png ({size} bytes)") return local if size > 0 else None print(f"[{datetime.now().strftime('%H:%M:%S')}] 连接Frida: {PHONE_IP}:{FRIDA_PORT}") dm = frida.get_device_manager() device = dm.add_remote_device(f"{PHONE_IP}:{FRIDA_PORT}") session = device.attach(WECHAT_PID) print(f"[OK] 附加微信 PID={WECHAT_PID}") with open(HOOK_SCRIPT, encoding="utf-8") as f: src = f.read() script = session.create_script(src) script.on("message", lambda m, d: None) script.load() print("[OK] Hook已加载,等待3秒...") time.sleep(3) rpc = script.exports_sync results = {} ts = datetime.now().strftime("%H%M%S") # ============================================================ # 阶段1:真实数据统计 # ============================================================ print("\n" + "="*50) print("阶段1:真实数据统计") print("="*50) r_type3 = rpc.raw_sql({"sql": "SELECT COUNT(*) as cnt FROM rcontact WHERE type=3"}) type3_count = r_type3.get("rows", [{}])[0].get("cnt", "?") r_groups = rpc.raw_sql({"sql": "SELECT COUNT(*) as cnt FROM chatroom"}) groups_count = r_groups.get("rows", [{}])[0].get("cnt", "?") r_total = rpc.raw_sql({"sql": "SELECT COUNT(*) as cnt FROM rcontact"}) total_count = r_total.get("rows", [{}])[0].get("cnt", "?") # 群组名称 r_named = rpc.raw_sql({"sql": "SELECT chatroomname, chatroomnick FROM chatroom WHERE chatroomnick IS NOT NULL AND chatroomnick != '' LIMIT 10"}) named_groups = r_named.get("rows", []) # 联系人样本 r_sample = rpc.raw_sql({"sql": "SELECT username, nickname, conRemark FROM rcontact WHERE type=3 AND username != 'filehelper' LIMIT 10"}) contact_sample = r_sample.get("rows", []) print(f" rcontact总记录: {total_count}") print(f" 真实好友(type=3): {type3_count}") print(f" 群组数量: {groups_count}") print(f" 有名称的群组: {len(named_groups)}个") for g in named_groups[:5]: print(f" {g.get('chatroomnick','')} ({g.get('chatroomname','')})") print(f" 联系人样本(前5):") for c in contact_sample[:5]: print(f" {c.get('nickname','')} ({c.get('username','')})") results["data_stats"] = { "total_rcontact": total_count, "type3_friends": type3_count, "groups_count": groups_count, "named_groups": named_groups, "contact_sample": contact_sample } # ============================================================ # 阶段2:截图验证朋友圈发送 # ============================================================ print("\n" + "="*50) print("阶段2:朋友圈发送截图验证") print("="*50) # 2a. 导航到主界面截图 print(" 2a. 导航到主界面...") rpc.navigate_to_main({}) adb_screenshot(f"moment_A_main_{ts}", wait=1.5) # 2b. 发送朋友圈 moment_content = f"[SDK验证{datetime.now().strftime('%m/%d %H:%M')}] 工作手机Frida真机验证-朋友圈功能正常 好友:{type3_count}人 群:{groups_count}个" print(f" 2b. 发送朋友圈: {moment_content[:40]}...") moment_result = rpc.post_moments({"content": moment_content, "image_urls": []}) print(f" 发送结果: {json.dumps(moment_result, ensure_ascii=False)}") results["moment_send"] = moment_result # 2c. 发送后截图 adb_screenshot(f"moment_B_after_send_{ts}", wait=2) # 2d. 读取朋友圈验证 moments = rpc.get_moments({"limit": 10}) print(f" 朋友圈读取: {moments.get('count', 0)}条") results["moments_read"] = moments # ============================================================ # 阶段3:截图验证消息发送 # ============================================================ print("\n" + "="*50) print("阶段3:消息发送截图验证") print("="*50) # 3a. 导航到文件传输助手 print(" 3a. 导航到文件传输助手...") rpc.navigate_to_chat({"wxid": "filehelper"}) adb_screenshot(f"msg_A_before_{ts}", wait=1.5) # 3b. 发送消息 msg1 = f"[SDK验证{datetime.now().strftime('%H:%M:%S')}] 真实数据: 好友{type3_count}人 | 群组{groups_count}个 | 总记录{total_count}条" print(f" 3b. 发送消息1: {msg1[:50]}...") msg_result1 = rpc.send_message({"to_id": "filehelper", "content": msg1, "msg_type": "text"}) print(f" 发送结果: {json.dumps(msg_result1, ensure_ascii=False)}") results["message_send_1"] = msg_result1 time.sleep(0.8) # 3c. 发送后截图(消息应出现在聊天界面) adb_screenshot(f"msg_B_after_send1_{ts}", wait=1) # 3d. 再发一条确认 msg2 = f"[SDK验证{datetime.now().strftime('%H:%M:%S')}] 第2条消息 - Frida真机控制正常" rpc.send_message({"to_id": "filehelper", "content": msg2, "msg_type": "text"}) results["message_send_2"] = {"content": msg2} adb_screenshot(f"msg_C_after_send2_{ts}", wait=1) # ============================================================ # 阶段4:群组详情验证 # ============================================================ print("\n" + "="*50) print("阶段4:群组详情验证") print("="*50) groups_full = rpc.get_groups_full({"limit": 100}) print(f" 群组总数: {groups_full.get('count', 0)} (来源: {groups_full.get('source', '?')})") if groups_full.get("groups"): for g in groups_full["groups"][:10]: print(f" {g.get('group_id','')} | {g.get('name','')} | 成员:{g.get('member_count','?')}") results["groups_full"] = groups_full # 获取第一个群的成员 if groups_full.get("groups"): first_group = groups_full["groups"][0] group_id = first_group.get("group_id", "") if group_id: members = rpc.get_group_members({"group_id": group_id}) print(f" 群 {group_id} 成员数: {members.get('count', 0)}") results["first_group_members"] = members # ============================================================ # 保存结果 # ============================================================ report = { "title": "工作手机SDK - 截图验证报告v2", "time": datetime.now().isoformat(), "device": PHONE_IP, "real_data": { "total_rcontact": total_count, "type3_friends": type3_count, "groups": groups_count, }, "screenshots": [ f"moment_A_main_{ts}.png", f"moment_B_after_send_{ts}.png", f"msg_A_before_{ts}.png", f"msg_B_after_send1_{ts}.png", f"msg_C_after_send2_{ts}.png", ], "results": results } with open(RESULT_FILE, "w", encoding="utf-8") as f: json.dump(report, f, ensure_ascii=False, indent=2, default=str) print(f"\n结果已保存: {RESULT_FILE}") script.unload() session.detach() print("完成!")