Created
March 21, 2023 01:22
-
-
Save NtTestAlert/3a9d8ee9f92376651f56f331e0ba052b to your computer and use it in GitHub Desktop.
IntelliJ Forgotten master key
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @ts-expect-error | |
import * as dpapi from 'win-dpapi'; | |
import crypto from 'node:crypto'; | |
import fs from 'node:fs/promises'; | |
function rot13(txt:string) { | |
return txt.replace(/[a-z]/gi, c => | |
"NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm" | |
[ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".indexOf(c) ] ); | |
} | |
const builtInEncryptionKey = Buffer.from(rot13('HUWirUxtD29hMzyaVSAyLj=='), 'base64'); | |
function decryptAes(encrypted: Buffer) { | |
const ivLen = encrypted.readUInt32BE(); | |
const iv = encrypted.slice(4, ivLen + 4); | |
const data = encrypted.slice(ivLen + 4); | |
const decipher = crypto.createDecipheriv( | |
'aes-128-cbc', | |
builtInEncryptionKey, | |
iv, | |
); | |
return decipher.update(data, undefined, 'utf8') + decipher.final('utf8'); | |
} | |
function decryptSecret(secret: string) { | |
const secretBin = Buffer.from(secret, 'base64'); | |
return dpapi.unprotectData(secretBin, null, 'LocalMachine') as Buffer; | |
} | |
async function getDirectories(path: string) { | |
const found = []; | |
for (const file of await fs.readdir(path)) { | |
if ((await fs.stat(`${path}${file}`)).isDirectory()) | |
found.push(`${path}${file}`); | |
} | |
return found; | |
} | |
async function fileExists(filename: string) { | |
try { | |
await fs.access(filename); | |
return true; | |
} catch (err: any) { | |
if (err.code === 'ENOENT') { | |
return 'File does not exist'; | |
} | |
return `Error reading file: ${err.code}`; | |
} | |
} | |
const appDir = `${process.env.APPDATA}\\JetBrains\\`; | |
getDirectories(appDir).then(async (apps) => { | |
for (const app of apps) { | |
if (app.endsWith('consentOptions')) continue; | |
const appName = app.slice(appDir.length); | |
const exists = await fileExists(`${app}\\c.pwd`); | |
if (exists !== true) { | |
console.error(`${appName}: c.pwd does not exist : ${exists}`); | |
continue; | |
} | |
let secret = ''; | |
try { | |
const fileData = await fs.readFile(`${app}\\c.pwd`, 'utf8'); | |
const metaData = Object.fromEntries( | |
fileData | |
.split('\n') | |
.map((line) => line.split(':').map((x) => x.trim())), | |
); | |
if (metaData.encryption !== 'CRYPT_32') { | |
console.error( | |
`${appName}: unknown encryption type : ${metaData.encryption}`, | |
); | |
continue; | |
} | |
secret = metaData.value.split(' ')[1]; | |
} catch (err) { | |
console.error(`${appName}: Error reading c.pwd`, err); | |
continue; | |
} | |
try { | |
console.log(`${appName} decrypted : ${decryptAes(decryptSecret(secret))}`); | |
} catch (err) { | |
console.error(`${appName}: Error decrypting secret`, err); | |
} | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment