private static extern bool CreateProcess( string lpApplicationName, string lpCommandLine, ref SecurityAttributes lpProcessAttributes, ref SecurityAttributes lpThreadAttributes, bool bInheritHandles, CreationFlags dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref StartupInfo lpStartupInfo, out ProcessInformation lpProcessInformation);
// AnonymousPipeServerStream owner; public unsafe Win32AnonymousPipeServer (AnonymousPipeServerStream owner, PipeDirection direction, HandleInheritability inheritability, int bufferSize, PipeSecurity pipeSecurity) { IntPtr r, w; byte[] securityDescriptor = null; if (pipeSecurity != null) securityDescriptor = pipeSecurity.GetSecurityDescriptorBinaryForm (); fixed (byte* securityDescriptorPtr = securityDescriptor) { SecurityAttributes att = new SecurityAttributes (inheritability, (IntPtr)securityDescriptorPtr); if (!Win32Marshal.CreatePipe (out r, out w, ref att, bufferSize)) throw Win32PipeError.GetException (); } var rh = new SafePipeHandle (r, true); var wh = new SafePipeHandle (w, true); if (direction == PipeDirection.Out) { server_handle = wh; client_handle = rh; } else { server_handle = rh; client_handle = wh; } }
/// <summary> /// Runs the actual managed shell logic /// </summary> private void RunInternal() { // Install ctrl handler SetConsoleCtrlHandler(ConsoleCtrlCheck, true); // Find manifest WriteLog(LogType.Info, "Searching for suitable target..."); var manifest = FindManifest(); if (manifest == null) { throw new Exception("Failed to find suitable target"); } WriteLog(LogType.Info, $"Found game '{manifest.GameName}'"); // Create the process WriteLog(LogType.Info, "Starting process..."); var startInfo = new ProcessStartInfo(); startInfo.FileName = Path.GetFullPath(manifest.ExecutableName); startInfo.Arguments = Environment.CommandLine; var startupInfo = new StartupInfo(); ProcessInformation procInfo; var cmdLineArgs = Environment.GetCommandLineArgs(); var lessCmdLineArgs = new string[cmdLineArgs.Length - 1]; Array.Copy(cmdLineArgs, 1, lessCmdLineArgs, 0, cmdLineArgs.Length - 1); string commandLine = $"\"{Path.GetFullPath(manifest.ExecutableName)}\" {string.Join(" ", lessCmdLineArgs)}"; var unusedSecAttr = new SecurityAttributes(); if (!CreateProcess( null, commandLine, ref unusedSecAttr, ref unusedSecAttr, true, CreationFlags.CREATE_SUSPENDED, IntPtr.Zero, Directory.GetCurrentDirectory(), ref startupInfo, out procInfo )) { WriteLog(LogType.Error, $"Failed to create process! ({GetLastError()})"); return; } process = Process.GetProcessById(procInfo.processId); WriteLog(LogType.Info, $"Process ID is {process.Id}"); // See if we can inject var dllPath = Path.GetFullPath(manifest.InjectDllName); if (File.Exists(dllPath)) { // Setup pipe SetupPipe(); // Inject PerformInjection(dllPath); } // Wait until it exits ResumeThreads(); process.WaitForExit(); process = null; // Clean up Terminate(); }
internal static extern IntPtr CreateFile (string name, PipeAccessRights desiredAccess, FileShare fileShare, ref SecurityAttributes atts, int creationDisposition, int flags, IntPtr templateHandle);
internal static extern IntPtr CreateNamedPipe (string name, uint openMode, int pipeMode, int maxInstances, int outBufferSize, int inBufferSize, int defaultTimeout, ref SecurityAttributes securityAttributes, IntPtr atts);
internal static extern bool CreatePipe (out IntPtr readHandle, out IntPtr writeHandle, ref SecurityAttributes pipeAtts, int size);
// .ctor without handle - create new public unsafe Win32NamedPipeServer (NamedPipeServerStream owner, string pipeName, int maxNumberOfServerInstances, PipeTransmissionMode transmissionMode, PipeAccessRights rights, PipeOptions options, int inBufferSize, int outBufferSize, PipeSecurity pipeSecurity, HandleInheritability inheritability) { string name = String.Format ("\\\\.\\pipe\\{0}", pipeName); uint openMode; openMode = (uint)rights | (uint)options; // Enum values match Win32 flags exactly. int pipeMode = 0; if ((owner.TransmissionMode & PipeTransmissionMode.Message) != 0) pipeMode |= 4; //if ((readTransmissionMode & PipeTransmissionMode.Message) != 0) // pipeMode |= 2; if ((options & PipeOptions.Asynchronous) != 0) pipeMode |= 1; byte[] securityDescriptor = null; if (pipeSecurity != null) securityDescriptor = pipeSecurity.GetSecurityDescriptorBinaryForm (); fixed (byte* securityDescriptorPtr = securityDescriptor) { // FIXME: is nDefaultTimeout = 0 ok? var att = new SecurityAttributes (inheritability, (IntPtr)securityDescriptorPtr); var ret = Win32Marshal.CreateNamedPipe (name, openMode, pipeMode, maxNumberOfServerInstances, outBufferSize, inBufferSize, 0, ref att, IntPtr.Zero); if (ret == new IntPtr (-1L)) throw Win32PipeError.GetException (); handle = new SafePipeHandle (ret, true); } }
// .ctor without handle - create new public Win32NamedPipeClient (NamedPipeClientStream owner, string serverName, string pipeName, PipeAccessRights desiredAccessRights, PipeOptions options, HandleInheritability inheritability) { name = String.Format ("\\\\{0}\\pipe\\{1}", serverName, pipeName); var att = new SecurityAttributes (inheritability, IntPtr.Zero); is_async = (options & PipeOptions.Asynchronous) != PipeOptions.None; opener = delegate { var ret = Win32Marshal.CreateFile (name, desiredAccessRights, 0, ref att, 3, 0, IntPtr.Zero); if (ret == new IntPtr (-1L)) throw Win32PipeError.GetException (); return new SafePipeHandle (ret, true); }; this.owner = owner; }