Files
workphone-sdk/verify_v8_fix.py

337 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""工作手机 SDK v8-fix - 全量接口验证"""
import frida, json, time, subprocess, os
PHONE_PORT = 27042
WECHAT_PID = 25425
JS_FILE = '/Users/karuo/Documents/开发/2、私域银行/工作手机/sdk/agent/hook/wechat_api_v8_fix.js'
SCREENSHOT_DIR = '/Users/karuo/Documents/开发/2、私域银行/工作手机/开发文档/6、测试/'
ADB = ['adb', '-s', '192.168.110.80:5555']
RESULT_FILE = '/Users/karuo/Documents/开发/2、私域银行/工作手机/verification_v8fix_results.json'
def screenshot(name):
remote = f'/sdcard/v8fix_{name}.png'
local = SCREENSHOT_DIR + f'v8fix_{name}.png'
subprocess.run(ADB + ['shell', f'screencap -p {remote}'], capture_output=True)
time.sleep(0.5)
subprocess.run(ADB + ['pull', remote, local], capture_output=True)
return local
def main():
print('='*65)
print('工作手机 SDK v8-fix - 全量接口验证')
print('='*65)
device = frida.get_device_manager().add_remote_device(f'127.0.0.1:{PHONE_PORT}')
session = device.attach(WECHAT_PID)
with open(JS_FILE) as f:
js = f.read()
script = session.create_script(js)
log_msgs = []
def on_msg(msg, data):
if msg['type'] == 'send':
log_msgs.append(msg['payload'])
elif msg['type'] == 'log':
print(f' [JS] {msg["payload"]}')
script.on('message', on_msg)
script.load()
time.sleep(3)
e = script.exports_sync
results = {}
passed = 0
failed = 0
def check(name, r, key=None):
nonlocal passed, failed
if r.get('error') and not r.get('success'):
print(f'{name}: {r.get("error","")[:60]}')
failed += 1
else:
passed += 1
return r
print('\n[1] Ping...')
r = e.ping()
print(f'{r}')
passed += 1
print('\n[2] 初始化所有DB...')
r = e.init_dbs()
status = r.get('status', {})
for k, v in status.items():
print(f' {"" if v else ""} {k}')
print(f' 总DB实例: {r.get("total_dbs")}')
results['db_init'] = r
print('\n[3] 列出所有DB...')
r = e.list_all_dbs()
print(f' 找到 {r.get("count")} 个DB')
for db in (r.get('dbs') or []):
print(f' {db["name"]}: {db["path"].split("/")[-1]}')
results['all_dbs'] = r
print('\n[4] 账号信息...')
r = e.get_account_info()
print(f' 微信号: {r.get("wxid")}')
print(f' 昵称: {r.get("nickname")}')
print(f' 手机: {r.get("phone")}')
print(f' 地区: {r.get("region")}')
print(f' 性别: {r.get("sex")}')
results['account'] = r
if r.get('wxid'): passed += 1
else: failed += 1
print('\n[5] 全量统计...')
r = e.get_all_stats()
print(f' ✅ 好友数: {r.get("friends")}')
print(f' ✅ 群组数: {r.get("groups")}')
print(f' ✅ 消息总数: {r.get("messages")}')
print(f' ✅ 图片总数: {r.get("images")}')
print(f' ✅ 视频总数: {r.get("videos")}')
print(f' ✅ 会话数: {r.get("conversations")}')
print(f' ✅ 文件数: {r.get("files")}')
results['stats'] = r
passed += 1
print('\n[6] 联系人数量...')
r = e.get_contact_count()
print(f' ✅ 真实好友: {r.get("friends")} | 总记录: {r.get("total")}')
results['contact_count'] = r
passed += 1
print('\n[7] 联系人列表前10个...')
r = e.get_contacts(10, 0)
for c in (r.get('rows') or [])[:10]:
print(f' {c.get("nickName","?")} | 备注:{c.get("conRemark","")} | {c.get("username","")}')
results['contacts'] = r
passed += 1
print('\n[8] 搜索联系人(搜索""...')
r = e.search_contact('')
print(f' 找到 {r.get("count")}')
for c in (r.get('rows') or [])[:5]:
print(f' {c.get("nickName","?")} ({c.get("username","?")})')
results['search'] = r
passed += 1
print('\n[9] 最近消息24小时...')
r = e.get_recent_messages(24)
print(f' 24小时消息: {r.get("count")}')
for m in (r.get('rows') or [])[:5]:
print(f' [{m.get("talker","?")}] {str(m.get("content",""))[:40]}')
results['recent_msgs'] = r
passed += 1
print('\n[10] 发送消息到文件传输助手...')
content = f'SDK v8-fix 测试消息 {time.strftime("%Y-%m-%d %H:%M:%S")}'
r = e.send_message('filehelper', content)
print(f' 发送: success={r.get("success")}, msgId={r.get("msgId")}')
print(f' DB验证: {"✅ 已写入" if r.get("db_verified") else "❌ 未写入"}')
results['send_msg'] = r
if r.get('db_verified'): passed += 1
else: failed += 1
time.sleep(1)
screenshot('after_send_msg')
print('\n[11] 会话列表前10个...')
r = e.get_conversations(10)
print(f' 会话数: {r.get("count")}')
for c in (r.get('rows') or [])[:5]:
print(f' [{c.get("username","?")}] 未读:{c.get("unReadCount",0)} | {str(c.get("lastMsg",""))[:30]}')
results['conversations'] = r
passed += 1
print('\n[12] 群组列表前10个...')
r = e.get_groups(10)
print(f' 群组数: {r.get("count")}')
for g in (r.get('rows') or [])[:5]:
print(f' {g.get("chatroomname","?")} | 成员:{g.get("memberCount",0)} | 群主:{g.get("roomowner","?")}')
results['groups'] = r
passed += 1
print('\n[13] 群成员详情第1个群...')
if r.get('rows'):
gid = r['rows'][0].get('chatroomname')
r2 = e.get_group_members(gid)
print(f' 群ID: {gid}')
print(f' 成员数: {r2.get("count")} | memberCount字段: {r2.get("memberCount")}')
print(f' 群主: {r2.get("owner")}')
print(f' 群公告: {str(r2.get("announcement",""))[:60] or ""}')
print(f' 我的群名: {r2.get("myName","")}')
print(f' 前3成员: {(r2.get("members") or [])[:3]}')
results['group_members'] = r2
passed += 1
print('\n[14] 标签统计...')
r = e.get_labels()
print(f' 标签数: {r.get("count")}')
top = sorted((r.get('usage') or {}).items(), key=lambda x: -int(x[1]))[:10]
print(f' 使用最多的标签: {top}')
results['labels'] = r
passed += 1
print('\n[15] 朋友圈DB信息...')
r = e.get_sns_db_info()
for k, v in r.items():
print(f' {k}: available={v.get("available")}, tables={v.get("tables",[])}')
results['sns_info'] = r
print('\n[16] 朋友圈内容前5条...')
r = e.get_moments(5)
print(f' 朋友圈条数: {r.get("count")} | DB: {r.get("db","?")}')
for m in (r.get('rows') or [])[:5]:
print(f' [{m.get("userName","?")}] {str(m.get("content",""))[:60]}')
results['moments'] = r
if not r.get('error'): passed += 1
else: failed += 1
print('\n[17] 发布朋友圈...')
moment_text = f'SDK v8-fix 后端发布 {time.strftime("%H:%M:%S")} #测试'
r = e.post_moment(moment_text)
print(f' 发布: success={r.get("success")}, snsId={r.get("snsId")}, db={r.get("db")}')
print(f' DB验证: {"✅ 已写入" if r.get("db_verified") else "❌ 未写入"} | error={r.get("error","")}')
results['post_moment'] = r
if r.get('db_verified'): passed += 1
else: failed += 1
time.sleep(1)
screenshot('after_post_moment')
print('\n[18] 视频号信息...')
r = e.get_finder_info()
for k, v in r.items():
print(f' {k}: available={v.get("available")}, tables={v.get("tables",[])}')
results['finder_info'] = r
print('\n[19] 视频号联系人...')
r = e.get_finder_contacts(10)
print(f' 视频号联系人: {r.get("count",0)}')
for c in (r.get('rows') or [])[:3]:
print(f' {str(c)[:60]}')
results['finder_contacts'] = r
if not r.get('error'): passed += 1
else: failed += 1
print('\n[20] 视频号媒体缓存...')
r = e.get_finder_media(5)
print(f' 视频号媒体: {r.get("count",0)}')
results['finder_media'] = r
if not r.get('error'): passed += 1
else: failed += 1
print('\n[21] 视频号账号...')
r = e.get_finder_accounts()
print(f' 视频号账号表: {r.get("tables",[])}')
for k, v in r.items():
if k != 'tables' and isinstance(v, dict) and v.get('rows'):
print(f' {k}: {v["count"]}')
results['finder_accounts'] = r
print('\n[22] 收藏...')
r = e.get_favorites(10)
print(f' 收藏: {r.get("count",0)} 条 | error={r.get("error","")}')
for fav in (r.get('rows') or [])[:3]:
print(f' {str(fav)[:60]}')
results['favorites'] = r
if not r.get('error'): passed += 1
else: failed += 1
print('\n[23] 钱包信息...')
r = e.get_wallet_info()
print(f' 钱包表: {r.get("tables",[])}')
results['wallet_info'] = r
if not r.get('error'): passed += 1
else: failed += 1
print('\n[24] 钱包账单前5条...')
r = e.get_wallet_ledger(5)
print(f' 账单: {r.get("count",0)}')
for ledger in (r.get('rows') or [])[:5]:
print(f' 用户:{ledger.get("tradeUser","?")} 金额:{ledger.get("tradeAmount","?")} 类型:{ledger.get("tradeType","?")} 日期:{ledger.get("msgDate","?")}')
results['wallet_ledger'] = r
if not r.get('error'): passed += 1
else: failed += 1
print('\n[25] 钱包用户信息...')
r = e.get_wallet_user_info()
print(f' 钱包表: {r.get("tables",[])}')
for k, v in r.items():
if k != 'tables' and isinstance(v, dict) and v.get('rows'):
print(f' {k}: {v["rows"][:1]}')
results['wallet_user'] = r
print('\n[26] 红包记录...')
r = e.get_lucky_money(5)
print(f' 红包: {r.get("count",0)}')
for lm in (r.get('rows') or [])[:3]:
print(f' {str(lm)[:60]}')
results['lucky_money'] = r
passed += 1
print('\n[27] 图片统计...')
r = e.get_image_count()
total = r.get('rows',[{}])[0].get('total',0) if r.get('rows') else 0
print(f' ✅ 图片总数: {total}')
results['image_count'] = r
passed += 1
print('\n[28] 视频统计...')
r = e.get_video_count()
total = r.get('rows',[{}])[0].get('total',0) if r.get('rows') else 0
print(f' ✅ 视频总数: {total}')
results['video_count'] = r
passed += 1
print('\n[29] 文件列表...')
r = e.get_file_list(5)
print(f' 文件: {r.get("count",0)}')
results['files'] = r
passed += 1
print('\n[30] 小程序列表...')
r = e.get_app_brand_list()
print(f' 小程序表: {r.get("tables",[])}')
for k, v in r.items():
if k != 'tables' and isinstance(v, dict) and v.get('count',0) > 0:
print(f' {k}: {v["count"]}')
results['appbrand'] = r
if not r.get('error'): passed += 1
else: failed += 1
print('\n[31] 群发消息(发给文件传输助手)...')
r = e.mass_message(['filehelper'], f'群发测试 {time.strftime("%H:%M:%S")}')
print(f' 群发: 总数={r.get("total")}, 成功={r.get("success_count")}')
results['mass_msg'] = r
if r.get('success_count',0) > 0: passed += 1
else: failed += 1
print('\n[32] 全局搜索(搜索""...')
r = e.global_search('')
print(f' 联系人: {r.get("contacts",{}).get("count",0)}')
print(f' 消息: {r.get("messages",{}).get("count",0)}')
results['global_search'] = r
passed += 1
print('\n[33] 原始SQL查询...')
r = e.raw_query('main', 'SELECT COUNT(*) as n FROM rcontact WHERE type=3')
print(f' 好友数原始SQL: {r.get("rows",[{}])[0].get("n","?")}')
results['raw_query'] = r
passed += 1
# 最终截图
screenshot('final')
# 保存结果
with open(RESULT_FILE, 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=2, default=str)
print('\n' + '='*65)
total = passed + failed
print(f'✅ 验证完成!通过: {passed}/{total} ({int(passed/total*100)}%)')
print(f'结果保存: {RESULT_FILE}')
print('='*65)
if __name__ == '__main__':
main()