From cfd76353232e90c59fa7a950c5e044d32960994b Mon Sep 17 00:00:00 2001 From: XiiTang Date: Mon, 12 Jan 2026 10:48:34 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=9B=B4=E6=96=B0getXorKey=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E4=BB=A5=E6=94=B9=E8=BF=9B=E5=AF=86=E9=92=A5=E6=8F=90?= =?UTF-8?q?=E5=8F=96=E9=80=BB=E8=BE=91=E5=B9=B6=E6=B7=BB=E5=8A=A0PNG?= =?UTF-8?q?=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- electron/services/keyService.ts | 56 ++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/electron/services/keyService.ts b/electron/services/keyService.ts index 971a79f..d78edbb 100644 --- a/electron/services/keyService.ts +++ b/electron/services/keyService.ts @@ -695,33 +695,41 @@ export class KeyService { } private getXorKey(templateFiles: string[]): number | null { - const counts = new Map() + const counts = new Map() + const tailSignatures = [ + Buffer.from([0xFF, 0xD9]), + Buffer.from([0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82]) + ] for (const file of templateFiles) { try { const bytes = readFileSync(file) - if (bytes.length < 2) continue - const x = bytes[bytes.length - 2] - const y = bytes[bytes.length - 1] - const key = `${x}_${y}` - counts.set(key, (counts.get(key) ?? 0) + 1) + for (const signature of tailSignatures) { + if (bytes.length < signature.length) continue + const tail = bytes.subarray(bytes.length - signature.length) + const xorKey = tail[0] ^ signature[0] + let valid = true + for (let i = 1; i < signature.length; i++) { + if ((tail[i] ^ xorKey) !== signature[i]) { + valid = false + break + } + } + if (valid) { + counts.set(xorKey, (counts.get(xorKey) ?? 0) + 1) + } + } } catch { } } if (!counts.size) return null - let mostKey = '' - let mostCount = 0 + let bestKey: number | null = null + let bestCount = 0 for (const [key, count] of counts) { - if (count > mostCount) { - mostCount = count - mostKey = key + if (count > bestCount) { + bestCount = count + bestKey = key } } - if (!mostKey) return null - const [xStr, yStr] = mostKey.split('_') - const x = Number(xStr) - const y = Number(yStr) - const xorKey = x ^ 0xFF - const check = y ^ 0xD9 - return xorKey === check ? xorKey : null + return bestKey } private getCiphertextFromTemplate(templateFiles: string[]): Buffer | null { @@ -766,7 +774,17 @@ export class KeyService { const decipher = crypto.createDecipheriv('aes-128-ecb', key, null) decipher.setAutoPadding(false) const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]) - return decrypted[0] === 0xff && decrypted[1] === 0xd8 && decrypted[2] === 0xff + const isJpeg = decrypted.length >= 3 && decrypted[0] === 0xff && decrypted[1] === 0xd8 && decrypted[2] === 0xff + const isPng = decrypted.length >= 8 && + decrypted[0] === 0x89 && + decrypted[1] === 0x50 && + decrypted[2] === 0x4e && + decrypted[3] === 0x47 && + decrypted[4] === 0x0d && + decrypted[5] === 0x0a && + decrypted[6] === 0x1a && + decrypted[7] === 0x0a + return isJpeg || isPng } catch { return false }