Auto re-sign WeChat when task_for_pid fails on macOS
When init fails due to macOS security policy (task_for_pid error), automatically re-sign WeChat with get-task-allow entitlement. Falls back to manual instructions if auto-signing fails.
This commit is contained in:
parent
3d75bde4ef
commit
2b1fc0a4b9
@ -4,9 +4,22 @@ import os
|
|||||||
import platform
|
import platform
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
|
|
||||||
from .common import collect_db_files, cross_verify_keys, save_results, scan_memory_for_keys
|
from .common import collect_db_files, cross_verify_keys, save_results, scan_memory_for_keys
|
||||||
|
|
||||||
|
# Entitlements needed for task_for_pid to work on WeChat
|
||||||
|
_ENTITLEMENTS_XML = """\
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.get-task-allow</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def _find_binary():
|
def _find_binary():
|
||||||
"""查找对应架构的 C 二进制。"""
|
"""查找对应架构的 C 二进制。"""
|
||||||
@ -39,6 +52,46 @@ def _find_binary():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _resign_wechat():
|
||||||
|
"""Re-sign WeChat with get-task-allow entitlement so task_for_pid works."""
|
||||||
|
wechat_paths = [
|
||||||
|
"/Applications/WeChat.app",
|
||||||
|
os.path.expanduser("~/Applications/WeChat.app"),
|
||||||
|
]
|
||||||
|
wechat_app = None
|
||||||
|
for p in wechat_paths:
|
||||||
|
if os.path.isdir(p):
|
||||||
|
wechat_app = p
|
||||||
|
break
|
||||||
|
|
||||||
|
if wechat_app is None:
|
||||||
|
return False, "未找到 WeChat.app(已搜索 /Applications 和 ~/Applications)"
|
||||||
|
|
||||||
|
# Write entitlements to temp file
|
||||||
|
ent_fd, ent_path = tempfile.mkstemp(suffix=".xml")
|
||||||
|
try:
|
||||||
|
with os.fdopen(ent_fd, "w") as f:
|
||||||
|
f.write(_ENTITLEMENTS_XML)
|
||||||
|
|
||||||
|
print(f"\n[*] 检测到 task_for_pid 权限不足,正在对微信重新签名...")
|
||||||
|
print(f" 目标: {wechat_app}")
|
||||||
|
|
||||||
|
result = subprocess.run(
|
||||||
|
["codesign", "--force", "--sign", "-", "--entitlements", ent_path, wechat_app],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
timeout=60,
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
os.unlink(ent_path)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
return False, f"codesign 失败: {result.stderr.strip()}"
|
||||||
|
|
||||||
|
print("[+] 签名完成!请重新启动微信后再执行 init。")
|
||||||
|
return True, None
|
||||||
|
|
||||||
|
|
||||||
def extract_keys(db_dir, output_path, pid=None):
|
def extract_keys(db_dir, output_path, pid=None):
|
||||||
"""通过 C 二进制提取 macOS 微信数据库密钥。
|
"""通过 C 二进制提取 macOS 微信数据库密钥。
|
||||||
|
|
||||||
@ -54,7 +107,6 @@ def extract_keys(db_dir, output_path, pid=None):
|
|||||||
Returns:
|
Returns:
|
||||||
dict: salt_hex -> enc_key_hex 映射
|
dict: salt_hex -> enc_key_hex 映射
|
||||||
"""
|
"""
|
||||||
import re
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
binary = _find_binary()
|
binary = _find_binary()
|
||||||
@ -89,14 +141,33 @@ def extract_keys(db_dir, output_path, pid=None):
|
|||||||
if result.stderr:
|
if result.stderr:
|
||||||
print(result.stderr, file=sys.stderr)
|
print(result.stderr, file=sys.stderr)
|
||||||
|
|
||||||
|
# 检测 task_for_pid 失败 → 尝试 re-sign
|
||||||
|
combined_output = (result.stdout or "") + (result.stderr or "")
|
||||||
|
if "task_for_pid" in combined_output:
|
||||||
|
print("\n[!] task_for_pid 失败:macOS 安全策略阻止了进程内存访问。")
|
||||||
|
print("[!] 需要对微信重新签名以允许调试访问。")
|
||||||
|
|
||||||
|
ok, err = _resign_wechat()
|
||||||
|
if ok:
|
||||||
|
raise RuntimeError(
|
||||||
|
"已对微信重新签名。请执行以下步骤后重试:\n"
|
||||||
|
" 1. 退出微信(完全退出,不是最小化)\n"
|
||||||
|
" 2. 重新打开微信并登录\n"
|
||||||
|
" 3. 再次执行: sudo wechat-cli init"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise RuntimeError(
|
||||||
|
f"自动签名失败: {err}\n"
|
||||||
|
"请手动执行以下命令后重试:\n"
|
||||||
|
' codesign --force --sign - --entitlements /dev/stdin /Applications/WeChat.app <<\'EOF\'\n'
|
||||||
|
+ _ENTITLEMENTS_XML +
|
||||||
|
"EOF\n"
|
||||||
|
"然后重启微信,再执行: sudo wechat-cli init"
|
||||||
|
)
|
||||||
|
|
||||||
# C 二进制输出 all_keys.json 到 work_dir
|
# C 二进制输出 all_keys.json 到 work_dir
|
||||||
c_output = os.path.join(work_dir, "all_keys.json")
|
c_output = os.path.join(work_dir, "all_keys.json")
|
||||||
if not os.path.exists(c_output):
|
if not os.path.exists(c_output):
|
||||||
if "task_for_pid" in (result.stdout or "") + (result.stderr or ""):
|
|
||||||
raise RuntimeError(
|
|
||||||
"需要 root 权限才能读取微信进程内存。\n"
|
|
||||||
"请使用: sudo wechat-cli init"
|
|
||||||
)
|
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"C 二进制未能生成密钥文件。\n"
|
"C 二进制未能生成密钥文件。\n"
|
||||||
f"stdout: {result.stdout}\nstderr: {result.stderr}"
|
f"stdout: {result.stdout}\nstderr: {result.stderr}"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user