mirror of
https://wget.la/https://github.com/Wxw-Gu/WechatExplorer
synced 2026-10-04 03:01:42 +08:00
fix: preserve legacy macOS key capture
This commit is contained in:
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -1 +1 @@
|
|||||||
f1bbd88584075c0e6d3487357a06424949de26d7e6dcad803d210aab83b0cbda xkey_helper
|
f1bbd88584075c0e6d3487357a06424949de26d7e6dcad803d210aab83b0cbda xkey_helper_4_1_13
|
||||||
+48
-11
@@ -6,6 +6,7 @@ import { promisify } from 'util'
|
|||||||
import { isValidDatabaseKey } from './database-key-store'
|
import { isValidDatabaseKey } from './database-key-store'
|
||||||
import crypto from 'crypto'
|
import crypto from 'crypto'
|
||||||
import { findResource, getResourceCandidates } from './resource-paths'
|
import { findResource, getResourceCandidates } from './resource-paths'
|
||||||
|
import { detectWechatVersion } from './services/connection-diagnostics'
|
||||||
|
|
||||||
const execFileAsync = promisify(execFile)
|
const execFileAsync = promisify(execFile)
|
||||||
|
|
||||||
@@ -24,10 +25,42 @@ export interface ImageKeyResult {
|
|||||||
error?: string
|
error?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type XkeyHelperMode = 'legacy' | 'wechat-4.1.13'
|
||||||
|
|
||||||
|
export function resolveXkeyHelperMode(wechatVersion: string): XkeyHelperMode {
|
||||||
|
return /^4\.1\.13(?:\.|$)/.test(wechatVersion.trim()) ? 'wechat-4.1.13' : 'legacy'
|
||||||
|
}
|
||||||
|
|
||||||
export function buildXkeyHelperArguments(pid: number, timeoutMs: number): string[] {
|
export function buildXkeyHelperArguments(pid: number, timeoutMs: number): string[] {
|
||||||
return [String(pid), String(timeoutMs), '--profile', 'wechat-4.1.13', '--account']
|
return [String(pid), String(timeoutMs), '--profile', 'wechat-4.1.13', '--account']
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function buildAppleSiliconXkeyInvocation(
|
||||||
|
wechatVersion: string,
|
||||||
|
pid: number,
|
||||||
|
timeoutMs: number
|
||||||
|
): {
|
||||||
|
mode: XkeyHelperMode
|
||||||
|
resourceName: string
|
||||||
|
args: string[]
|
||||||
|
waitMs: number
|
||||||
|
timeoutSeconds: number
|
||||||
|
execTimeoutMs: number
|
||||||
|
} {
|
||||||
|
const mode = resolveXkeyHelperMode(wechatVersion)
|
||||||
|
const isWechat413 = mode === 'wechat-4.1.13'
|
||||||
|
const waitMs = Math.max(isWechat413 ? 120_000 : 30_000, timeoutMs)
|
||||||
|
const timeoutSeconds = Math.ceil(waitMs / 1000) + (isWechat413 ? 10 : 30)
|
||||||
|
return {
|
||||||
|
mode,
|
||||||
|
resourceName: isWechat413 ? 'xkey_helper_4_1_13' : 'xkey_helper',
|
||||||
|
args: isWechat413 ? buildXkeyHelperArguments(pid, waitMs) : [String(pid), String(waitMs)],
|
||||||
|
waitMs,
|
||||||
|
timeoutSeconds,
|
||||||
|
execTimeoutMs: isWechat413 ? timeoutSeconds * 1000 + 5_000 : waitMs + 20_000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function mapXkeyHelperFailure(
|
export function mapXkeyHelperFailure(
|
||||||
rawError: string,
|
rawError: string,
|
||||||
fallbackCode = 'HELPER_RESULT_INVALID'
|
fallbackCode = 'HELPER_RESULT_INVALID'
|
||||||
@@ -260,11 +293,11 @@ export class KeyServiceMac {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getHelperPath(): string {
|
private getHelperPath(resourceName = 'xkey_helper'): string {
|
||||||
const helperPath = findResource('xkey_helper')
|
const helperPath = findResource(resourceName)
|
||||||
if (!helperPath) {
|
if (!helperPath) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`找不到 xkey_helper(已检查:${getResourceCandidates('xkey_helper').join(';')})`
|
`找不到 ${resourceName}(已检查:${getResourceCandidates(resourceName).join(';')})`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return helperPath
|
return helperPath
|
||||||
@@ -326,17 +359,17 @@ export class KeyServiceMac {
|
|||||||
onStatus?.(result.success ? '密钥获取成功' : '密钥获取失败')
|
onStatus?.(result.success ? '密钥获取成功' : '密钥获取失败')
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
const wechatVersion = await detectWechatVersion()
|
||||||
onStatus?.('正在查找微信进程...')
|
onStatus?.('正在查找微信进程...')
|
||||||
const pid = await this.getWeChatPid()
|
const pid = await this.getWeChatPid()
|
||||||
const helperPath = this.getHelperPath()
|
const invocation = buildAppleSiliconXkeyInvocation(wechatVersion, pid, timeoutMs)
|
||||||
const waitMs = Math.max(120_000, timeoutMs)
|
const isWechat413 = invocation.mode === 'wechat-4.1.13'
|
||||||
const timeoutSeconds = Math.ceil(waitMs / 1000) + 10
|
const helperPath = this.getHelperPath(invocation.resourceName)
|
||||||
const helperArguments = buildXkeyHelperArguments(pid, waitMs)
|
|
||||||
onStatus?.('正在请求管理员授权...')
|
onStatus?.('正在请求管理员授权...')
|
||||||
const scriptLines = [
|
const scriptLines = [
|
||||||
`set helperPath to ${JSON.stringify(helperPath)}`,
|
`set helperPath to ${JSON.stringify(helperPath)}`,
|
||||||
`set cmd to quoted form of helperPath & " ${helperArguments.join(' ')}"`,
|
`set cmd to quoted form of helperPath & " ${invocation.args.join(' ')}"`,
|
||||||
`set timeoutSec to ${timeoutSeconds}`,
|
`set timeoutSec to ${invocation.timeoutSeconds}`,
|
||||||
'try',
|
'try',
|
||||||
'with timeout of timeoutSec seconds',
|
'with timeout of timeoutSec seconds',
|
||||||
'set outText to do shell script cmd with administrator privileges',
|
'set outText to do shell script cmd with administrator privileges',
|
||||||
@@ -346,11 +379,15 @@ export class KeyServiceMac {
|
|||||||
'return "ERR::" & errNum & "::" & errMsg',
|
'return "ERR::" & errNum & "::" & errMsg',
|
||||||
'end try'
|
'end try'
|
||||||
]
|
]
|
||||||
onStatus?.('授权后请在微信登录界面点击“登录”,已有登录凭据时通常不需要扫码')
|
onStatus?.(
|
||||||
|
isWechat413
|
||||||
|
? '授权后请在微信登录界面点击“登录”,已有登录凭据时通常不需要扫码'
|
||||||
|
: '授权后 需要在微信登录界面 点击登录微信'
|
||||||
|
)
|
||||||
const { stdout } = await execFileAsync(
|
const { stdout } = await execFileAsync(
|
||||||
'/usr/bin/osascript',
|
'/usr/bin/osascript',
|
||||||
scriptLines.flatMap((line) => ['-e', line]),
|
scriptLines.flatMap((line) => ['-e', line]),
|
||||||
{ timeout: timeoutSeconds * 1000 + 5_000 }
|
{ timeout: invocation.execTimeoutMs }
|
||||||
)
|
)
|
||||||
const output = String(stdout).trim()
|
const output = String(stdout).trim()
|
||||||
if (output.startsWith('ERR::-128')) {
|
if (output.startsWith('ERR::-128')) {
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ vi.mock('electron', () => ({
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
buildAppleSiliconXkeyInvocation,
|
||||||
buildXkeyHelperArguments,
|
buildXkeyHelperArguments,
|
||||||
mapXkeyHelperFailure,
|
mapXkeyHelperFailure,
|
||||||
parseXkeyHelperOutput
|
parseXkeyHelperOutput,
|
||||||
|
resolveXkeyHelperMode
|
||||||
} from '../../src/main/key-service-mac'
|
} from '../../src/main/key-service-mac'
|
||||||
|
|
||||||
describe('parseXkeyHelperOutput', () => {
|
describe('parseXkeyHelperOutput', () => {
|
||||||
@@ -71,7 +73,19 @@ describe('parseXkeyHelperOutput', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('uses the verified 4.1.13 account-key capture contract', () => {
|
it.each([
|
||||||
|
['4.1.8', 'legacy'],
|
||||||
|
['4.1.9.57', 'legacy'],
|
||||||
|
['4.1.10', 'legacy'],
|
||||||
|
['4.1.13', 'wechat-4.1.13'],
|
||||||
|
['4.1.13.91', 'wechat-4.1.13'],
|
||||||
|
['4.1.130', 'legacy'],
|
||||||
|
['未检测到', 'legacy']
|
||||||
|
])('selects the helper mode for WeChat %s', (version, mode) => {
|
||||||
|
expect(resolveXkeyHelperMode(version)).toBe(mode)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('builds the verified 4.1.13 account-key capture contract', () => {
|
||||||
expect(buildXkeyHelperArguments(60037, 120_000)).toEqual([
|
expect(buildXkeyHelperArguments(60037, 120_000)).toEqual([
|
||||||
'60037',
|
'60037',
|
||||||
'120000',
|
'120000',
|
||||||
@@ -81,6 +95,31 @@ describe('parseXkeyHelperOutput', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('uses the new helper only for WeChat 4.1.13', () => {
|
||||||
|
expect(buildAppleSiliconXkeyInvocation('4.1.13.91', 60037, 60_000)).toEqual({
|
||||||
|
mode: 'wechat-4.1.13',
|
||||||
|
resourceName: 'xkey_helper_4_1_13',
|
||||||
|
args: ['60037', '120000', '--profile', 'wechat-4.1.13', '--account'],
|
||||||
|
waitMs: 120_000,
|
||||||
|
timeoutSeconds: 130,
|
||||||
|
execTimeoutMs: 135_000
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it.each(['4.1.8', '4.1.9.57', '4.1.10', '未检测到'])(
|
||||||
|
'preserves the legacy helper invocation for WeChat %s',
|
||||||
|
(version) => {
|
||||||
|
expect(buildAppleSiliconXkeyInvocation(version, 60037, 60_000)).toEqual({
|
||||||
|
mode: 'legacy',
|
||||||
|
resourceName: 'xkey_helper',
|
||||||
|
args: ['60037', '60000'],
|
||||||
|
waitMs: 60_000,
|
||||||
|
timeoutSeconds: 90,
|
||||||
|
execTimeoutMs: 80_000
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
it('extracts a helper error embedded in AppleScript diagnostics', () => {
|
it('extracts a helper error embedded in AppleScript diagnostics', () => {
|
||||||
expect(
|
expect(
|
||||||
mapXkeyHelperFailure(
|
mapXkeyHelperFailure(
|
||||||
|
|||||||
Reference in New Issue
Block a user