mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-10-05 04:20:34 +08:00
fix: 增加sip文案
This commit is contained in:
+60
-3
@@ -1,5 +1,62 @@
|
||||
# macOS 数据访问说明(兼容入口)
|
||||
# macOS 关闭 SIP 教程
|
||||
|
||||
完整内容已移到[macOS 数据访问与系统权限](./platform/macos.md)。
|
||||
SIP(System Integrity Protection,系统完整性保护)是 macOS 的系统安全机制。关闭 SIP 会降低系统安全性,只建议在确实需要读取或调试本地微信数据时临时关闭;操作完成后,建议重新开启。
|
||||
|
||||
保留此文件是为了兼容应用内已经发布的帮助链接。请不要把“关闭 SIP”当作默认安装步骤;只有当当前连接页面明确要求时才处理,并在完成后恢复系统安全设置。
|
||||
> 只在连接页面明确提示需要关闭 SIP 时才处理。首次连接失败时,先确认微信版本、账号目录和登录时机,再按本文操作。关闭 SIP 不是 TraceMemo 的常规安装步骤,也不应长期保持关闭。
|
||||
|
||||
## 准备
|
||||
|
||||
- 一台 Mac 电脑,Intel 芯片和 Apple Silicon 芯片均可。
|
||||
- 需要进入 macOS 恢复模式。
|
||||
- 请先保存正在编辑的文件,并预留一次重启时间。
|
||||
|
||||
## 关闭 SIP
|
||||
|
||||
### Intel Mac
|
||||
|
||||
1. 关机。
|
||||
2. 按下开机键后,立刻按住 `Command + R`。
|
||||
3. 保持按住,直到进入 macOS 恢复模式。
|
||||
|
||||
### Apple Silicon Mac(M1/M2/M3/M4/M5)
|
||||
|
||||
1. 关机。
|
||||
2. 长按开机键不放。
|
||||
3. 直到出现启动选项界面后松开。
|
||||
4. 选择"选项",进入 macOS 恢复模式。
|
||||
|
||||
### 在恢复模式中执行命令
|
||||
|
||||
1. 进入恢复模式后,点击顶部菜单栏的 **Utilities(实用工具)**。
|
||||
2. 选择 **Terminal(终端)**。
|
||||
3. 在终端中输入:
|
||||
|
||||
```bash
|
||||
csrutil disable
|
||||
```
|
||||
|
||||
4. 按回车执行。
|
||||
5. 看到关闭成功提示后,重启电脑。
|
||||
|
||||
## 确认是否生效
|
||||
|
||||
重启回到正常桌面后,打开"终端",执行:
|
||||
|
||||
```bash
|
||||
csrutil status
|
||||
```
|
||||
|
||||
看到 `System Integrity Protection status: disabled.` 才算关闭成功。
|
||||
|
||||
若仍显示 `enabled`,说明没有生效。常见原因是没在恢复模式里执行,或系统刚做过大版本更新——
|
||||
macOS 大版本更新会把 SIP 重置回开启状态,此前关过也会失效,需要重新按上面的步骤操作。
|
||||
|
||||
## 重新开启 SIP
|
||||
|
||||
拿到数据库密钥后,建议重新进入恢复模式,在终端中执行:
|
||||
|
||||
```bash
|
||||
csrutil enable
|
||||
```
|
||||
|
||||
然后重启电脑,恢复系统安全设置。
|
||||
|
||||
@@ -8,7 +8,7 @@ TraceMemo 需要读取微信本地数据。macOS 会根据系统版本、微信
|
||||
|
||||
1. 先启动 TraceMemo,阅读连接页面显示的当前前置条件。
|
||||
2. 确认微信数据目录指向当前账号。
|
||||
3. 只在页面明确要求时处理系统授权或 SIP;按页面提示完成密钥获取后,恢复你平时使用的安全设置。
|
||||
3. 只在页面明确要求时处理系统授权或 SIP;关闭 SIP 的具体步骤见[关闭 SIP 教程](../mac-disable-sip.md),按页面提示完成密钥获取后,恢复你平时使用的安全设置。
|
||||
4. 返回应用重新检测账号、数据库和图片资源状态。
|
||||
|
||||
不要直接复制网上针对其他微信版本的命令。系统授权失败时,记录 macOS 版本、微信版本和页面错误,再按[排障文档](../user-guide/troubleshooting.md#连接微信失败)处理。
|
||||
|
||||
@@ -134,6 +134,15 @@ export function parseXkeyHelperOutput(output: string): DatabaseKeyResult {
|
||||
return mapXkeyHelperFailure(rawError)
|
||||
}
|
||||
|
||||
export const SIP_ENABLED_ERROR =
|
||||
'macOS 系统完整性保护(SIP)已开启,无法自动获取数据库密钥。请先关闭 SIP,或改用手动粘贴。'
|
||||
|
||||
export function parseSipEnabled(statusOutput: string): boolean {
|
||||
const status = statusOutput.match(/status:\s*([a-z]+)/i)?.[1]?.toLowerCase()
|
||||
if (status) return status === 'enabled'
|
||||
return statusOutput.toLowerCase().includes('enabled')
|
||||
}
|
||||
|
||||
export class KeyServiceMac {
|
||||
private getMacKeyRuntimeDir(): string {
|
||||
return path.join(app.getPath('userData'), 'key-runtime')
|
||||
@@ -306,7 +315,7 @@ export class KeyServiceMac {
|
||||
private async isSipEnabled(): Promise<boolean> {
|
||||
try {
|
||||
const { stdout } = await execFileAsync('/usr/bin/csrutil', ['status'])
|
||||
return stdout.toLowerCase().includes('enabled')
|
||||
return parseSipEnabled(stdout)
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
@@ -346,10 +355,7 @@ export class KeyServiceMac {
|
||||
return { success: false, error: '自动获取密钥目前仅支持 macOS' }
|
||||
}
|
||||
if (await this.isSipEnabled()) {
|
||||
return {
|
||||
success: false,
|
||||
error: '当前系统还未完成连接环境准备,请按页面提示完成设置。'
|
||||
}
|
||||
return { success: false, code: 'SIP_ENABLED', error: SIP_ENABLED_ERROR }
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -491,14 +491,8 @@ export function DatabaseConnectionPage({
|
||||
<p className="database-login-platform-note">
|
||||
{isMac ? (
|
||||
<>
|
||||
{isIntelMac
|
||||
? 'Intel Mac 首次使用需要先准备连接环境,按页面提示完成即可。'
|
||||
: 'macOS Apple 芯片首次获取密钥需要关闭 SIP,并在监听期间点击微信登录。'}{' '}
|
||||
<a
|
||||
href={isIntelMac ? GUIDE_URL : macKeyFaqUrl}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
macOS 首次获取密钥需要关闭 SIP,并在监听期间点击微信登录。{' '}
|
||||
<a href={macKeyFaqUrl} target="_blank" rel="noreferrer">
|
||||
查看说明
|
||||
</a>
|
||||
<br />第 4 步之前不要登录微信,只需保留微信登录页面窗口;授权后再点「登录」。
|
||||
|
||||
@@ -143,7 +143,9 @@ describe('DatabaseConnectionPage', () => {
|
||||
|
||||
expect(screen.getByRole('button', { name: '开始获取密钥' })).toBeVisible()
|
||||
expect(screen.queryByText(/管理员授权|电脑密码/)).not.toBeInTheDocument()
|
||||
expect(screen.queryByText(/Frida|Python|SIP|重新签名/)).not.toBeInTheDocument()
|
||||
// SIP is a user prerequisite, not an implementation detail: seeing it in the
|
||||
// UI is expected whenever the key cannot be captured without it.
|
||||
expect(screen.queryByText(/Frida|Python|重新签名/)).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('renders a discovered nickname and avatar before connection', () => {
|
||||
|
||||
@@ -84,7 +84,8 @@ describe('database key controls', () => {
|
||||
|
||||
expect(screen.getByText('Intel Mac 自动获取')).toBeVisible()
|
||||
expect(screen.getByText(/按页面提示操作即可/)).toBeVisible()
|
||||
expect(screen.queryByText(/Frida|Python|SIP|签名/)).not.toBeInTheDocument()
|
||||
// SIP is a user prerequisite, not an implementation detail.
|
||||
expect(screen.queryByText(/Frida|Python|签名/)).not.toBeInTheDocument()
|
||||
await user.click(screen.getByRole('button', { name: '自动获取密钥' }))
|
||||
expect(onDetect).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
@@ -7,9 +7,11 @@ vi.mock('electron', () => ({
|
||||
}))
|
||||
|
||||
import {
|
||||
SIP_ENABLED_ERROR,
|
||||
buildAppleSiliconXkeyInvocation,
|
||||
buildXkeyHelperArguments,
|
||||
mapXkeyHelperFailure,
|
||||
parseSipEnabled,
|
||||
parseXkeyHelperOutput,
|
||||
resolveXkeyHelperMode
|
||||
} from '../../src/main/key-service-mac'
|
||||
@@ -133,3 +135,28 @@ describe('parseXkeyHelperOutput', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('parseSipEnabled', () => {
|
||||
it.each<[string, boolean]>([
|
||||
['System Integrity Protection status: enabled.', true],
|
||||
['System Integrity Protection status: disabled.', false],
|
||||
['System Integrity Protection status: unknown (Custom Configuration).', false],
|
||||
['System Integrity Protection status: enabled (Apple Internal).', true],
|
||||
['System Integrity Protection status: disabled (Apple Internal).', false]
|
||||
])('reads "%s" as %s', (statusOutput, expected) => {
|
||||
expect(parseSipEnabled(statusOutput)).toBe(expected)
|
||||
})
|
||||
|
||||
it('only reads the status field, not the word enabled elsewhere in the output', () => {
|
||||
expect(
|
||||
parseSipEnabled('System Integrity Protection status: disabled.\nKernel Extensions: enabled')
|
||||
).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('SIP blocking message', () => {
|
||||
it('names the prerequisite and the next action', () => {
|
||||
expect(SIP_ENABLED_ERROR).toContain('SIP')
|
||||
expect(SIP_ENABLED_ERROR).toMatch(/关闭 SIP|手动粘贴/)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user