mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 15:25:50 +00:00
fix: 图片密钥内存扫描通过子进程调用解决 task_for_pid 权限问题
Electron 进程缺少 com.apple.security.cs.debugger entitlement, 导致 ScanMemoryForImageKey 中的 task_for_pid 调用失败(kr=5)。 新增 image_scan_helper 子进程包装程序(与 xkey_helper 方案一致): - 新建 resources/image_scan_helper.c:dlopen libwx_key.dylib 并调用 ScanMemoryForImageKey,通过 JSON stdout 返回结果 - 新建 resources/image_scan_entitlements.plist:包含 debugger 和 allow-unsigned-executable-memory entitlements - 编译为 universal binary(x86_64 + arm64)并 ad-hoc 签名 - 修改 keyServiceMac.ts _scanMemoryForAesKey():优先 spawn image_scan_helper 子进程,失败时 fallback 到直接调 dylib Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -43,6 +43,26 @@ export class KeyServiceMac {
|
||||
throw new Error('xkey_helper not found')
|
||||
}
|
||||
|
||||
private getImageScanHelperPath(): string {
|
||||
const isPackaged = app.isPackaged
|
||||
const candidates: string[] = []
|
||||
|
||||
if (isPackaged) {
|
||||
candidates.push(join(process.resourcesPath, 'resources', 'image_scan_helper'))
|
||||
candidates.push(join(process.resourcesPath, 'image_scan_helper'))
|
||||
} else {
|
||||
const cwd = process.cwd()
|
||||
candidates.push(join(cwd, 'resources', 'image_scan_helper'))
|
||||
candidates.push(join(app.getAppPath(), 'resources', 'image_scan_helper'))
|
||||
}
|
||||
|
||||
for (const path of candidates) {
|
||||
if (existsSync(path)) return path
|
||||
}
|
||||
|
||||
throw new Error('image_scan_helper not found')
|
||||
}
|
||||
|
||||
private getDylibPath(): string {
|
||||
const isPackaged = app.isPackaged
|
||||
const candidates: string[] = []
|
||||
@@ -463,6 +483,36 @@ export class KeyServiceMac {
|
||||
|
||||
private async _scanMemoryForAesKey(pid: number, ciphertext: Buffer): Promise<string | null> {
|
||||
const ciphertextHex = ciphertext.toString('hex')
|
||||
|
||||
// 优先通过 image_scan_helper 子进程调用(有 debugger entitlement)
|
||||
try {
|
||||
const helperPath = this.getImageScanHelperPath()
|
||||
const result = await new Promise<string | null>((resolve, reject) => {
|
||||
const child = spawn(helperPath, [String(pid), ciphertextHex], { stdio: ['ignore', 'pipe', 'pipe'] })
|
||||
let stdout = ''
|
||||
child.stdout.on('data', (chunk: Buffer) => { stdout += chunk.toString() })
|
||||
child.stderr.on('data', (chunk: Buffer) => { console.log('[image_scan_helper]', chunk.toString().trim()) })
|
||||
child.on('error', reject)
|
||||
child.on('close', () => {
|
||||
try {
|
||||
const lines = stdout.split(/\r?\n/).map(x => x.trim()).filter(Boolean)
|
||||
const last = lines[lines.length - 1]
|
||||
if (!last) { resolve(null); return }
|
||||
const payload = JSON.parse(last)
|
||||
resolve(payload?.success && payload?.aesKey ? payload.aesKey : null)
|
||||
} catch {
|
||||
resolve(null)
|
||||
}
|
||||
})
|
||||
setTimeout(() => { try { child.kill('SIGTERM') } catch {} }, 30_000)
|
||||
})
|
||||
return result
|
||||
} catch (e: any) {
|
||||
console.warn('[KeyServiceMac] image_scan_helper unavailable, fallback to dylib:', e?.message)
|
||||
}
|
||||
|
||||
// fallback: 直接调 dylib(Electron 进程可能没有 task_for_pid 权限)
|
||||
if (!this.initialized) await this.initialize()
|
||||
const aesKey = this.ScanMemoryForImageKey(pid, ciphertextHex)
|
||||
return aesKey || null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user