/// <summary> /// Helper function creating virtual registry object using an encryption key /// if it is specified and installing string value alterer (rebasing paths). /// </summary> private VirtualRegistry CreateVirtualRegistry() { DebugLogger.WriteLine("Reg hive file: {0} for process {1}", params_.GetRegHivePath(), RemoteHooking.GetCurrentProcessId()); Crypto.FileEncryptionLayer.AttachFile(params_.GetRegHivePath(), params_.GetCryptoKey()); string diffHivePath = Path.GetFullPath("local.rh"); Crypto.FileEncryptionLayer.AttachFile(diffHivePath, ""); // This is because diff hive is saved first into a temporary file which is then atomically renamed Crypto.FileEncryptionLayer.AttachFile(diffHivePath + OffRegHive.TMP_SAVE_SUFFIX, ""); VirtualRegistry result = new VirtualRegistry(params_.GetRegHivePath(), diffHivePath); result.DataAlterer.RegisterStringValueAlterer(pathRebaser_.RebasePath); return(result); }
/// <summary> /// This is a single sandboxing finalization method, which is called from ProcessExit event /// and from ExitProcess hook. /// </summary> /// <para>This method performs deinitialization in the needed order. It saves "diff" reghive /// if it was not yet saved. Uninstalls hooks, deinitializes helper objects: logger, saver /// thread.</para> private void Shutdown() { if (registry_ != null) { registry_ = null; //Debugger.Launch(); DateTime dt = DateTime.Now; shutdownManager_.Dispose(); // To make sure all hooks are uninstalled before shutdown is finished // TODO: wrap it into IDisposable installed during initialization NativeAPI.LhWaitForPendingRemovals(); TimeSpan ts = DateTime.Now - dt; DebugLogger.WriteLine("Shutdown - took {0}", ts); } DebugLogger.SafeDispose(); }
/// <summary> /// Main injection method, which is called when injection is done and does not return /// until the target process exits. /// </summary> /// <para>Run method has the same signature as the constructor, the parameters' values /// are those which are passed to <see cref="StartSandbox.EasyHookWrapper.Inject"/> call.</para> /// <param name="context"></param> /// <param name="channelName">IPC channel name (used by constructor and not used by Run)</param> /// <param name="regHivePath">Path to the "base" reghive which is not changed (all changes are /// saved to a different "diff" reghive).</param> /// <param name="xml">XML containing file names and encryption keys associated with them /// (including reghive encryption key if used).</param> /// <param name="threadId">Thread ID of the main target process thread, used to resume it as soon /// as initialization is done.</param> public void Run( RemoteHooking.IContext context, string channelName, string paramsXml) { try { // Uncomment for debugging purpose // This is to preload assemblies and attach debugger to break into code simply // by a call to Debugger.Break // Debugger.Launch(); // TODO: think about general way for components to initialize before hooks are installed. // static constructors do not work because they are called on first use. // To initialize crypto system, otherwise initialization may throw exceptions because // file hooks are already installed and initialization may be called from one of them. Aes.Create(); params_ = new Params(paramsXml); if (!params_.IsProductionTitle()) { fileAccessLogger_ = new FileAccessLogger(params_.GetRedmineId()); shutdownManager_.Attach(fileAccessLogger_); } // Hotfix: Disabling crash report window for ACDSee exceptionHandler_ = new ExceptionHandler(ShutdownOnException, disabled: params_.GetRedmineId() == 1345); AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit); AppDomain.CurrentDomain.DomainUnload += new EventHandler(CurrentDomain_DomainUnload); // Starting DebugLogger before file hooks are installed to make them disabled for its thread DebugLogger.WriteLine("---------------------startup----------------------"); // TODO: put registration of SetUnhandledExceptionFilter hook to ExceptionHandler constructor // for this purpose may be make installedHooks a static variable so that anyone can register there AddHooks(new InstalledHooks(this, new Hooks( new Delegate[] { new Win32Api.ExitProcess_Delegate(ExitProcess_Hooked), new Win32Api.SetUnhandledExceptionFilter_Delegate(ExceptionHandler.SetUnhandledExceptionFilter_Hooked) }))); shutdownManager_.Attach(exceptionHandler_); pathRebaser_ = new PathRebaser(); AddHooks(new InstalledHooks(this, Logging.FileAccessFunctionsHookLib.Hooks)); AddHooks(new InstalledHooks(this, Crypto.CryptoFunctionsHookLib.Hooks)); registry_ = CreateVirtualRegistry(); shutdownManager_.Attach(registry_); // TODO: TextPad in case of error during startup crashes after showing a error message // because .NET tries to access a HKEY returned by VirtualRegistry // after hooks are uninstalled in Shutdown method. // So either we shouldn't uninstall hooks at all, just save VirtualRegistry and that's it, // or do something else. AddHooks(new InstalledHooks(this, RegistryFunctionsHookLib.Hooks)); // To debug hooks under XP 64, because breakpoints can be safely set for syscalls // only after hooks are installed //MessageBox.Show("Sandbox debug"); shutdownManager_.Attach(new RegularHiveSaver(registry_)); WakeUpProcess(params_.GetThreadId()); interface_.SafelyReportInjectionDone(); } catch (Exception ex) { interface_.SafelyReportInjectionError(ex); return; } // wait for host process termination... try { // TODO: think about disabling file hooks for this thread because they are called for pipe, // in the beginning of sandbox implementation this thread was disabled for all hooks // but this caused some problems... possibly with .NET interaction between threads // and passing registry handles, so do not disable all hooks, just file hooks // but make sure file access log is fine w/o reghives and may be some other files while (true) { if (interface_.SafeCheckNowEmbedded()) { NowEmbeddedEvent(); } // Using Join instead of Sleep to pump message loop needed for the case of STA COM objects // living in this thread Thread.CurrentThread.Join(100); } } catch { // NET Remoting will raise an exception if host is unreachable // and if current process is exiting } DebugLogger.WriteLine("Exitting Run"); }