using System;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
using System.Security;
using System.IO;
using System.Text;
namespace RegSpyConsole
{
class RegSpyCOMInterop
{
//RegLocation will act as the mirror for the other keys
string RegLocation=@"Software\Vagmi\RegSpyInterop\";
//This is a global variable used to identify the above path and delete them
string PathToDelete;
[STAThread]
static void Main(string[] args)
{
string AssemblyPath="";
string RegFile="";
if(args.Length<2)
{
Console.WriteLine("Usage: RegSpyCOMInterop assembly.dll regfile.reg");
return;
}
AssemblyPath=args[0];
RegFile=args[1];
RegSpyCOMInterop rsObj=new RegSpyCOMInterop(AssemblyPath, RegFile);
}
public RegSpyCOMInterop(string AssemblyPath, string RegFile)
{
try
{
Assembly a=Assembly.LoadFrom(AssemblyPath);
RegistrationServices regServices=new RegistrationServices();
//map hives to registry keys
MapRegHives();
//Register assembly for COM interop
regServices.RegisterAssembly(a,AssemblyRegistrationFlags.SetCodeBase);
//Unmap hives
UnMapRegHives();
WriteToRegFile(RegFile);
}
catch(Exception e)
{
Console.WriteLine("Caught Exception : " + e.Message);
}
}
public void WriteToRegFile(string regfile)
{
RegistryKey r=Registry.LocalMachine.OpenSubKey(RegLocation,false);
PathToDelete=r.Name + "\\";
Process pr=new Process();
pr.StartInfo.FileName="regedit";
pr.StartInfo.Arguments=" /e " + regfile + " " + r.Name;
pr.Start();
pr.WaitForExit();
string line;
StreamReader reader=new StreamReader(regfile);
StreamWriter writer=new StreamWriter("TempFile.txt");
while((line=reader.ReadLine())!=null)
{
writer.WriteLine(processRegistryName(line));
}
reader.Close();
writer.Close();
File.Copy("TempFile.txt",regfile,true);
File.Delete("TempFile.txt");
r.Flush();
r.Close();
}
public String processRegistryName(string regname)
{
string newRegName="";
newRegName=regname.Replace(PathToDelete,"");
newRegName=newRegName.Replace("[" + PathToDelete.Substring(0,PathToDelete.Length-1) + "]","");
newRegName=newRegName.Replace("HKCR","HKEY_CLASS_ROOT");
newRegName=newRegName.Replace("HKCU","HKEY_CURRENT_USER");
newRegName=newRegName.Replace("HKLM","HKEY_LOCAL_MACHINE");
newRegName=newRegName.Replace("HKU","HKEY_USERS");
return newRegName;
}
//Functions to map registry hives. You need to add try/catch blocks
void MapRegHives()
{
MapRegHive(OverRideRegistry.HkeyClassesRoot,this.RegLocation+"HKCR");
MapRegHive(OverRideRegistry.HkeyCurrentUser,this.RegLocation+"HKCU");
MapRegHive(OverRideRegistry.HkeyUsers,this.RegLocation+"HKU");
MapRegHive(OverRideRegistry.HkeyLocalMachine,this.RegLocation+"HKLM");
}
void MapRegHive(UIntPtr key, string location)
{
Console.WriteLine("Mapping " + key + " to " + location);
IntPtr createdKey=IntPtr.Zero;
try
{
createdKey=OverRideRegistry.OpenRegistryKey(OverRideRegistry.HkeyLocalMachine,location);
OverRideRegistry.OverrideRegistryKey(key,createdKey);
}
catch(Exception e)
{
Console.WriteLine("Caught exception: " + e.Message);
}
finally
{
//close key like responsible programmers
OverRideRegistry.CloseRegistryKey(createdKey);
}
}
//Functions to unmap registry hives.
void UnMapRegHives()
{
OverRideRegistry.OverrideRegistryKey(OverRideRegistry.HkeyClassesRoot,IntPtr.Zero);
OverRideRegistry.OverrideRegistryKey(OverRideRegistry.HkeyCurrentUser,IntPtr.Zero);
OverRideRegistry.OverrideRegistryKey(OverRideRegistry.HkeyLocalMachine,IntPtr.Zero);
OverRideRegistry.OverrideRegistryKey(OverRideRegistry.HkeyUsers,IntPtr.Zero);
}
}
class OverRideRegistry
{
//We first declare some stuff required. The are defined in winreg.h and windows.h
public static readonly UIntPtr HkeyClassesRoot = (UIntPtr)0x80000000;
public static readonly UIntPtr HkeyCurrentUser = (UIntPtr)0x80000001;
public static readonly UIntPtr HkeyLocalMachine = (UIntPtr)0x80000002;
public static readonly UIntPtr HkeyUsers = (UIntPtr)0x80000003;
public const uint Delete = 0x00010000;
public const uint ReadOnly = 0x00020000;
public const uint WriteDac = 0x00040000;
public const uint WriteOwner = 0x00080000;
public const uint Synchronize = 0x00100000;
public const uint StandardRightsRequired = 0x000F0000;
public const uint StandardRightsAll = 0x001F0000;
public const uint GenericRead = 0x80000000;
public const uint GenericWrite = 0x40000000;
public const uint GenericExecute = 0x20000000;
public const uint GenericAll = 0x10000000;
#region The Interop Import Stuff
//we now import the functions exposed by advapi32.dll
//Use RegCreateKeyEx to get handle to the openedKey
[DllImport("advapi32.dll", EntryPoint="RegCreateKeyExW", CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
internal static extern int RegCreateKey(UIntPtr key, string subkey, uint reserved, string className, uint options, uint desiredSam, uint securityAttributes, out IntPtr openedKey, out uint disposition);
//This does the actual hive to key mapping
[DllImport("advapi32.dll", EntryPoint="RegOverridePredefKey", CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
internal static extern int RegOverridePredefKey(UIntPtr key, IntPtr newKey);
//Like good programmers, we release our handles.
[DllImport("advapi32.dll", EntryPoint="RegCloseKey", CharSet=CharSet.Unicode, ExactSpelling=true, SetLastError=true)]
internal static extern int RegCloseKey(IntPtr key);
//Our interops are done :-)
#endregion
//Now we actually write wrapper functions to use the imported functions
//Wrapper for creating Registry Keys
internal static IntPtr OpenRegistryKey(UIntPtr key, string path)
{
IntPtr newKey = IntPtr.Zero;
uint disposition = 0;
uint security = StandardRightsAll | GenericRead | GenericWrite | GenericExecute | GenericAll;
int error = RegCreateKey(key, path, 0, null, 0, security, 0, out newKey, out disposition);
return newKey;
}
//Wrapper for the mapping
internal static void OverrideRegistryKey(UIntPtr key, IntPtr newKey)
{
int error = RegOverridePredefKey(key, newKey);
}
//Wrapper for freeing the handle
internal static void CloseRegistryKey(IntPtr key)
{
int error = RegCloseKey(key);
}
}
}