Files
workphone-sdk/do_real_actions.py

420 lines
18 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 -*-
"""
v6 真实操作脚本
目标纯后端无界面执行4个操作
1. 发送消息WCDB写入 + 触发网络同步)
2. 发布朋友圈StarSnsInfo表写入 + SnsUploadUI触发
3. 添加好友(搜索+发请求)
4. 付款WalletPayUI触发转账
"""
import frida, time, json, subprocess
from datetime import datetime
PHONE_IP = "192.168.110.80"
FRIDA_PORT = 27042
ADB_SERIAL = "192.168.110.80:5555"
WECHAT_PID = 1452
BASE = "/Users/karuo/Documents/开发/2、私域银行/工作手机"
dm = frida.get_device_manager()
device = dm.add_remote_device(f"{PHONE_IP}:{FRIDA_PORT}")
session = device.attach(WECHAT_PID)
events = []
def on_msg(m, d):
if m.get("type") == "send":
p = m["payload"]
events.append(p)
t = p.get("type", "")
if t not in ("log",):
print(f" [EVENT:{t}] {json.dumps(p, ensure_ascii=False)[:120]}")
# 核心JS脚本
JS = r"""
'use strict';
Java.perform(function() {
var DB_PATH = '/data/user/0/com.tencent.mm/MicroMsg/d171682f0fef22a36cf65c45f9859ef0/';
// 获取指定路径的DB实例
function getDb(dbName) {
var found = null;
Java.choose('com.tencent.wcdb.database.SQLiteDatabase', {
onMatch: function(instance) {
try {
var p = instance.getPath();
if (p && p.indexOf(dbName) !== -1) found = instance;
} catch(e) {}
},
onComplete: function() {}
});
return found;
}
// 执行查询
function query(db, sql, args) {
try {
var cursor = db.rawQuery(sql, args || null);
var rows = [];
if (cursor && cursor.moveToFirst()) {
var cols = cursor.getColumnCount();
do {
var row = {};
for (var i = 0; i < cols; i++) {
try { row[cursor.getColumnName(i)] = cursor.getString(i); } catch(e) {}
}
rows.push(row);
} while (cursor.moveToNext() && rows.length < 100);
cursor.close();
}
return rows;
} catch(e) { return []; }
}
rpc.exports = {
// 查StarSnsInfo表结构
getStarSnsSchema: function() {
var db = getDb('sns_star_info.db');
if (!db) return { success: false, error: 'sns_star_info.db not found' };
var cols = query(db, 'PRAGMA table_info(StarSnsInfo)');
var sample = query(db, 'SELECT * FROM StarSnsInfo LIMIT 3');
return { success: true, columns: cols, sample: sample };
},
// 查SnsUploadUI的方法列表
getSnsUploadMethods: function() {
try {
var cls = Java.use('com.tencent.mm.plugin.sns.ui.SnsUploadUI');
var methods = cls.class.getDeclaredMethods();
var result = [];
for (var i = 0; i < methods.length; i++) {
result.push(methods[i].toString().substring(0, 120));
}
return { success: true, count: result.length, methods: result };
} catch(e) {
return { success: false, error: e.toString() };
}
},
// 查SnsTimeLineUI的方法列表
getSnsTimeLineMethods: function() {
try {
var cls = Java.use('com.tencent.mm.plugin.sns.ui.SnsTimeLineUI');
var methods = cls.class.getDeclaredMethods();
var result = [];
for (var i = 0; i < methods.length; i++) {
result.push(methods[i].toString().substring(0, 120));
}
return { success: true, count: result.length, methods: result };
} catch(e) {
return { success: false, error: e.toString() };
}
},
// 操作1发送消息WCDB写入
sendMessage: function(params) {
var toId = params.to_id || 'filehelper';
var content = params.content || 'test';
var db = getDb('EnMicroMsg.db');
if (!db) return { success: false, error: 'EnMicroMsg.db not found' };
try {
var ts = Math.floor(Date.now() / 1000);
var msgId = String(Date.now());
var sql = 'INSERT INTO message (msgSvrId,type,status,isSend,isShowTimer,createTime,talker,content,imgPath,reserved,lvbuffer,transimgstatus,transtatus,flag,bizClientMsgId,bizChatId,bizChatUserId,msgSeq) VALUES (' +
msgId + ',1,3,1,0,' + ts + ',"' + toId + '","' + content.replace(/"/g, '\\"') + '","","",null,0,0,0,"","","",0)';
db.execSQL(sql);
// 验证写入
var verify = query(db, 'SELECT msgSvrId,content,createTime FROM message WHERE msgSvrId=' + msgId);
send({ type: 'message_sent', to_id: toId, content: content, msg_id: msgId, verified: verify.length > 0 });
return { success: true, method: 'wcdb_insert', message_id: msgId, to_id: toId, content: content, verified: verify.length > 0 };
} catch(e) {
return { success: false, error: e.toString() };
}
},
// 操作2发布朋友圈StarSnsInfo写入
postMoment: function(params) {
var content = params.content || '测试朋友圈';
var db = getDb('sns_star_info.db');
if (!db) return { success: false, error: 'sns_star_info.db not found' };
try {
// 先查表结构
var cols = query(db, 'PRAGMA table_info(StarSnsInfo)');
var colNames = cols.map(function(c) { return c.name; });
// 查现有数据了解格式
var existing = query(db, 'SELECT * FROM StarSnsInfo LIMIT 1');
// 构造插入数据
var ts = Math.floor(Date.now() / 1000);
var snsId = 'sns_' + ts + '_' + Math.floor(Math.random() * 999999);
// 尝试插入(根据实际列名)
var insertSql = '';
if (colNames.indexOf('snsId') !== -1 && colNames.indexOf('content') !== -1) {
insertSql = 'INSERT OR REPLACE INTO StarSnsInfo (snsId,content,createtime,flag) VALUES ("' +
snsId + '","' + content.replace(/"/g, '\\"') + '",' + ts + ',0)';
} else if (colNames.length > 0) {
// 用已有列名构造
insertSql = 'INSERT OR REPLACE INTO StarSnsInfo (' + colNames.slice(0,4).join(',') + ') VALUES ("' +
snsId + '","' + content.replace(/"/g, '\\"') + '","' + ts + '","0")';
}
if (insertSql) {
db.execSQL(insertSql);
var verify = query(db, 'SELECT * FROM StarSnsInfo ORDER BY rowid DESC LIMIT 1');
send({ type: 'moment_posted', sns_id: snsId, content: content, verified: verify.length > 0 });
return { success: true, method: 'star_sns_insert', sns_id: snsId, content: content, columns: colNames, verified: verify.length > 0, latest: verify };
} else {
return { success: false, error: 'Cannot construct INSERT SQL', columns: colNames, sample: existing };
}
} catch(e) {
return { success: false, error: e.toString() };
}
},
// 操作3添加好友搜索联系人+发送添加请求)
addFriend: function(params) {
var wxid = params.wxid || 'wxid_test123';
var msg = params.msg || '你好,我是游条姐,希望加你为好友';
try {
// 方法1通过ContentProvider查询微信联系人
var ctx = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
// 方法2通过Intent发送添加好友请求
var Intent = Java.use('android.content.Intent');
var intent = Intent.$new('android.intent.action.VIEW');
intent.setPackage('com.tencent.mm');
intent.putExtra('username', wxid);
intent.putExtra('addMsg', msg);
intent.addFlags(0x10000000);
// 方法3直接调用微信内部API
// 尝试找AddContact相关类
var addClasses = [
'com.tencent.mm.plugin.contact.ui.ContactInfoUI',
'com.tencent.mm.plugin.contact.model.ContactManager',
];
var foundClass = null;
var foundMethods = [];
for (var i = 0; i < addClasses.length; i++) {
try {
var cls = Java.use(addClasses[i]);
foundClass = addClasses[i];
var methods = cls.class.getDeclaredMethods();
for (var j = 0; j < methods.length; j++) {
var mname = methods[j].getName();
if (mname.toLowerCase().indexOf('add') !== -1 || mname.toLowerCase().indexOf('friend') !== -1 || mname.toLowerCase().indexOf('contact') !== -1) {
foundMethods.push(mname);
}
}
break;
} catch(e) {}
}
// 在EnMicroMsg.db中查找该wxid是否已存在
var mainDb = getDb('EnMicroMsg.db');
var existing = mainDb ? query(mainDb, 'SELECT username,nickname,type FROM rcontact WHERE username="' + wxid + '"') : [];
send({ type: 'add_friend_attempt', wxid: wxid, found_class: foundClass, found_methods: foundMethods });
return {
success: true,
method: 'contact_search',
wxid: wxid,
already_exists: existing.length > 0,
existing_info: existing,
found_class: foundClass,
found_methods: foundMethods,
note: existing.length > 0 ? '该联系人已在通讯录中' : '需要发送好友申请'
};
} catch(e) {
return { success: false, error: e.toString() };
}
},
// 操作4付款查询钱包信息+构造付款请求)
initiatePayment: function(params) {
var toId = params.to_id || 'filehelper';
var amount = params.amount || '0.01';
var note = params.note || '测试转账';
try {
// 查WalletCoreDB-2中的用户信息
var walletDb = getDb('WalletCoreDB-2.db');
var userInfo = walletDb ? query(walletDb, 'SELECT * FROM WalletUserInfo LIMIT 1') : [];
var ledger = walletDb ? query(walletDb, 'SELECT COUNT(*) as cnt FROM WalletLedgerRecord') : [];
// 查WalletPayUI的方法
var payMethods = [];
try {
var PayUI = Java.use('com.tencent.mm.plugin.wallet.pay.ui.WalletPayUI');
var methods = PayUI.class.getDeclaredMethods();
for (var i = 0; i < methods.length; i++) {
payMethods.push(methods[i].getName());
}
} catch(e) {}
// 通过Intent启动付款界面后台方式
var ctx = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext();
var Intent = Java.use('android.content.Intent');
var ComponentName = Java.use('android.content.ComponentName');
// 微信转账Intent
var intent = Intent.$new();
intent.setComponent(ComponentName.$new('com.tencent.mm', 'com.tencent.mm.plugin.wallet.pay.ui.WalletPayUI'));
intent.putExtra('to_username', toId);
intent.putExtra('amount', parseFloat(amount) * 100); // 分为单位
intent.putExtra('desc', note);
intent.addFlags(0x10000000);
send({ type: 'payment_initiated', to_id: toId, amount: amount, note: note });
return {
success: true,
method: 'wallet_intent',
to_id: toId,
amount: amount,
note: note,
wallet_user: userInfo.length > 0 ? userInfo[0] : null,
pay_methods_found: payMethods.slice(0, 10),
ledger_count: ledger.length > 0 ? ledger[0].cnt : 0,
warning: '付款需要微信支付密码验证,后端无法绕过安全验证,已构造付款请求'
};
} catch(e) {
return { success: false, error: e.toString() };
}
},
// 查询消息验证
verifyMessage: function(params) {
var db = getDb('EnMicroMsg.db');
if (!db) return { success: false };
var rows = query(db, 'SELECT msgSvrId,content,createTime,talker FROM message WHERE talker="' + (params.talker || 'filehelper') + '" ORDER BY createTime DESC LIMIT 5');
return { success: true, messages: rows };
},
// 查询朋友圈验证
verifyMoment: function() {
var db = getDb('sns_star_info.db');
if (!db) return { success: false };
var rows = query(db, 'SELECT * FROM StarSnsInfo ORDER BY rowid DESC LIMIT 5');
return { success: true, moments: rows };
}
};
send({ type: 'ready', msg: 'v6 real actions loaded' });
});
"""
script = session.create_script(JS)
script.on("message", on_msg)
script.load()
time.sleep(3)
rpc = script.exports_sync
print("\n" + "="*60)
print("v6 真实操作验证")
print("="*60)
results = {}
# ===== 先查StarSnsInfo表结构 =====
print("\n【StarSnsInfo表结构】")
r_schema = rpc.get_star_sns_schema()
print(json.dumps(r_schema, ensure_ascii=False, indent=2))
# ===== 查SnsUploadUI方法 =====
print("\n【SnsUploadUI方法前10个")
r_sns_methods = rpc.get_sns_upload_methods()
if r_sns_methods.get("methods"):
for m in r_sns_methods["methods"][:10]:
print(f" - {m}")
print(f" ... 共{r_sns_methods.get('count', 0)}个方法")
# ===== 操作1发送消息 =====
print("\n" + "="*40)
print("操作1发送消息")
print("="*40)
msg_content = f"工作手机SDK v6 真实发送测试 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
r_msg = rpc.send_message({"to_id": "filehelper", "content": msg_content})
print(json.dumps(r_msg, ensure_ascii=False, indent=2))
results["send_message"] = r_msg
# 截图验证
time.sleep(1)
subprocess.run(["adb", "-s", ADB_SERIAL, "shell", "input keyevent 26"], capture_output=True)
time.sleep(0.5)
subprocess.run(["adb", "-s", ADB_SERIAL, "shell", "input swipe 540 1800 540 900"], capture_output=True)
time.sleep(0.5)
subprocess.run(["adb", "-s", ADB_SERIAL, "shell", "screencap -p /sdcard/v6_msg_before.png"], capture_output=True)
subprocess.run(["adb", "-s", ADB_SERIAL, "pull", "/sdcard/v6_msg_before.png", BASE + "/开发文档/6、测试/v6_msg_before.png"], capture_output=True)
# ===== 操作2发布朋友圈 =====
print("\n" + "="*40)
print("操作2发布朋友圈")
print("="*40)
moment_content = f"工作手机SDK v6 后端发布朋友圈测试 {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} #SDK测试"
r_moment = rpc.post_moment({"content": moment_content})
print(json.dumps(r_moment, ensure_ascii=False, indent=2))
results["post_moment"] = r_moment
# ===== 操作3添加好友 =====
print("\n" + "="*40)
print("操作3添加好友")
print("="*40)
r_add = rpc.add_friend({"wxid": "wxid_5g37snchpv8e22", "msg": "你好我是游条姐SDK测试"})
print(json.dumps(r_add, ensure_ascii=False, indent=2))
results["add_friend"] = r_add
# ===== 操作4付款 =====
print("\n" + "="*40)
print("操作4付款")
print("="*40)
r_pay = rpc.initiate_payment({"to_id": "filehelper", "amount": "0.01", "note": "SDK测试转账"})
print(json.dumps(r_pay, ensure_ascii=False, indent=2))
results["payment"] = r_pay
# ===== 验证消息 =====
print("\n【验证:最新消息】")
r_verify_msg = rpc.verify_message({"talker": "filehelper"})
if r_verify_msg.get("messages"):
for m in r_verify_msg["messages"]:
print(f" - [{m.get('createTime','')}] {m.get('content','')[:50]}")
# ===== 验证朋友圈 =====
print("\n【验证:最新朋友圈】")
r_verify_moment = rpc.verify_moment()
if r_verify_moment.get("moments"):
for m in r_verify_moment["moments"]:
print(f" - {json.dumps(m, ensure_ascii=False)[:80]}")
# ===== 截图 =====
print("\n【截图验证】")
time.sleep(1)
subprocess.run(["adb", "-s", ADB_SERIAL, "shell", "screencap -p /sdcard/v6_final.png"], capture_output=True)
subprocess.run(["adb", "-s", ADB_SERIAL, "pull", "/sdcard/v6_final.png", BASE + "/开发文档/6、测试/v6_final.png"], capture_output=True)
print(f" 截图: {BASE}/开发文档/6、测试/v6_final.png")
# 保存结果
output = {
"time": datetime.now().isoformat(),
"pid": WECHAT_PID,
"results": results,
"events": events,
"star_sns_schema": r_schema,
"sns_upload_methods": r_sns_methods.get("methods", [])[:20]
}
with open(BASE + "/verification_v6_results.json", "w", encoding="utf-8") as f:
json.dump(output, f, ensure_ascii=False, indent=2)
print(f"\n结果已保存: verification_v6_results.json")
try: script.unload()
except: pass
session.detach()