Preserve WeChat original entitlements when re-signing (v0.2.3)
- Extract existing entitlements before re-signing - Merge get-task-allow into original entitlements instead of replacing - Prevents breaking WeChat features like Search after init
This commit is contained in:
parent
b794ad1370
commit
7158422618
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@canghe_ai/wechat-cli-darwin-arm64",
|
"name": "@canghe_ai/wechat-cli-darwin-arm64",
|
||||||
"version": "0.2.2",
|
"version": "0.2.3",
|
||||||
"description": "wechat-cli binary for macOS arm64",
|
"description": "wechat-cli binary for macOS arm64",
|
||||||
"os": ["darwin"],
|
"os": ["darwin"],
|
||||||
"cpu": ["arm64"],
|
"cpu": ["arm64"],
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@canghe_ai/wechat-cli",
|
"name": "@canghe_ai/wechat-cli",
|
||||||
"version": "0.2.2",
|
"version": "0.2.3",
|
||||||
"description": "WeChat data query CLI — chat history, contacts, sessions, favorites, and more. Designed for LLM integration.",
|
"description": "WeChat data query CLI — chat history, contacts, sessions, favorites, and more. Designed for LLM integration.",
|
||||||
"bin": {
|
"bin": {
|
||||||
"wechat-cli": "bin/wechat-cli.js"
|
"wechat-cli": "bin/wechat-cli.js"
|
||||||
@ -13,7 +13,7 @@
|
|||||||
"install.js"
|
"install.js"
|
||||||
],
|
],
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@canghe_ai/wechat-cli-darwin-arm64": "0.2.2"
|
"@canghe_ai/wechat-cli-darwin-arm64": "0.2.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
|
|||||||
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "wechat-cli"
|
name = "wechat-cli"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
description = "WeChat data query CLI for LLMs"
|
description = "WeChat data query CLI for LLMs"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@ -2,24 +2,13 @@
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import plistlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
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 二进制。"""
|
||||||
@ -52,8 +41,34 @@ def _find_binary():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_original_entitlements(app_path):
|
||||||
|
"""提取 app 当前的签名 entitlements,返回 dict 或 None。"""
|
||||||
|
try:
|
||||||
|
result = subprocess.run(
|
||||||
|
["codesign", "-d", "--entitlements", ":-", app_path],
|
||||||
|
capture_output=True,
|
||||||
|
timeout=15,
|
||||||
|
)
|
||||||
|
if result.returncode == 0 and result.stdout:
|
||||||
|
return plistlib.loads(result.stdout)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _build_entitlements_xml(app_path):
|
||||||
|
"""构建 entitlements:保留原有权限 + 添加 get-task-allow。"""
|
||||||
|
entitlements = _get_original_entitlements(app_path)
|
||||||
|
if entitlements is None:
|
||||||
|
entitlements = {}
|
||||||
|
|
||||||
|
entitlements["com.apple.security.get-task-allow"] = True
|
||||||
|
|
||||||
|
return plistlib.dumps(entitlements, fmt=plistlib.FMT_XML)
|
||||||
|
|
||||||
|
|
||||||
def _resign_wechat():
|
def _resign_wechat():
|
||||||
"""Re-sign WeChat with get-task-allow entitlement so task_for_pid works."""
|
"""Re-sign WeChat: 保留原有 entitlements,仅添加 get-task-allow。"""
|
||||||
wechat_paths = [
|
wechat_paths = [
|
||||||
"/Applications/WeChat.app",
|
"/Applications/WeChat.app",
|
||||||
os.path.expanduser("~/Applications/WeChat.app"),
|
os.path.expanduser("~/Applications/WeChat.app"),
|
||||||
@ -67,14 +82,19 @@ def _resign_wechat():
|
|||||||
if wechat_app is None:
|
if wechat_app is None:
|
||||||
return False, "未找到 WeChat.app(已搜索 /Applications 和 ~/Applications)"
|
return False, "未找到 WeChat.app(已搜索 /Applications 和 ~/Applications)"
|
||||||
|
|
||||||
# Write entitlements to temp file
|
print(f"\n[*] 检测到 task_for_pid 权限不足,正在对微信重新签名...")
|
||||||
ent_fd, ent_path = tempfile.mkstemp(suffix=".xml")
|
print(f" 目标: {wechat_app}")
|
||||||
try:
|
|
||||||
with os.fdopen(ent_fd, "w") as f:
|
|
||||||
f.write(_ENTITLEMENTS_XML)
|
|
||||||
|
|
||||||
print(f"\n[*] 检测到 task_for_pid 权限不足,正在对微信重新签名...")
|
# 提取并合并 entitlements
|
||||||
print(f" 目标: {wechat_app}")
|
try:
|
||||||
|
ent_data = _build_entitlements_xml(wechat_app)
|
||||||
|
except Exception as e:
|
||||||
|
return False, f"提取微信原始权限失败: {e}"
|
||||||
|
|
||||||
|
ent_fd, ent_path = tempfile.mkstemp(suffix=".plist")
|
||||||
|
try:
|
||||||
|
with os.fdopen(ent_fd, "wb") as f:
|
||||||
|
f.write(ent_data)
|
||||||
|
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
["codesign", "--force", "--sign", "-", "--entitlements", ent_path, wechat_app],
|
["codesign", "--force", "--sign", "-", "--entitlements", ent_path, wechat_app],
|
||||||
@ -88,7 +108,9 @@ def _resign_wechat():
|
|||||||
if result.returncode != 0:
|
if result.returncode != 0:
|
||||||
return False, f"codesign 失败: {result.stderr.strip()}"
|
return False, f"codesign 失败: {result.stderr.strip()}"
|
||||||
|
|
||||||
print("[+] 签名完成!请重新启动微信后再执行 init。")
|
print("[+] 签名完成(已保留微信原有权限,仅添加调试访问权限)。")
|
||||||
|
print("[+] 请重新启动微信后再执行 init。")
|
||||||
|
print("[!] 注意:如果微信自动更新,可能需要重新签名。")
|
||||||
return True, None
|
return True, None
|
||||||
|
|
||||||
|
|
||||||
@ -145,23 +167,29 @@ def extract_keys(db_dir, output_path, pid=None):
|
|||||||
combined_output = (result.stdout or "") + (result.stderr or "")
|
combined_output = (result.stdout or "") + (result.stderr or "")
|
||||||
if "task_for_pid" in combined_output:
|
if "task_for_pid" in combined_output:
|
||||||
print("\n[!] task_for_pid 失败:macOS 安全策略阻止了进程内存访问。")
|
print("\n[!] task_for_pid 失败:macOS 安全策略阻止了进程内存访问。")
|
||||||
print("[!] 需要对微信重新签名以允许调试访问。")
|
print("[!] 需要对微信重新签名以允许调试访问(不影响微信正常功能)。")
|
||||||
|
|
||||||
ok, err = _resign_wechat()
|
ok, err = _resign_wechat()
|
||||||
if ok:
|
if ok:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"已对微信重新签名。请执行以下步骤后重试:\n"
|
"已对微信重新签名(保留原有权限)。请执行以下步骤后重试:\n"
|
||||||
" 1. 退出微信(完全退出,不是最小化)\n"
|
" 1. 退出微信(完全退出,不是最小化)\n"
|
||||||
" 2. 重新打开微信并登录\n"
|
" 2. 重新打开微信并登录\n"
|
||||||
" 3. 再次执行: sudo wechat-cli init"
|
" 3. 再次执行: sudo wechat-cli init"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
# 手动命令也需要保留原有权限
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"自动签名失败: {err}\n"
|
f"自动签名失败: {err}\n"
|
||||||
"请手动执行以下命令后重试:\n"
|
"请手动执行以下命令后重试:\n"
|
||||||
' codesign --force --sign - --entitlements /dev/stdin /Applications/WeChat.app <<\'EOF\'\n'
|
" # 1. 提取微信原有权限\n"
|
||||||
+ _ENTITLEMENTS_XML +
|
" codesign -d --entitlements wechat_ent.plist /Applications/WeChat.app\n"
|
||||||
"EOF\n"
|
" # 2. 用 PlistBuddy 添加 get-task-allow\n"
|
||||||
|
' /usr/libexec/PlistBuddy -c "Add :com.apple.security.get-task-allow bool true" wechat_ent.plist\n'
|
||||||
|
" # 3. 重新签名\n"
|
||||||
|
" codesign --force --sign - --entitlements wechat_ent.plist /Applications/WeChat.app\n"
|
||||||
|
" # 4. 清理\n"
|
||||||
|
" rm wechat_ent.plist\n"
|
||||||
"然后重启微信,再执行: sudo wechat-cli init"
|
"然后重启微信,再执行: sudo wechat-cli init"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import click
|
|||||||
|
|
||||||
from .core.context import AppContext
|
from .core.context import AppContext
|
||||||
|
|
||||||
_VERSION = "0.2.2"
|
_VERSION = "0.2.3"
|
||||||
|
|
||||||
|
|
||||||
@click.group()
|
@click.group()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user