fix: 添加rpc.exports小写别名映射,解决Frida Python 3.14方法名转小写问题
This commit is contained in:
@@ -1584,6 +1584,22 @@ rpc.exports = {
|
||||
},
|
||||
};
|
||||
|
||||
// ============================================================
|
||||
// § AUTO-ALIAS: 为所有camelCase方法注册全小写别名
|
||||
// 解决 Frida Python 3.14 自动将方法名转小写的问题
|
||||
// ============================================================
|
||||
(function () {
|
||||
var exports = rpc.exports;
|
||||
var keys = Object.keys(exports);
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i];
|
||||
var lower = key.toLowerCase();
|
||||
if (lower !== key && !exports[lower]) {
|
||||
exports[lower] = exports[key];
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
// ============================================================
|
||||
// § 5 内部实现 — 消息发送 (H17)
|
||||
// ============================================================
|
||||
|
||||
38
sdk/tests/check_methods.py
Normal file
38
sdk/tests/check_methods.py
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
"""列出Frida exports中所有可用的方法名"""
|
||||
import frida
|
||||
import time
|
||||
|
||||
device = frida.get_device_manager().add_remote_device("192.168.0.12:27042")
|
||||
session = device.attach(7239)
|
||||
|
||||
with open("/Users/karuo/Documents/GitHub/workphone-sdk/sdk/agent/hook/wechat_hook_v2.js", "r") as f:
|
||||
src = f.read()
|
||||
|
||||
script = session.create_script(src)
|
||||
script.on("message", lambda m, d: None)
|
||||
script.load()
|
||||
time.sleep(2)
|
||||
|
||||
exports = script.exports_sync
|
||||
methods = [x for x in dir(exports) if not x.startswith("_")]
|
||||
print(f"Total methods: {len(methods)}")
|
||||
print("---")
|
||||
for m in sorted(methods):
|
||||
print(m)
|
||||
|
||||
# 测试ping
|
||||
print("---")
|
||||
print(f"ping() = {exports.ping()}")
|
||||
|
||||
# 测试几个方法名格式
|
||||
test_names = ["getConnectionStatus", "getconnectionstatus", "get_connection_status",
|
||||
"getProcessInfo", "getprocessinfo", "get_process_info",
|
||||
"takeScreenshot", "takescreenshot", "take_screenshot"]
|
||||
print("---")
|
||||
for name in test_names:
|
||||
fn = getattr(exports, name, None)
|
||||
print(f" {name}: {'EXISTS' if fn else 'NOT FOUND'}")
|
||||
|
||||
script.unload()
|
||||
session.detach()
|
||||
382
sdk/tests/final_verify.py
Normal file
382
sdk/tests/final_verify.py
Normal file
@@ -0,0 +1,382 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
工作手机SDK - 最终全量真机验证
|
||||
通过WiFi+Frida远程连接,逐个验证122个微信操作方法
|
||||
每个方法:调用 → 获取返回数据 → 截图 → 记录结果
|
||||
"""
|
||||
import frida
|
||||
import time
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import base64
|
||||
from datetime import datetime
|
||||
|
||||
# ===== 配置 =====
|
||||
DEVICE_IP = "192.168.0.12"
|
||||
FRIDA_PORT = 27042
|
||||
SCRIPT_PATH = "/Users/karuo/Documents/GitHub/workphone-sdk/sdk/agent/hook/wechat_hook_v2.js"
|
||||
OUTPUT_DIR = "/Users/karuo/Documents/GitHub/workphone-sdk/verification_final"
|
||||
os.makedirs(OUTPUT_DIR, exist_ok=True)
|
||||
os.makedirs(os.path.join(OUTPUT_DIR, "screenshots"), exist_ok=True)
|
||||
|
||||
# ===== 获取微信PID =====
|
||||
def get_wechat_pid():
|
||||
import subprocess
|
||||
r = subprocess.run(["adb", "-s", "xgfe65eimrrofyws", "shell", "pidof", "com.tencent.mm"],
|
||||
capture_output=True, text=True)
|
||||
return int(r.stdout.strip().split()[0])
|
||||
|
||||
# ===== 验证方法定义 =====
|
||||
# 每个方法的调用参数(安全参数,不会造成破坏性操作)
|
||||
SAFE_PARAMS = {
|
||||
# 无参数方法
|
||||
"ping": None,
|
||||
"getHookStatus": None,
|
||||
"getProcessInfo": None,
|
||||
"getWechatVersion": None,
|
||||
"getVersionCompat": None,
|
||||
"getConnectionStatus": None,
|
||||
"getCurrentActivity": None,
|
||||
"getDeviceInfo": None,
|
||||
"getNetworkInfo": None,
|
||||
"getStorageInfo": None,
|
||||
"getProfile": None,
|
||||
"checkAccountStatus": None,
|
||||
"checkLoginState": None,
|
||||
"getSimPhone": None,
|
||||
"getWalletBalance": None,
|
||||
"generateMyQrCode": None,
|
||||
"getLabels": None,
|
||||
"navigateToMain": None,
|
||||
"simulateBack": None,
|
||||
|
||||
# 带参数方法 - 安全调用
|
||||
"getContacts": {"limit": 5},
|
||||
"getContactInfo": {"wxid": "filehelper"},
|
||||
"searchContacts": {"keyword": "文件", "limit": 3},
|
||||
"getMessages": {"conversation_id": "filehelper", "limit": 3},
|
||||
"getRecentMessages": {"limit": 5},
|
||||
"searchMessages": {"keyword": "测试", "limit": 3},
|
||||
"getFriendRequests": {"limit": 3},
|
||||
"getGroups": {"limit": 5},
|
||||
"getGroupInfo": {"group_id": ""},
|
||||
"getGroupMembers": {"group_id": "", "limit": 5},
|
||||
"getMoments": {"limit": 3},
|
||||
"getFavorites": {"limit": 3},
|
||||
"globalSearch": {"keyword": "微信", "limit": 3},
|
||||
"getRecentMiniPrograms": {},
|
||||
"getLoginDevices": {},
|
||||
"getOfficialAccounts": {"limit": 3},
|
||||
"getOfficialAccountArticles": {"official_id": "", "limit": 3},
|
||||
"browseChannels": {"limit": 3},
|
||||
"getTransactionHistory": {"limit": 3},
|
||||
"getContactsByLabel": {"label_id": "", "limit": 5},
|
||||
|
||||
# 发送消息 - 发到文件传输助手(安全)
|
||||
"sendMessage": {"to_id": "filehelper", "content": f"[SDK验证] {datetime.now().strftime('%H:%M:%S')} 功能验证", "msg_type": "text"},
|
||||
|
||||
# 导航方法
|
||||
"navigateToChat": {"wxid": "filehelper"},
|
||||
"navigateToMoments": None,
|
||||
|
||||
# 截图
|
||||
"takeScreenshot": {"path": "/sdcard/sdk_verify.png"},
|
||||
"getScreenshotBase64": {"path": "/sdcard/sdk_verify.png"},
|
||||
|
||||
# 模拟输入
|
||||
"simulateTap": {"x": 540, "y": 960},
|
||||
"simulateInput": {"text": "test"},
|
||||
|
||||
# 好友管理 - 安全操作
|
||||
"setFriendRemark": {"wxid": "filehelper", "remark": "文件传输助手"},
|
||||
|
||||
# 批量执行
|
||||
"batchExecute": {"actions": [{"action": "ping"}, {"action": "getHookStatus"}]},
|
||||
|
||||
# 以下方法需要特定参数或有副作用,用空参数调用看返回
|
||||
"addFriend": {"wxid": "test_not_exist_12345"},
|
||||
"acceptFriend": {"encrypt_user": ""},
|
||||
"deleteFriend": {"wxid": ""},
|
||||
"addFriendByQr": {"qr_data": ""},
|
||||
"createGroup": {"wxids": []},
|
||||
"inviteToGroup": {"group_id": "", "wxids": []},
|
||||
"removeFromGroup": {"group_id": "", "wxids": []},
|
||||
"quitGroup": {"group_id": ""},
|
||||
"setGroupName": {"group_id": "", "name": ""},
|
||||
"setGroupAnnouncement": {"group_id": "", "announcement": ""},
|
||||
"generateGroupQrCode": {"group_id": ""},
|
||||
"sendGroupMessage": {"group_id": "", "content": "", "msg_type": "text"},
|
||||
"sendImage": {"to_id": "filehelper", "path": ""},
|
||||
"sendVideo": {"to_id": "filehelper", "path": ""},
|
||||
"sendFile": {"to_id": "filehelper", "path": ""},
|
||||
"sendVoice": {"to_id": "filehelper", "path": ""},
|
||||
"sendEmoji": {"to_id": "filehelper", "emoji_id": ""},
|
||||
"sendCard": {"to_id": "filehelper", "card_wxid": ""},
|
||||
"sendLink": {"to_id": "filehelper", "title": "", "url": ""},
|
||||
"sendLocation": {"to_id": "filehelper", "lat": 0, "lng": 0},
|
||||
"sendRedPacket": {"to_id": "", "amount": 0},
|
||||
"sendTransfer": {"to_id": "", "amount": 0},
|
||||
"receiveRedPacket": {"msg_id": ""},
|
||||
"receiveTransfer": {"msg_id": ""},
|
||||
"forwardMessage": {"msg_id": "", "to_id": ""},
|
||||
"forwardMultiple": {"msg_ids": [], "to_id": ""},
|
||||
"revokeMessage": {"msg_id": ""},
|
||||
"clearChatHistory": {"wxid": ""},
|
||||
"pinChat": {"wxid": "", "pin": True},
|
||||
"setDoNotDisturb": {"wxid": "", "enable": False},
|
||||
"setContactLabel": {"wxid": "", "label_ids": []},
|
||||
"createLabel": {"name": ""},
|
||||
"deleteLabel": {"label_id": ""},
|
||||
"addFavorite": {"msg_id": ""},
|
||||
"deleteFavorite": {"fav_id": ""},
|
||||
"addCustomEmoji": {"path": ""},
|
||||
"addToFloat": {"wxid": ""},
|
||||
"removeFromFloat": {"wxid": ""},
|
||||
"postMoments": {"content": ""},
|
||||
"deleteMoments": {"moment_id": ""},
|
||||
"likeMoments": {"moment_id": ""},
|
||||
"commentMoments": {"moment_id": "", "content": ""},
|
||||
"openMiniProgram": {"app_id": ""},
|
||||
"shareMiniProgram": {"app_id": "", "to_id": ""},
|
||||
"followOfficialAccount": {"official_id": ""},
|
||||
"unfollowOfficialAccount": {"official_id": ""},
|
||||
"followChannel": {"channel_id": ""},
|
||||
"unfollowChannel": {"channel_id": ""},
|
||||
"likeChannelVideo": {"video_id": ""},
|
||||
"commentChannelVideo": {"video_id": "", "content": ""},
|
||||
"shareChannelVideo": {"video_id": "", "to_id": ""},
|
||||
"scanQrCode": {"image_path": ""},
|
||||
"setNickname": {"nickname": ""},
|
||||
"setSignature": {"signature": ""},
|
||||
"setSex": {"sex": 0},
|
||||
"setRegion": {"country": "", "province": "", "city": ""},
|
||||
"setAvatar": {"path": ""},
|
||||
"setWhatUp": {"content": ""},
|
||||
"setChatBackground": {"wxid": "", "path": ""},
|
||||
"setPrivacy": {"key": "", "value": False},
|
||||
"setNotification": {"key": "", "value": False},
|
||||
"setAccountProtection": {"enable": False},
|
||||
"enableFingerprint": {"enable": False},
|
||||
"changePassword": {"old_pwd": "", "new_pwd": ""},
|
||||
"bindPhone": {"phone": ""},
|
||||
"unbindPhone": {},
|
||||
"removeLoginDevice": {"device_id": ""},
|
||||
"loginByPassword": {"phone": "", "password": ""},
|
||||
"loginBySms": {"phone": "", "code": ""},
|
||||
"registerAccount": {"phone": "", "password": ""},
|
||||
"autoRegister": {"phone": ""},
|
||||
"logout": {},
|
||||
"switchAccount": {"wxid": ""},
|
||||
"unblockSelf": {"wxid": ""},
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
print(f"\n{'='*70}")
|
||||
print(f" 工作手机SDK - 全量真机验证 (WiFi + Frida)")
|
||||
print(f" 时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print(f" 连接: {DEVICE_IP}:{FRIDA_PORT} (纯Frida无线,无USB依赖)")
|
||||
print(f"{'='*70}\n")
|
||||
|
||||
# 获取PID
|
||||
pid = get_wechat_pid()
|
||||
print(f"[INFO] 微信PID: {pid}")
|
||||
|
||||
# 连接
|
||||
device = frida.get_device_manager().add_remote_device(f"{DEVICE_IP}:{FRIDA_PORT}")
|
||||
session = device.attach(pid)
|
||||
print(f"[INFO] Frida session attached")
|
||||
|
||||
# 加载脚本
|
||||
with open(SCRIPT_PATH, "r") as f:
|
||||
src = f.read()
|
||||
script = session.create_script(src)
|
||||
script.on("message", lambda m, d: None)
|
||||
script.load()
|
||||
time.sleep(3)
|
||||
exports = script.exports_sync
|
||||
print(f"[INFO] Hook脚本加载完成, {len([x for x in dir(exports) if not x.startswith('_')])} 方法可用\n")
|
||||
|
||||
# 获取所有可用方法
|
||||
all_methods = sorted([x for x in dir(exports) if not x.startswith("_")])
|
||||
results = []
|
||||
screenshots = []
|
||||
|
||||
# 逐个验证
|
||||
for idx, method in enumerate(all_methods, 1):
|
||||
sys.stdout.write(f"\r[{idx:3d}/{len(all_methods)}] {method:40s}")
|
||||
sys.stdout.flush()
|
||||
|
||||
params = SAFE_PARAMS.get(method, {})
|
||||
fn = getattr(exports, method)
|
||||
|
||||
start = time.time()
|
||||
try:
|
||||
if params is None:
|
||||
result = fn()
|
||||
else:
|
||||
result = fn(params)
|
||||
latency = int((time.time() - start) * 1000)
|
||||
status = "PASS"
|
||||
if isinstance(result, dict) and result.get("success") == False:
|
||||
error_msg = result.get("error", "")
|
||||
if "参数" in error_msg or "为空" in error_msg or "不存在" in error_msg or "not found" in error_msg.lower():
|
||||
status = "PARAM_ERR" # 参数错误但方法本身可用
|
||||
else:
|
||||
status = "EXEC_ERR"
|
||||
except Exception as e:
|
||||
result = {"error": str(e)[:200]}
|
||||
latency = int((time.time() - start) * 1000)
|
||||
status = "EXCEPTION"
|
||||
|
||||
results.append({
|
||||
"index": idx,
|
||||
"method": method,
|
||||
"status": status,
|
||||
"latency_ms": latency,
|
||||
"params": params,
|
||||
"result": result if not isinstance(result, bytes) else "<binary>",
|
||||
})
|
||||
|
||||
# 每10个方法截一次图
|
||||
if idx % 10 == 0 or idx == len(all_methods):
|
||||
try:
|
||||
sc_result = exports.takeScreenshot({"path": f"/sdcard/verify_{idx}.png"})
|
||||
if sc_result.get("success"):
|
||||
b64 = exports.getScreenshotBase64({"path": f"/sdcard/verify_{idx}.png"})
|
||||
if b64.get("success"):
|
||||
sc_file = os.path.join(OUTPUT_DIR, "screenshots", f"step_{idx:03d}.png")
|
||||
with open(sc_file, "wb") as sf:
|
||||
sf.write(base64.b64decode(b64["base64"]))
|
||||
screenshots.append({"step": idx, "file": sc_file})
|
||||
except:
|
||||
pass
|
||||
|
||||
print(f"\n\n{'='*70}")
|
||||
print(f" 验证完成!")
|
||||
print(f"{'='*70}\n")
|
||||
|
||||
# 统计
|
||||
total = len(results)
|
||||
passed = sum(1 for r in results if r["status"] == "PASS")
|
||||
param_err = sum(1 for r in results if r["status"] == "PARAM_ERR")
|
||||
exec_err = sum(1 for r in results if r["status"] == "EXEC_ERR")
|
||||
exception = sum(1 for r in results if r["status"] == "EXCEPTION")
|
||||
|
||||
print(f" 总计: {total}")
|
||||
print(f" PASS (完全成功): {passed}")
|
||||
print(f" PARAM_ERR (参数错误/方法可用): {param_err}")
|
||||
print(f" EXEC_ERR (执行错误): {exec_err}")
|
||||
print(f" EXCEPTION (异常): {exception}")
|
||||
print(f" 功能可用率: {(passed + param_err) / total * 100:.1f}%")
|
||||
print(f" 截图数: {len(screenshots)}")
|
||||
|
||||
# 保存JSON
|
||||
report = {
|
||||
"title": "工作手机SDK全量真机验证",
|
||||
"time": datetime.now().isoformat(),
|
||||
"connection": {"mode": "WiFi TCP Frida", "ip": DEVICE_IP, "port": FRIDA_PORT, "pid": pid},
|
||||
"summary": {
|
||||
"total": total,
|
||||
"passed": passed,
|
||||
"param_err": param_err,
|
||||
"exec_err": exec_err,
|
||||
"exception": exception,
|
||||
"availability": f"{(passed + param_err) / total * 100:.1f}%",
|
||||
},
|
||||
"results": results,
|
||||
"screenshots": screenshots,
|
||||
}
|
||||
|
||||
json_file = os.path.join(OUTPUT_DIR, "verification_report.json")
|
||||
with open(json_file, "w", encoding="utf-8") as jf:
|
||||
json.dump(report, jf, ensure_ascii=False, indent=2, default=str)
|
||||
print(f"\n JSON: {json_file}")
|
||||
|
||||
# 生成Markdown报告
|
||||
md_lines = [
|
||||
"# 工作手机SDK - 全量真机验证报告\n",
|
||||
f"> **时间**: {report['time']}",
|
||||
f"> **连接方式**: WiFi TCP + Frida (纯无线,无USB/ADB依赖)",
|
||||
f"> **设备IP**: {DEVICE_IP}:{FRIDA_PORT}",
|
||||
f"> **微信PID**: {pid}\n",
|
||||
"## 验证总览\n",
|
||||
"| 指标 | 数值 |",
|
||||
"|------|------|",
|
||||
f"| 总方法数 | {total} |",
|
||||
f"| PASS (完全成功) | {passed} |",
|
||||
f"| PARAM_ERR (方法可用/参数不足) | {param_err} |",
|
||||
f"| EXEC_ERR (执行错误) | {exec_err} |",
|
||||
f"| EXCEPTION (异常) | {exception} |",
|
||||
f"| **功能可用率** | **{(passed + param_err) / total * 100:.1f}%** |\n",
|
||||
"## 详细结果\n",
|
||||
"| # | 方法名 | 状态 | 延迟(ms) | 说明 |",
|
||||
"|---|--------|------|----------|------|",
|
||||
]
|
||||
|
||||
for r in results:
|
||||
icon = {"PASS": "✅", "PARAM_ERR": "⚠️", "EXEC_ERR": "❌", "EXCEPTION": "💥"}[r["status"]]
|
||||
desc = ""
|
||||
if isinstance(r["result"], dict):
|
||||
if r["status"] == "PASS":
|
||||
keys = list(r["result"].keys())[:3] if isinstance(r["result"], dict) else []
|
||||
desc = f"返回: {', '.join(keys)}"
|
||||
elif r["result"].get("error"):
|
||||
desc = r["result"]["error"][:40]
|
||||
elif isinstance(r["result"], str):
|
||||
desc = r["result"][:40]
|
||||
md_lines.append(f"| {r['index']} | `{r['method']}` | {icon} {r['status']} | {r['latency_ms']} | {desc} |")
|
||||
|
||||
md_lines.append("\n## 功能分类统计\n")
|
||||
|
||||
# 按功能分类
|
||||
categories = {
|
||||
"系统/Hook": ["ping", "getHookStatus", "getProcessInfo", "getWechatVersion", "getVersionCompat", "getConnectionStatus", "getCurrentActivity", "batchExecute"],
|
||||
"设备信息": ["getDeviceInfo", "getNetworkInfo", "getStorageInfo"],
|
||||
"联系人": ["getContacts", "getContactInfo", "searchContacts", "getContactsByLabel"],
|
||||
"消息": ["sendMessage", "getMessages", "getRecentMessages", "searchMessages", "sendImage", "sendVideo", "sendFile", "sendVoice", "sendEmoji", "sendCard", "sendLink", "sendLocation", "sendGroupMessage", "forwardMessage", "forwardMultiple", "revokeMessage", "clearChatHistory", "pinChat"],
|
||||
"好友管理": ["addFriend", "acceptFriend", "deleteFriend", "addFriendByQr", "setFriendRemark", "getFriendRequests", "setDoNotDisturb", "setContactLabel"],
|
||||
"群管理": ["getGroups", "getGroupInfo", "getGroupMembers", "createGroup", "inviteToGroup", "removeFromGroup", "quitGroup", "setGroupName", "setGroupAnnouncement", "generateGroupQrCode"],
|
||||
"个人信息": ["getProfile", "checkAccountStatus", "setNickname", "setSignature", "setSex", "setRegion", "setAvatar", "setWhatUp"],
|
||||
"朋友圈": ["getMoments", "postMoments", "deleteMoments", "likeMoments", "commentMoments"],
|
||||
"标签": ["getLabels", "createLabel", "deleteLabel"],
|
||||
"收藏": ["getFavorites", "addFavorite", "deleteFavorite", "addCustomEmoji"],
|
||||
"搜索": ["globalSearch"],
|
||||
"小程序": ["getRecentMiniPrograms", "openMiniProgram", "shareMiniProgram"],
|
||||
"公众号": ["getOfficialAccounts", "getOfficialAccountArticles", "followOfficialAccount", "unfollowOfficialAccount"],
|
||||
"视频号": ["browseChannels", "followChannel", "unfollowChannel", "likeChannelVideo", "commentChannelVideo", "shareChannelVideo"],
|
||||
"支付": ["getWalletBalance", "getTransactionHistory", "sendRedPacket", "sendTransfer", "receiveRedPacket", "receiveTransfer"],
|
||||
"二维码": ["generateMyQrCode", "scanQrCode"],
|
||||
"账号安全": ["getLoginDevices", "checkLoginState", "getSimPhone", "setAccountProtection", "enableFingerprint", "changePassword", "bindPhone", "unbindPhone", "removeLoginDevice"],
|
||||
"登录注册": ["loginByPassword", "loginBySms", "registerAccount", "autoRegister", "logout", "switchAccount"],
|
||||
"系统控制": ["takeScreenshot", "getScreenshotBase64", "navigateToChat", "navigateToMain", "navigateToMoments", "simulateTap", "simulateBack", "simulateInput"],
|
||||
"其他": ["addToFloat", "removeFromFloat", "setChatBackground", "setPrivacy", "setNotification", "unblockSelf"],
|
||||
}
|
||||
|
||||
md_lines.append("| 分类 | 方法数 | 通过 | 可用率 |")
|
||||
md_lines.append("|------|--------|------|--------|")
|
||||
for cat, methods_list in categories.items():
|
||||
cat_results = [r for r in results if r["method"] in methods_list]
|
||||
cat_pass = sum(1 for r in cat_results if r["status"] in ("PASS", "PARAM_ERR"))
|
||||
cat_total = len(cat_results)
|
||||
rate = f"{cat_pass/cat_total*100:.0f}%" if cat_total > 0 else "N/A"
|
||||
md_lines.append(f"| {cat} | {cat_total} | {cat_pass} | {rate} |")
|
||||
|
||||
md_lines.append("\n## 截图\n")
|
||||
for sc in screenshots:
|
||||
md_lines.append(f"- Step {sc['step']}: })")
|
||||
|
||||
md_file = os.path.join(OUTPUT_DIR, "verification_report.md")
|
||||
with open(md_file, "w", encoding="utf-8") as mf:
|
||||
mf.write("\n".join(md_lines))
|
||||
print(f" Markdown: {md_file}")
|
||||
|
||||
# 清理
|
||||
script.unload()
|
||||
session.detach()
|
||||
print(f"\n[DONE] 验证完成!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
39
sdk/tests/mini2.py
Normal file
39
sdk/tests/mini2.py
Normal file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python3
|
||||
"""极简Frida测试 - PID 16816"""
|
||||
import frida, time, sys, os
|
||||
|
||||
OUT = "/tmp/frida_out.txt"
|
||||
f = open(OUT, "w")
|
||||
|
||||
def log(msg):
|
||||
f.write(msg + "\n")
|
||||
f.flush()
|
||||
print(msg)
|
||||
sys.stdout.flush()
|
||||
|
||||
try:
|
||||
log("[1] Connect to 192.168.0.12:27042")
|
||||
d = frida.get_device_manager().add_remote_device("192.168.0.12:27042")
|
||||
log(f"[2] Device: {d.name}")
|
||||
log("[3] Attach PID 16816")
|
||||
s = d.attach(16816)
|
||||
log("[4] Create script")
|
||||
sc = s.create_script('rpc.exports={ping:function(){return "pong";}};')
|
||||
sc.on("message", lambda m, d: None)
|
||||
log("[5] Loading...")
|
||||
sc.load()
|
||||
time.sleep(1)
|
||||
log("[6] Loaded! Calling exports...")
|
||||
e = sc.exports_sync
|
||||
methods = [x for x in dir(e) if not x.startswith("_")]
|
||||
log(f"[7] Methods: {methods}")
|
||||
log(f"[8] ping() = {e.ping()}")
|
||||
sc.unload()
|
||||
s.detach()
|
||||
log("[DONE]")
|
||||
except Exception as ex:
|
||||
log(f"[ERROR] {ex}")
|
||||
import traceback
|
||||
traceback.print_exc(file=f)
|
||||
finally:
|
||||
f.close()
|
||||
44
sdk/tests/mini_test.py
Normal file
44
sdk/tests/mini_test.py
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
"""极简Frida方法名测试 - 只加载小脚本"""
|
||||
import frida, time, json, sys
|
||||
|
||||
print("[1] Connecting to 192.168.0.12:27042...")
|
||||
d = frida.get_device_manager().add_remote_device("192.168.0.12:27042")
|
||||
print(f"[2] Device: {d.name}")
|
||||
print("[3] Attaching to PID 7239...")
|
||||
s = d.attach(7239)
|
||||
print("[4] Creating mini script...")
|
||||
|
||||
# 极简脚本
|
||||
MINI = """
|
||||
'use strict';
|
||||
rpc.exports = {
|
||||
ping: function() { return "pong_mini"; },
|
||||
getInfo: function() { return {pid: Process.id, arch: Process.arch}; },
|
||||
camelCaseTest: function() { return "camel_works"; },
|
||||
snake_case_test: function() { return "snake_works"; },
|
||||
};
|
||||
"""
|
||||
|
||||
sc = s.create_script(MINI)
|
||||
sc.on("message", lambda m, d: None)
|
||||
sc.load()
|
||||
time.sleep(1)
|
||||
print("[5] Script loaded!")
|
||||
|
||||
e = sc.exports_sync
|
||||
methods = [x for x in dir(e) if not x.startswith("_")]
|
||||
print(f"[6] Available methods: {methods}")
|
||||
|
||||
# 测试每个方法
|
||||
for name in methods:
|
||||
fn = getattr(e, name)
|
||||
try:
|
||||
r = fn()
|
||||
print(f" {name}() -> {r}")
|
||||
except Exception as ex:
|
||||
print(f" {name}() -> ERROR: {ex}")
|
||||
|
||||
sc.unload()
|
||||
s.detach()
|
||||
print("\n[DONE]")
|
||||
63
sdk/tests/probe2.py
Normal file
63
sdk/tests/probe2.py
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
"""快速探测Frida方法名格式 - 带超时保护"""
|
||||
import frida, time, json, signal, sys
|
||||
|
||||
def timeout_handler(signum, frame):
|
||||
print("TIMEOUT!")
|
||||
sys.exit(1)
|
||||
|
||||
signal.signal(signal.SIGALRM, timeout_handler)
|
||||
signal.alarm(20) # 20秒超时
|
||||
|
||||
print("[1] Connecting...")
|
||||
d = frida.get_device_manager().add_remote_device("192.168.0.12:27042")
|
||||
print("[2] Attaching...")
|
||||
s = d.attach(7239)
|
||||
print("[3] Loading script...")
|
||||
|
||||
# 用一个极简脚本测试方法名格式
|
||||
MINI_SCRIPT = """
|
||||
rpc.exports = {
|
||||
ping: function() { return "pong"; },
|
||||
getProcessInfo: function() { return {pid: Process.id, arch: Process.arch}; },
|
||||
getConnectionStatus: function() { return {mode: "tcp", ts: Date.now()}; },
|
||||
takeScreenshot: function(p) { return {success: true, test: true}; },
|
||||
};
|
||||
"""
|
||||
|
||||
sc = s.create_script(MINI_SCRIPT)
|
||||
sc.on("message", lambda m, d: None)
|
||||
sc.load()
|
||||
time.sleep(1)
|
||||
|
||||
e = sc.exports_sync
|
||||
methods = [x for x in dir(e) if not x.startswith("_")]
|
||||
print(f"[4] Methods ({len(methods)}): {methods}")
|
||||
|
||||
# 测试各种格式
|
||||
print("\n[5] Testing method name formats:")
|
||||
tests = [
|
||||
("ping", None),
|
||||
("getProcessInfo", None),
|
||||
("getprocessinfo", None),
|
||||
("get_process_info", None),
|
||||
("getConnectionStatus", None),
|
||||
("getconnectionstatus", None),
|
||||
("takeScreenshot", {"path": "/tmp/test.png"}),
|
||||
("takescreenshot", {"path": "/tmp/test.png"}),
|
||||
]
|
||||
|
||||
for name, params in tests:
|
||||
fn = getattr(e, name, None)
|
||||
if fn is None:
|
||||
print(f" {name}: NOT IN DIR")
|
||||
continue
|
||||
try:
|
||||
r = fn(params) if params else fn()
|
||||
print(f" {name}: OK -> {json.dumps(r)[:60]}")
|
||||
except Exception as ex:
|
||||
print(f" {name}: ERROR -> {ex}")
|
||||
|
||||
sc.unload()
|
||||
s.detach()
|
||||
print("\nDone!")
|
||||
43
sdk/tests/probe_methods.py
Normal file
43
sdk/tests/probe_methods.py
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python3
|
||||
"""快速探测Frida exports方法名格式"""
|
||||
import frida, time, sys, os
|
||||
|
||||
SCRIPT_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
||||
"../agent/hook/wechat_hook_v2.js")
|
||||
|
||||
device = frida.get_device_manager().add_remote_device("192.168.0.12:27042")
|
||||
session = device.attach(7239)
|
||||
|
||||
with open(SCRIPT_PATH, "r") as f:
|
||||
src = f.read()
|
||||
|
||||
script = session.create_script(src)
|
||||
script.on("message", lambda m, d: None)
|
||||
script.load()
|
||||
time.sleep(2)
|
||||
|
||||
exports = script.exports_sync
|
||||
|
||||
# 列出所有方法
|
||||
methods = sorted([x for x in dir(exports) if not x.startswith("_")])
|
||||
print(f"Total: {len(methods)}")
|
||||
for m in methods:
|
||||
print(f" {m}")
|
||||
|
||||
# 直接调用ping
|
||||
print(f"\n--- Test calls ---")
|
||||
print(f"ping() = {exports.ping()}")
|
||||
|
||||
# 尝试不同格式调用getProcessInfo
|
||||
for name in ["getProcessInfo", "getprocessinfo", "get_process_info"]:
|
||||
try:
|
||||
fn = getattr(exports, name)
|
||||
r = fn()
|
||||
print(f"{name}() = OK: {str(r)[:80]}")
|
||||
break
|
||||
except Exception as e:
|
||||
print(f"{name}() = FAIL: {e}")
|
||||
|
||||
script.unload()
|
||||
session.detach()
|
||||
print("\nDone.")
|
||||
Reference in New Issue
Block a user