private static String serviceRegistry(HttpRequest req, Socket sock) { if (req.UrlParameters.ContainsKey("hive") && req.UrlParameters.ContainsKey("path")) { RegistryHive hk = (RegistryHive)int.Parse(req.UrlParameters["hive"], NumberStyles.AllowHexSpecifier); String path = req.UrlParameters["path"].TrimEnd('\\'); if (req.UrlParameters.ContainsKey("download")) { // Build a .REG file (named based on the reg key) and upload it to the user String file = RegTools.BuildRegFile(hk, path); if (null != file) { HttpResponse.Redirect( sock, "/Filesystem?path=" + Path.GetDirectoryName(file) + "&download=" + WebUtility.UrlEncode(Path.GetFileName(file))); } return(null); } // Else, load the requested registry key String[] subkeys; ValueInfo[] values; if (!NativeRegistry.GetSubKeyNames(hk, path, out subkeys)) { // An error occurred! return("An error occurred while getting the registry sub-keys! The Win32 error code was " + NativeRegistry.GetError()); } if (!NativeRegistry.GetValues(hk, path, out values)) { return("An error occurred while getting the registry values! The Win32 error code was " + NativeRegistry.GetError()); } // Build the HTML body StringBuilder build = new StringBuilder(); if (!String.IsNullOrWhiteSpace(path)) { build.AppendLine("<h4><a href=\"/Registry?hive=" + req.UrlParameters["hive"] + "&path=" + (path.Contains('\\') ? path.Substring(0, path.LastIndexOf('\\')) : String.Empty) + "\">Go to parent key</a></h4>"); } if (subkeys != null && subkeys.Length > 0) { build.AppendLine("<table><tr><th>Keys</th></tr>"); foreach (String key in subkeys) { build.Append("<tr><td><a href=\"/Registry?hive=").Append(((uint)hk).ToString("X")) .Append("&path="); if (!String.IsNullOrEmpty(path)) { build.Append(WebUtility.UrlEncode(path + "\\")); } build.Append(WebUtility.UrlEncode(key)).Append("\">") .Append(key).AppendLine("</a></td></tr>"); } build.AppendLine("</table>"); } else { build.AppendLine("<h4>This key has no subkeys.</h4>"); } if (values != null && values.Length > 0) { build.AppendLine("<table border=\"1\"><tr><th>Values</th><th>Type</th><th>Size</th><th>Data</th></tr>"); foreach (ValueInfo info in values) { String name = String.IsNullOrEmpty(info.Name) ? "<i>default</i>" : info.Name; // Create name cell build.Append("<tr><td>").Append(name).Append("</td><td>") // Create type cell .Append(info.Type.ToString("G")).Append(" (").Append(info.Type.ToString("D")).Append(")</td><td>") // Create length cell .Append(info.Length).AppendLine("</td><td>"); if (0 == info.Length) { // No data! build.Append("<i>NULL</i>"); } else { switch (info.Type) { case RegistryType.String: case RegistryType.VariableString: { // Make sure it's really a string; display binary otherwise if (0 != (info.Length % 2)) { byte[] binary; RegistryType t; if (NativeRegistry.QueryValue(hk, path, info.Name, out t, out binary)) { buildHexTable(build, binary); } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } // Handle REG_SZ and REG_EXPAND_SZ String data; if (NativeRegistry.ReadString(hk, path, info.Name, out data)) { if (String.IsNullOrEmpty(data)) { build.Append("<i>EMPTY STRING</i>"); } else { build.Append(WebUtility.HtmlEncode(data)); } } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } case RegistryType.Integer: { // Make sure it's really a DWORD; display binary otherwise if (info.Length != 4) { byte[] binary; RegistryType t; if (NativeRegistry.QueryValue(hk, path, info.Name, out t, out binary)) { buildHexTable(build, binary); } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } // Handle REG_DWORD uint data; if (NativeRegistry.ReadDWORD(hk, path, info.Name, out data)) { build.Append(data).AppendFormat(" (0x{0:X8})", data); } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } case RegistryType.Long: { // Make sure it's really a QWORD; display binary otherwise if (info.Length != 8) { byte[] binary; RegistryType t; if (NativeRegistry.QueryValue(hk, path, info.Name, out t, out binary)) { buildHexTable(build, binary); } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } // Handle REG_QWORD ulong data; if (NativeRegistry.ReadQWORD(hk, path, info.Name, out data)) { try { DateTime date = DateTime.FromFileTime((long)data); build.Append(data).AppendFormat(" (0x{0:X16}) (", data).Append(date.ToString()).Append(')'); } catch (ArgumentOutOfRangeException) { // It's not a date... build.Append(data).AppendFormat(" (0x{0:X16})", data); } } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } case RegistryType.MultiString: { // Make sure it's really a string; display binary otherwise if (0 != (info.Length % 2)) { // Odd number of bytes byte[] binary; RegistryType t; if (NativeRegistry.QueryValue(hk, path, info.Name, out t, out binary)) { buildHexTable(build, binary); } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } // Handle REG_MULTI_SZ String[] data; if (NativeRegistry.ReadMultiString(hk, path, info.Name, out data)) { if ((null == data) || (0 == data.Length)) { build.Append("<i>NO STRINGS</i>"); } else { if (String.IsNullOrEmpty(data[0])) { build.Append("<i>EMPTY STRING</i>"); } else { build.Append(WebUtility.HtmlEncode(data[0])); } for (int i = 1; i < data.Length; i++) { if (String.IsNullOrEmpty(data[i])) { build.Append("<br />\n<i>EMPTY STRING</i>"); } else { build.Append("<br />\n").Append(WebUtility.HtmlEncode(data[i])); } } } } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } case RegistryType.None: case RegistryType.Binary: { // Handle REG_BINARY switch (info.Length) { // Zero is taken care of above case 4: { // Treat it as a DWORD uint data; if (NativeRegistry.ReadDWORD(hk, path, info.Name, out data)) { build.Append(data).AppendFormat(" (0x{0:X8})", data); } else { byte[] binary; RegistryType t; if (NativeRegistry.QueryValue(hk, path, info.Name, out t, out binary)) { buildHexTable(build, binary); } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } } break; } case 8: { // Treat it as a QWORD ulong data; if (NativeRegistry.ReadQWORD(hk, path, info.Name, out data)) { try { DateTime date = DateTime.FromFileTime((long)data); build.Append(data).AppendFormat(" (0x{0:X16}) (", data).Append(date.ToString()).Append(')'); } catch (ArgumentOutOfRangeException) { // It's not a date... build.Append(data).AppendFormat(" (0x{0:X16})", data); } } else { byte[] binary; RegistryType t; if (NativeRegistry.QueryValue(hk, path, info.Name, out t, out binary)) { buildHexTable(build, binary); } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } } break; } default: { // Display as a binary hex sequence byte[] data; RegistryType type; if (NativeRegistry.QueryValue(hk, path, info.Name, out type, out data)) { buildHexTable(build, data); } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } } // End of info.length switch break; } default: { // Handle arbitrary value types byte[] data; RegistryType type; if (NativeRegistry.QueryValue(hk, path, info.Name, out type, out data)) { buildHexTable(build, data); } else { // Error reading data build.AppendFormat("<i>Error reading data: {0} ({0:X})</i>", NativeRegistry.GetError()); } break; } } // End of info.type switch build.AppendLine("</td></tr>"); } } build.AppendLine("</table>"); } else { build.AppendLine("<h4>This key contains no values.</h4>"); } return(build.ToString()); } else { // No request specified... return (@"Specify a registry key above, or jump to the following examples:<br /> <a href='/Registry?hive=80000002&path=SOFTWARE\Microsoft\DeviceReg\Install'>Dev-unlock info</a><br /> <a href='/Registry?hive=80000001&path='>Current User registry hive</a><br />"); } }
static void BuildRegRecurse(RegistryHive hive, String path, StreamWriter writer) { String[] subkeys; ValueInfo[] vals; // First, write this key writer.WriteLine("\r\n[" + new RegistryKey(hive, path).FullName + ']'); if (NativeRegistry.GetValues(hive, path, out vals)) { if (null != vals) { foreach (ValueInfo val in vals) { String name = String.IsNullOrEmpty(val.Name) ? "@" : '"' + val.Name + '"'; switch (val.Type) { case RegistryType.String: case RegistryType.VariableString: { String str; if (NativeRegistry.ReadString(hive, path, val.Name, out str)) { // Put a comment with what we think the string is writer.WriteLine(";" + name + "=\"" + str + '\"'); } else { // Explain the error writer.WriteLine(";Getting the string failed with error " + NativeRegistry.GetError()); } break; } case RegistryType.Integer: { uint i; if (NativeRegistry.ReadDWORD(hive, path, val.Name, out i)) { // Put a comment with what we think the integer is writer.WriteLine(";" + name + "=DWORD:" + i.ToString("X8") + " ;(" + i.ToString() + ')'); } else { // Explain the error writer.WriteLine(";Getting the DWORD failed with error " + NativeRegistry.GetError()); } break; } case RegistryType.MultiString: { String[] ms; if (NativeRegistry.ReadMultiString(hive, path, val.Name, out ms)) { // Put a comment with what we think the strings are writer.Write(";" + name + "="); foreach (String s in ms) { writer.Write("\\\r\n; \"" + s + '"'); } writer.WriteLine(); } else { // Explain the error writer.WriteLine(";Getting the multi-string failed with error " + NativeRegistry.GetError()); } break; } default: // Put a comment with what type it's supposed to be writer.WriteLine(";" + name + " has type " + val.Type.ToString("G")); break; } // Write the actual value in hex format byte[] buf; RegistryType t; if (!NativeRegistry.QueryValue(hive, path, val.Name, out t, out buf)) { // Explain the error and move on writer.WriteLine(";Querying value failed with error " + NativeRegistry.GetError()); continue; } writer.Write(name + "=hex(" + ((uint)t).ToString("x") + ((null != buf && buf.Length > 0) ? "):\\\r\n " : "):\r\n")); if (null != buf && buf.Length > 0) { for (int i = 0; i < buf.Length; i++) { writer.Write(buf[i].ToString("X2")); if ((i + 1) < buf.Length) { writer.Write(','); if (0xF == (i & 0xF)) { writer.Write("\\\r\n "); } } } writer.WriteLine(); } } } else { // No values; put a comment saying so writer.WriteLine("; This key contains no values, or values can't be read"); } } else { // Error while getting the values writer.WriteLine("; Failed to get the values of this key. Error " + NativeRegistry.GetError()); } // OK, we wrote the values (whew). Time for subkeys. if (NativeRegistry.GetSubKeyNames(hive, path, out subkeys)) { if (null != subkeys) { foreach (String sk in subkeys) { BuildRegRecurse(hive, (!String.IsNullOrEmpty(path) ? path + '\\' + sk : sk), writer); } } // Else no subkeys, no need to say anything about it } else { // Error getting subkeys writer.WriteLine("; Failed to get subkeys of this key. Error " + NativeRegistry.GetError()); } }