Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * This application converts a text message to uppercase by spawning a child process as another user and saves it to a file.
- *
- * Usage: app.exe MESSAGE FILE_PATH
- * or
- * Usage: app.exe DOMAIN USERNAME PASSWORD MESSAGE FILE_PATH
- *
- *
- * Setup instructions:
- *
- * 1. Open secpol.msc
- * 2. Navigate to 'Local Policies' > 'User Rights Assignment' > 'Log on as a service'.
- * 3. Add your account and click the 'OK' button.
- * 4. Compile this file as a console application.
- * 5. Open a PowerShell console as administrator.
- * 6. PS C:\> New-Service ServiceTest "CONSOLE_EXE_PATH MESSAGE FILE_PATH" -Credential YOUR_DOMAIN\YOUR_ACCOUNT
- * 7. PS C:\> Start-Service ServiceTest
- * 8. Verify that the file is created with the message in uppercase.
- * 10. Delete the file.
- * 11. PS C:\> Stop-Service ServiceTest
- * 12. PS C:\> sc.exe delete ServiceTest
- * 13. PS C:\> New-Service ServiceTest "CONSOLE_EXE_PATH YOUR_DOMAIN ANOTHER_ACCOUNT_USERNAME PASSWORD MESSAGE FILE_PATH" -Credential YOUR_DOMAIN\YOUR_ACCOUNT
- * 14. Ensure the YOUR_DOMAIN\ANOTHER_ACCOUNT_USERNAME has access to the folder where CONSOLE_EXE_PATH is located.
- * 15. PS C:\> Start-Service ServiceTest
- * 16. Verify that the file is not created.
- * 17. Open eventvwr
- * 18. Verify that a { "Log Name": "System", "Source": "Application Popup", "EventId": 26, "Data": ["CONSOLE_EXE - Application Error", "The application was unable to start correctly (0xc0000142). Click OK to close the application."] } event is registered.
- * 19. PS C:\> Stop-Service ServiceTest
- * 20. PS C:\> sc.exe delete ServiceTest
- */
- namespace ServiceTest
- {
- using System;
- using System.Diagnostics;
- using System.IO;
- using System.Net;
- using System.ServiceProcess;
- using System.Text;
- using System.Threading;
- internal sealed class Program : ServiceBase
- {
- private const string ChildIndicator = "079a9ab7-e4b8-4192-9dc7-dc7b93ec9376";
- private readonly string[] args;
- private readonly ManualResetEventSlim processDone = new ManualResetEventSlim();
- private Program(string[] args)
- {
- this.args = args;
- }
- public static void Main(string[] args)
- {
- if (Environment.UserInteractive || Program.IsChildProcess(args))
- {
- var p = new Program(args);
- p.OnStart(null);
- p.OnStop();
- }
- else
- {
- ServiceBase.Run(new Program(args));
- }
- }
- protected override void OnStart(string[] notUsed)
- {
- if (Program.IsChildProcess(this.args))
- {
- Console.WriteLine("handshake");
- var input = Console.In.ReadToEnd();
- if (input != null)
- {
- Console.WriteLine(input.ToUpper());
- }
- this.processDone.Set();
- }
- else if (this.args.Length == 2 || this.args.Length == 5)
- {
- var credentials = this.args.Length == 5 ? new NetworkCredential(this.args[1], this.args[2], this.args[0]) : null;
- var message = this.args.Length == 5 ? this.args[3] : this.args[0];
- var outputFile = this.args.Length == 5 ? this.args[4] : this.args[1];
- // Create process.
- var process = new Process
- {
- EnableRaisingEvents = true,
- StartInfo =
- {
- FileName = Process.GetCurrentProcess().MainModule.FileName,
- Arguments = Program.ChildIndicator,
- CreateNoWindow = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- RedirectStandardOutput = true,
- UseShellExecute = false,
- WorkingDirectory = @"C:\"
- }
- };
- if (credentials != null)
- {
- process.StartInfo.Domain = credentials.Domain;
- process.StartInfo.UserName = credentials.UserName;
- process.StartInfo.Password = credentials.SecurePassword;
- }
- var error = new StringBuilder();
- var errorWaitHandle = new ManualResetEventSlim();
- process.ErrorDataReceived += (s, e) =>
- {
- if (e.Data != null)
- {
- error.AppendLine(e.Data);
- }
- else
- {
- errorWaitHandle.Set();
- }
- };
- var output = new StringBuilder();
- var outputWaitHandle = new ManualResetEventSlim();
- process.OutputDataReceived += (s, e) =>
- {
- if (e.Data == "handshake")
- {
- process.StandardInput.Write(message);
- process.StandardInput.Close();
- }
- else if (e.Data != null)
- {
- output.AppendLine(e.Data);
- }
- else
- {
- outputWaitHandle.Set();
- }
- };
- process.Exited += (s, e) =>
- {
- try
- {
- errorWaitHandle.Wait();
- outputWaitHandle.Wait();
- if (error.Length > 0)
- {
- File.WriteAllText(outputFile, string.Format("Child process completed with an error: {0}", error));
- }
- else if (output.Length > 0)
- {
- File.WriteAllText(outputFile, output.ToString());
- }
- }
- finally
- {
- process.Dispose();
- this.processDone.Set();
- }
- };
- process.Start();
- process.BeginErrorReadLine();
- process.BeginOutputReadLine();
- }
- else
- {
- using (var currentProcess = Process.GetCurrentProcess())
- {
- Console.WriteLine("Usage:");
- Console.WriteLine("{0} <msg> <path_to_output_file>", currentProcess.MainModule.ModuleName);
- Console.WriteLine("{0} <domain> <username> <password> <msg> <path_to_output_file>", currentProcess.MainModule.ModuleName);
- this.processDone.Set();
- }
- }
- }
- protected override void OnStop()
- {
- this.processDone.Wait();
- }
- private static bool IsChildProcess(string[] args)
- {
- return args.Length == 1 && args[0] == Program.ChildIndicator;
- }
- }
- }
Add Comment
Please, Sign In to add comment