fix: 更新getXorKey方法以改进密钥提取逻辑并添加PNG支持

This commit is contained in:
XiiTang
2026-01-12 10:48:34 +08:00
parent 895249940c
commit cfd7635323

View File

@@ -695,33 +695,41 @@ export class KeyService {
} }
private getXorKey(templateFiles: string[]): number | null { private getXorKey(templateFiles: string[]): number | null {
const counts = new Map<string, number>() const counts = new Map<number, number>()
const tailSignatures = [
Buffer.from([0xFF, 0xD9]),
Buffer.from([0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82])
]
for (const file of templateFiles) { for (const file of templateFiles) {
try { try {
const bytes = readFileSync(file) const bytes = readFileSync(file)
if (bytes.length < 2) continue for (const signature of tailSignatures) {
const x = bytes[bytes.length - 2] if (bytes.length < signature.length) continue
const y = bytes[bytes.length - 1] const tail = bytes.subarray(bytes.length - signature.length)
const key = `${x}_${y}` const xorKey = tail[0] ^ signature[0]
counts.set(key, (counts.get(key) ?? 0) + 1) 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 { } } catch { }
} }
if (!counts.size) return null if (!counts.size) return null
let mostKey = '' let bestKey: number | null = null
let mostCount = 0 let bestCount = 0
for (const [key, count] of counts) { for (const [key, count] of counts) {
if (count > mostCount) { if (count > bestCount) {
mostCount = count bestCount = count
mostKey = key bestKey = key
} }
} }
if (!mostKey) return null return bestKey
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
} }
private getCiphertextFromTemplate(templateFiles: string[]): Buffer | null { private getCiphertextFromTemplate(templateFiles: string[]): Buffer | null {
@@ -766,7 +774,17 @@ export class KeyService {
const decipher = crypto.createDecipheriv('aes-128-ecb', key, null) const decipher = crypto.createDecipheriv('aes-128-ecb', key, null)
decipher.setAutoPadding(false) decipher.setAutoPadding(false)
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]) 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 { } catch {
return false return false
} }