Files
workphone-sdk/test_frida_debug_data.py

163 lines
6.4 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
# -*- coding: utf-8 -*-
"""
工作手机SDK - 深度数据调试脚本
目标:查明联系人/群组真实数量验证SQL过滤条件
"""
import frida, time, json, os
from datetime import datetime
PHONE_IP = "192.168.110.80"
FRIDA_PORT = 27042
WECHAT_PID = 16816
BASE = "/Users/karuo/Documents/开发/2、私域银行/工作手机"
RESULT_FILE = BASE + "/debug_data_20260518.json"
# 内联调试脚本 - 直接执行原始SQL
DEBUG_SCRIPT = """
'use strict';
// 复用 _execSQL 逻辑
function findDbPath() {
var paths = [
'/data/data/com.tencent.mm/MicroMsg/',
];
var dbPath = null;
try {
var File = Java.use('java.io.File');
var base = File.$new('/data/data/com.tencent.mm/MicroMsg/');
var dirs = base.listFiles();
if (dirs) {
for (var i = 0; i < dirs.length; i++) {
var d = dirs[i];
if (d.isDirectory() && d.getName().length === 32) {
var candidate = d.getAbsolutePath() + '/EnMicroMsg.db';
if (File.$new(candidate).exists()) {
dbPath = candidate;
break;
}
}
}
}
} catch(e) {}
return dbPath;
}
function execSQL(sql, dbPath) {
try {
var SQLiteDatabase = Java.use('net.sqlcipher.database.SQLiteDatabase');
var db = SQLiteDatabase.openDatabase(dbPath, '00000000000000000000000000000000', null, 0);
var cursor = db.rawQuery(sql, null);
var rows = [];
var colCount = cursor.getColumnCount();
var colNames = [];
for (var i = 0; i < colCount; i++) colNames.push(cursor.getColumnName(i));
while (cursor.moveToNext()) {
var row = {};
for (var j = 0; j < colCount; j++) {
try { row[colNames[j]] = cursor.getString(j); } catch(_) { row[colNames[j]] = null; }
}
rows.push(row);
}
cursor.close();
db.close();
return rows;
} catch(e) {
return [{error: String(e)}];
}
}
rpc.exports = {
debugContacts: function() {
return Java.performNow(function() {
var dbPath = findDbPath();
if (!dbPath) return {error: 'DB not found'};
var results = {};
// 1. 总联系人数(无过滤)
var r1 = execSQL("SELECT COUNT(*) as cnt FROM rcontact", dbPath);
results.total_rcontact = r1[0] ? r1[0].cnt : 'err';
// 2. type分布
var r2 = execSQL("SELECT type, COUNT(*) as cnt FROM rcontact GROUP BY type ORDER BY cnt DESC LIMIT 20", dbPath);
results.type_distribution = r2;
// 3. verifyFlag分布
var r3 = execSQL("SELECT verifyFlag, COUNT(*) as cnt FROM rcontact GROUP BY verifyFlag ORDER BY cnt DESC", dbPath);
results.verifyflag_distribution = r3;
// 4. 真实好友type=3是好友
var r4 = execSQL("SELECT COUNT(*) as cnt FROM rcontact WHERE type=3", dbPath);
results.type3_friends = r4[0] ? r4[0].cnt : 'err';
// 5. 放宽条件的好友
var r5 = execSQL("SELECT COUNT(*) as cnt FROM rcontact WHERE type NOT IN (0,33) AND username NOT LIKE '%@chatroom' AND username NOT LIKE 'gh_%'", dbPath);
results.relaxed_friends = r5[0] ? r5[0].cnt : 'err';
// 6. 完全无过滤的好友(排除系统账号)
var r6 = execSQL("SELECT COUNT(*) as cnt FROM rcontact WHERE username NOT LIKE '%@chatroom' AND username NOT LIKE 'gh_%' AND username NOT IN ('filehelper','fmessage','medianote','weibo','qqfriend','qmessage','tmessage','newsapp','brandsessionholder','notification_messages','officialaccounts','revokemsg','gh_792c1a7a1923','voipnotify','voipmessage','systemnotice','weapp','weixinofficialaccounts')", dbPath);
results.no_filter_friends = r6[0] ? r6[0].cnt : 'err';
// 7. 群组数量 - rcontact表
var r7 = execSQL("SELECT COUNT(*) as cnt FROM rcontact WHERE username LIKE '%@chatroom'", dbPath);
results.groups_in_rcontact = r7[0] ? r7[0].cnt : 'err';
// 8. 群组数量 - chatroom表
try {
var r8 = execSQL("SELECT COUNT(*) as cnt FROM chatroom", dbPath);
results.groups_in_chatroom = r8[0] ? r8[0].cnt : 'err';
} catch(e) {
results.groups_in_chatroom = 'table_not_found: ' + String(e);
}
// 9. 前20个联系人type=3
var r9 = execSQL("SELECT username, nickname, conRemark, type, verifyFlag FROM rcontact WHERE type=3 LIMIT 20", dbPath);
results.sample_type3 = r9;
// 10. 前5个群组
var r10 = execSQL("SELECT username, nickname FROM rcontact WHERE username LIKE '%@chatroom' LIMIT 10", dbPath);
results.sample_groups = r10;
// 11. 检查chatroom表结构
try {
var r11 = execSQL("SELECT chatroomname, chatroomnick FROM chatroom LIMIT 10", dbPath);
results.chatroom_sample = r11;
} catch(e) {
results.chatroom_sample = 'error: ' + String(e);
}
// 12. 所有type值的样本
var r12 = execSQL("SELECT username, nickname, type, verifyFlag FROM rcontact WHERE type NOT IN (0,33) LIMIT 5", dbPath);
results.sample_non_system = r12;
return {success: true, dbPath: dbPath, results: results};
});
}
};
"""
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}")
script = session.create_script(DEBUG_SCRIPT)
script.on("message", lambda m, d: print(f"[MSG] {m}"))
script.load()
print("[OK] 调试脚本已加载等待2秒...")
time.sleep(2)
rpc = script.exports_sync
print("\n=== 深度数据调试 ===")
result = rpc.debug_contacts()
print(json.dumps(result, ensure_ascii=False, indent=2, default=str))
with open(RESULT_FILE, "w", encoding="utf-8") as f:
json.dump(result, f, ensure_ascii=False, indent=2, default=str)
print(f"\n已保存: {RESULT_FILE}")
script.unload()
session.detach()