├── README.md ├── RegistryStrikesBack.sln └── RegistryStrikesBack ├── Program.cs ├── Properties └── AssemblyInfo.cs └── RegistryStrikesBack.csproj /README.md: -------------------------------------------------------------------------------- 1 | # RegistryStrikesBack 2 | 3 | RegistryStrikesBack allows a red team operator to export valid .reg files for portions of the Windows Registry via a .NET assembly that should run as a standard user. It can be useful in exfiltrating config files such as to support actions like are described in the "Segmentation Vault" article on the [MDSec Blog](https://www.mdsec.co.uk/knowledge-centre/insights/). 4 | 5 | ## Note 6 | 7 | This is not yet fully implemented, its a best effort and it does not yet support all datatypes and may lead to some unexpected results. However, it did function for the use cases required. 8 | 9 | ## Usage 10 | 11 | ``` 12 | RegistryStrikesBack.exe [output file path] 13 | ``` 14 | 15 | Export OneDrive Registry Keys to file in .reg format 16 | 17 | ``` 18 | RegistryStrikesBack.exe HKCU\Software\Microsoft\OneDrive C:\ProgramData\OneDriveBusiness.reg 19 | ``` 20 | 21 | Export OneDrive Registry Keys to console in .reg format 22 | 23 | ``` 24 | RegistryStrikesBack.exe HKCU\Software\Microsoft\OneDrive 25 | ``` 26 | 27 | ## Author 28 | * **David Middlehurst, MDSec ActiveBreach** - Twitter- [@dtmsecurity](https://twitter.com/dtmsecurity) 29 | 30 | ## Acknowledgments 31 | * PowerShell Implementation https://franckrichard.blogspot.com/2010/12/generate-reg-regedit-export-to-file.html -------------------------------------------------------------------------------- /RegistryStrikesBack.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30309.148 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryStrikesBack", "RegistryStrikesBack\RegistryStrikesBack.csproj", "{90EBD469-D780-4431-9BD8-014B00057665}" 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 | {90EBD469-D780-4431-9BD8-014B00057665}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {90EBD469-D780-4431-9BD8-014B00057665}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {90EBD469-D780-4431-9BD8-014B00057665}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {90EBD469-D780-4431-9BD8-014B00057665}.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 = {8A482F53-E269-4971-AA20-77D5754434FD} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /RegistryStrikesBack/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Win32; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | // This project partly ported from ideas in this PowerShell script: 7 | // https://franckrichard.blogspot.com/2010/12/generate-reg-regedit-export-to-file.html 8 | 9 | namespace RegistryStrikesBack 10 | { 11 | class Program 12 | { 13 | public static string output = "Windows Registry Editor Version 5.00\r\n\r\n"; 14 | public static string outputLocation = "Console"; 15 | 16 | private static string transformStringReg(string input) 17 | { 18 | input = input.Replace("\\", "\\"); 19 | input = input.Replace('"', '\"'); 20 | return input; 21 | } 22 | 23 | private static string transformBinReg(byte[] input, int len, bool multi) 24 | { 25 | string outputLines = ""; 26 | 27 | string[] hex_values_array = BitConverter.ToString(input).ToLower().Split('-'); 28 | List hex_values = new List(hex_values_array); 29 | 30 | int totalValues = hex_values.Count; 31 | 32 | int diff = 25 - (int)Math.Ceiling(Decimal.Divide(len, 3)); 33 | 34 | if (totalValues <= diff) 35 | { 36 | outputLines += String.Join(",", hex_values); 37 | } 38 | else 39 | { 40 | outputLines += String.Join(",", hex_values.Take(diff)) + ",\\\r\n"; 41 | hex_values.RemoveRange(0, diff); 42 | while (hex_values.Count > 0) 43 | { 44 | if (hex_values.Count > 25) 45 | { 46 | outputLines += String.Join(",", hex_values.Take(25)) + ",\\\r\n"; 47 | hex_values.RemoveRange(0, 25); 48 | } 49 | else 50 | { 51 | outputLines += String.Join(",", hex_values.Take(hex_values.Count)); 52 | hex_values.RemoveRange(0, hex_values.Count); 53 | } 54 | } 55 | } 56 | return outputLines; 57 | } 58 | 59 | private static byte[] Combine(params byte[][] arrays) 60 | { 61 | byte[] rv = new byte[arrays.Sum(a => a.Length)]; 62 | int offset = 0; 63 | foreach (byte[] array in arrays) 64 | { 65 | System.Buffer.BlockCopy(array, 0, rv, offset, array.Length); 66 | offset += array.Length; 67 | } 68 | return rv; 69 | } 70 | 71 | private static void processValueNames(RegistryKey Key) 72 | { 73 | output += "[" + Key.Name + "]\n"; 74 | string[] valuenames = Key.GetValueNames(); 75 | if (valuenames == null || valuenames.Length <= 0) 76 | { 77 | return; 78 | } 79 | foreach (string valuename in valuenames) 80 | { 81 | object obj = Key.GetValue(valuename); 82 | if (obj != null) 83 | { 84 | 85 | string type = obj.GetType().Name; 86 | RegistryValueKind valuekind = Key.GetValueKind(valuename); 87 | 88 | 89 | int len = 0; 90 | switch (valuekind.ToString()) 91 | { 92 | case "String": 93 | output += String.Format("\"{0}\"=\"{1}\"\r\n", transformStringReg(valuename), transformStringReg(obj.ToString())); 94 | break; 95 | case "ExpandString": 96 | object tmpvalues = Key.GetValue(valuename, "error", RegistryValueOptions.DoNotExpandEnvironmentNames); 97 | byte[] values = System.Text.Encoding.Unicode.GetBytes(tmpvalues.ToString() + "*"); 98 | 99 | len = String.Format("\"{0}\"=hex(2):", transformStringReg(valuename)).Length; 100 | output += String.Format("\"{0}\"=hex(2):{1}\r\n", transformStringReg(valuename), transformBinReg(values, len, true)); 101 | break; 102 | case "MultiString": 103 | string[] stringvalues = (string[])obj; 104 | 105 | byte[] totalbytes = new byte[0]; 106 | foreach (string stringvalue in stringvalues) 107 | { 108 | byte[] valuedata = System.Text.Encoding.Unicode.GetBytes(stringvalue + "*"); 109 | byte[] rv = new byte[totalbytes.Length + valuedata.Length]; 110 | System.Buffer.BlockCopy(totalbytes, 0, rv, 0, totalbytes.Length); 111 | System.Buffer.BlockCopy(valuedata, 0, rv, totalbytes.Length, valuedata.Length); 112 | totalbytes = rv; 113 | } 114 | len = String.Format("\"{0}\"=hex(7):", transformStringReg(valuename)).Length; 115 | output += String.Format("\"{0}\"=hex(7):{1}\r\n", transformStringReg(valuename), transformBinReg(totalbytes, len, true)); 116 | 117 | break; 118 | case "Binary": 119 | len = String.Format("\"{0}\"=hex:", transformStringReg(valuename)).Length; 120 | output += String.Format("\"{0}\"=hex:{1}\r\n", transformStringReg(valuename), transformBinReg((byte[])obj, len, false)); 121 | break; 122 | 123 | case "DWord": 124 | string value = String.Format("{0:x8}", (Int32)obj); 125 | output += String.Format("\"{0}\"=dword:{1}\r\n", transformStringReg(valuename), value); 126 | break; 127 | case "QWord": 128 | string qvalue = String.Format("{0:x16}", int.Parse(obj.ToString())); 129 | output += String.Format("\"{0}\"=hex(b):{1}\r\n", transformStringReg(valuename), qvalue.Substring(14, 2) + "," + qvalue.Substring(12, 2) + "," + qvalue.Substring(10, 2) + "," + qvalue.Substring(8, 2) + "," + qvalue.Substring(6, 2) + "," + qvalue.Substring(4, 2) + "," + qvalue.Substring(2, 2) + "," + qvalue.Substring(0, 2)); 130 | break; 131 | default: 132 | break; 133 | } 134 | 135 | if (outputLocation == "Console") 136 | { 137 | Console.Write(output); 138 | } 139 | else 140 | { 141 | System.IO.File.AppendAllText(outputLocation, output); 142 | } 143 | output = ""; 144 | } 145 | } 146 | output += "\r\n"; 147 | } 148 | 149 | public static void OutputRegKey(RegistryKey Key) 150 | { 151 | try 152 | { 153 | string[] subkeynames = Key.GetSubKeyNames(); 154 | if (subkeynames == null || subkeynames.Length <= 0) 155 | { 156 | processValueNames(Key); 157 | return; 158 | } 159 | foreach (string keyname in subkeynames) 160 | { 161 | using (RegistryKey key2 = Key.OpenSubKey(keyname)) 162 | OutputRegKey(key2); 163 | } 164 | processValueNames(Key); 165 | } 166 | catch (Exception e) 167 | { 168 | } 169 | } 170 | static void Main(string[] args) 171 | { 172 | if (args.Length == 2) 173 | { 174 | outputLocation = args[1]; 175 | Console.WriteLine("[*] Writing Output to {0}", outputLocation); 176 | } 177 | else if (args.Length == 1) 178 | { 179 | outputLocation = "Console"; 180 | } 181 | else 182 | { 183 | Console.WriteLine("RegistryStrikesBack.exe [output file path]"); 184 | return; 185 | } 186 | 187 | string key = args[0]; 188 | 189 | RegistryKey reg = Registry.CurrentUser; 190 | if (key.StartsWith("HKCU\\")) 191 | { 192 | key = key.Replace("HKCU\\", ""); 193 | } 194 | else if (key.StartsWith("HKLM\\")) 195 | { 196 | reg = Registry.LocalMachine; 197 | key = key.Replace("HKLM\\", ""); 198 | } 199 | else if (key.StartsWith("HKCR\\")) 200 | { 201 | reg = Registry.ClassesRoot; 202 | key = key.Replace("HKCR\\", ""); 203 | } 204 | else if (key.StartsWith("HKU\\")) 205 | { 206 | reg = Registry.Users; 207 | key = key.Replace("HKU\\", ""); 208 | } 209 | else if (key.StartsWith("HKCC\\")) 210 | { 211 | reg = Registry.CurrentConfig; 212 | key = key.Replace("HKCC\\", ""); 213 | } 214 | 215 | RegistryKey RegKey = reg.OpenSubKey(key); 216 | OutputRegKey(RegKey); 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /RegistryStrikesBack/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("RegistryStrikesBack")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("RegistryStrikesBack")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 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("90ebd469-d780-4431-9bd8-014b00057665")] 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 | -------------------------------------------------------------------------------- /RegistryStrikesBack/RegistryStrikesBack.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {90EBD469-D780-4431-9BD8-014B00057665} 8 | Exe 9 | RegistryStrikesBack 10 | RegistryStrikesBack 11 | v4.0 12 | 512 13 | true 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | --------------------------------------------------------------------------------