Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.DirectoryServices.AccountManagement;
- using System.IO;
- using System.Linq;
- using System.Security;
- using System.Security.AccessControl;
- using Newtonsoft.Json;
- using System.Collections;
- using System.ComponentModel;
- using System.Text.RegularExpressions;
- using System.Security.Cryptography.X509Certificates;
- namespace ConsoleApplication1
- {
- static class Program
- {
- static string[] RequiredAccessPaths = new[]
- {
- @"C:\Users\worker\workspace",
- //@"C:\ProgramData\Microsoft\Crypto",
- //@"C:\Windows\SysWOW64\config\systemprofile\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python",
- };
- static void Main(string[] args)
- {
- var workingDrive = Environment.GetEnvironmentVariable("SystemDrive").ToLower();
- for (char d = 'x'; d <= 'z'; d++)
- {
- if(Directory.Exists(string.Concat(d, ":\\")))
- {
- workingDrive = string.Concat(d, ':');
- break;
- }
- }
- var results = new List<CommandResult>();
- string username = string.Format("task-{0}", Guid.NewGuid().ToString().Substring(0, 8));
- string password = Guid.NewGuid().ToString().Substring(0, 13);
- string workingDirectory = Path.Combine(string.Concat(workingDrive, '\\'), username);
- var user = CreateUser(username, password, workingDirectory, "Users");
- var ds = new DirectorySecurity();
- foreach (var sid in new[] { GroupPrincipal.FindByIdentity(new PrincipalContext(ContextType.Machine), "Administrators").Sid, user.Sid })
- {
- var fsar = new FileSystemAccessRule(sid, FileSystemRights.FullControl, AccessControlType.Allow);
- ds.AddAccessRule(fsar);
- }
- foreach(var dir in new[] { workingDirectory, Path.Combine(workingDirectory, "Temp"), Path.Combine(workingDirectory, "AppData", "Roaming"), Path.Combine(workingDirectory, "AppData", "Local") })
- Directory.CreateDirectory(workingDirectory, ds);
- var protectedEnvironmentVariables = new List<EnvironmentVariable>()
- {
- new EnvironmentVariable("USERNAME", username),
- new EnvironmentVariable("HOME", workingDirectory),
- new EnvironmentVariable("HOMEDRIVE", workingDirectory.Split(':').First()),
- new EnvironmentVariable("HOMEPATH", workingDirectory.Split(':').Last()),
- new EnvironmentVariable("USERPROFILE", workingDirectory),
- new EnvironmentVariable("TEMP", Path.Combine(workingDirectory, "Temp")),
- new EnvironmentVariable("TMP", Path.Combine(workingDirectory, "Temp")),
- new EnvironmentVariable("APPDATA", Path.Combine(workingDirectory, "AppData", "Roaming")),
- new EnvironmentVariable("LOCALAPPDATA", Path.Combine(workingDirectory, "AppData", "Local"))
- };
- var payload = JsonConvert.DeserializeObject<Payload>(System.IO.File.ReadAllText(@"c:\data\payload.json"));
- var environmentVariables = new List<EnvironmentVariable>(payload.Environment.Select(v => new EnvironmentVariable(v.Name, ExpandEnvironmentVariablesWithSubstitution(ExpandEnvironmentVariables(v.Value, payload.Environment), workingDirectory, username, password))));
- protectedEnvironmentVariables.ForEach(pev =>
- {
- if (environmentVariables.Any(ev => Regex.IsMatch(ev.Name, pev.Name, RegexOptions.IgnoreCase)))
- environmentVariables.First(ev => Regex.IsMatch(ev.Name, pev.Name, RegexOptions.IgnoreCase)).Value = pev.Value;
- else
- environmentVariables.Add(pev);
- });
- var impossibleSubstitutions = new Dictionary<string, string>();
- while (environmentVariables.Any(v => Regex.IsMatch(v.Value, "%[^%^;]+%") && !Regex.IsMatch(v.Value, string.Format("%{0}%", v.Name), RegexOptions.IgnoreCase) && !Regex.Matches(v.Value, "%([^%^;]+)%").Cast<Match>().Select(r=>r.Groups[1].Value).Any(r => impossibleSubstitutions.ContainsKey(r.ToUpperInvariant()))))
- {
- foreach (var v in environmentVariables.Where(v => Regex.IsMatch(v.Value, "%[^%^;]+%") && !Regex.IsMatch(v.Value, string.Format("%{0}%", v.Name), RegexOptions.IgnoreCase)))
- {
- foreach (Match m in Regex.Matches(v.Value, "%([^%^;]+)%"))
- if (!environmentVariables.Select(x=>x.Name).Any(name=> string.Equals(name, m.Groups[1].Value)) && string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(m.Groups[1].Value)))
- {
- if (!impossibleSubstitutions.ContainsKey(m.Groups[1].Value.ToUpperInvariant()))
- impossibleSubstitutions.Add(m.Groups[1].Value.ToUpperInvariant(), m.Groups[1].Value);
- v.Value = v.Value.Replace(string.Format("%{0}%", m.Groups[1].Value), string.Empty);
- }
- }
- environmentVariables = new List<EnvironmentVariable>(environmentVariables.Select(v => new EnvironmentVariable(v.Name, ExpandEnvironmentVariablesWithSubstitution(ExpandEnvironmentVariables(v.Value, environmentVariables), workingDirectory, username, password))));
- }
- // merge system environment variables
- //foreach (DictionaryEntry sev in Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine))
- // if (!environmentVariables.Any(v => string.Equals(v.Name, (string)sev.Key, StringComparison.OrdinalIgnoreCase)))
- // environmentVariables.Add(new EnvironmentVariable((string)sev.Key, (string)sev.Value));
- // replace any variables in variable values
- //for (int i = 0; i < environmentVariables.Count; i++)
- //{
- // var any = new Regex("%([^%^;]+)%");
- // if (any.IsMatch(environmentVariables[i].Value))
- // {
- // //todo: deal with multiple matches var matchCOunt = any.Match(environmentVariables[i].Value).Groups.Count;
- // var key = any.Match(environmentVariables[i].Value).Groups[1].Value;
- // if (environmentVariables.Any(v => string.Equals(v.Name, key, StringComparison.OrdinalIgnoreCase)))
- // {
- // var value = environmentVariables.First(v => string.Equals(v.Name, key, StringComparison.OrdinalIgnoreCase)).Value;
- // environmentVariables[i].Value = Regex.Replace(environmentVariables[i].Value, string.Format("%{0}%", key), value, RegexOptions.IgnoreCase);
- // }
- // else
- // {
- // environmentVariables[i].Value = ExpandEnvironmentVariablesWithSubstitution(environmentVariables[i].Value);
- // }
- // }
- //}
- // atempt to import moz certs
- //var mozCertPath = Path.Combine(@"c:\", "mozilla-build", "msys", "etc", "ca-bundle.crt");
- //if (File.Exists(mozCertPath))
- //{
- // var mozCert = new X509Certificate2(X509Certificate.CreateFromCertFile(mozCertPath));
- // X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
- // store.Open(OpenFlags.ReadWrite);
- // var existing = store.Certificates.Find(X509FindType.FindByThumbprint, mozCert.Thumbprint, true);
- // if (existing == null)
- // store.Add(mozCert);
- // store.Close();
- //}
- try
- {
- Console.ForegroundColor = ConsoleColor.Gray;
- Console.WriteLine("minion found a payload with {0} commands and {1} environment variables.", payload.Commands.Count(), payload.Environment.Count());
- Console.ResetColor();
- var interrupt = false;
- foreach (var command in payload.Commands)
- {
- var environmentBefore = new List<EnvironmentVariable>(environmentVariables);
- command.File = ExpandEnvironmentVariablesWithSubstitution(ExpandEnvironmentVariables(command.File, environmentVariables), workingDirectory);
- command.Arguments = command.Arguments.Select(a => ExpandEnvironmentVariablesWithSubstitution(ExpandEnvironmentVariables(a, environmentVariables), workingDirectory));
- Console.ForegroundColor = ConsoleColor.Yellow;
- Console.WriteLine("{0} {1}", command.File, string.Join(" ", command.Arguments));
- Console.ResetColor();
- if (interrupt)
- {
- results.Add(new CommandResult()
- {
- ExitCode = -100000
- });
- Console.ForegroundColor = ConsoleColor.Gray;
- Console.WriteLine("skipped due to previous errors.");
- Console.ResetColor();
- }
- else
- {
- var errors = new List<string>();
- var output = new List<string>();
- var process = new Process
- {
- StartInfo = new ProcessStartInfo
- {
- FileName = command.File,
- Arguments = command.Arguments.Any() ? string.Join(" ", command.Arguments) : null,
- UseShellExecute = false,
- CreateNoWindow = true,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- WorkingDirectory = workingDirectory,
- UserName = username,
- Password = password.ToSecureString()
- }
- };
- try
- {
- // pass environment changes to the command
- environmentVariables.ForEach(e => {
- if (process.StartInfo.EnvironmentVariables.ContainsKey(e.Name))
- process.StartInfo.EnvironmentVariables[e.Name] = e.Value;
- else
- process.StartInfo.EnvironmentVariables.Add(e.Name, e.Value);
- });
- process.ErrorDataReceived += (s, ea) => {
- errors.Add(ea.Data);
- Console.ForegroundColor = ConsoleColor.Red;
- Console.WriteLine(ea.Data);
- Console.ResetColor();
- };
- process.OutputDataReceived += (s, ea) => {
- output.Add(ea.Data);
- Console.ForegroundColor = ConsoleColor.Blue;
- Console.WriteLine(ea.Data);
- Console.ResetColor();
- };
- process.Start();
- process.BeginOutputReadLine();
- process.BeginErrorReadLine();
- process.WaitForExit();
- if (process.ExitCode != 0)
- {
- if (!process.HasExited)
- process.Kill();
- interrupt = true;
- }
- // propagate environment changes from the command
- // todo: validate that changes show up here
- environmentVariables.Clear();
- process.StartInfo.EnvironmentVariables.Cast<DictionaryEntry>().AsParallel().ForAll(v => environmentVariables.Add(new EnvironmentVariable((string)v.Key, (string)v.Value)));
- if(process.ExitCode != 0)
- {
- results.Add(new CommandResult()
- {
- StartTime = process.StartTime,
- ExitTime = process.ExitTime,
- TotalProcessorTime = process.TotalProcessorTime,
- ExitCode = process.ExitCode,
- EnvironmentBefore = environmentBefore,
- EnvironmentAfter = environmentVariables
- });
- foreach (var ev in environmentVariables.OrderBy(o => o.Name))
- {
- Console.ForegroundColor = ConsoleColor.Cyan;
- Console.Write(ev.Name);
- Console.ForegroundColor = ConsoleColor.Gray;
- Console.Write(": ");
- Console.ForegroundColor = ConsoleColor.Magenta;
- Console.Write(ev.Value);
- Console.Write('\n');
- Console.ResetColor();
- }
- }
- Console.ForegroundColor = ConsoleColor.Gray;
- Console.WriteLine("paeon completed this task in {0} seconds.", process.TotalProcessorTime.TotalSeconds);
- Console.ResetColor();
- }
- catch (Win32Exception win32Exception)
- {
- Console.ForegroundColor = ConsoleColor.DarkYellow;
- Console.WriteLine(win32Exception);
- Console.ResetColor();
- }
- finally
- {
- process.CancelOutputRead();
- process.CancelErrorRead();
- if (!process.HasExited)
- {
- process.Kill();
- }
- }
- }
- }
- }
- catch (Exception exception)
- {
- Console.ForegroundColor = ConsoleColor.DarkYellow;
- Console.WriteLine(exception);
- Console.ResetColor();
- }
- finally
- {
- var completed = results.Count(r => r.ExitCode == 0);
- var skipped = results.Count(r => r.ExitCode == -100000);
- var failed = results.Count(r => r.ExitCode != -100000 && r.ExitCode != 0);
- DeleteUser(user);
- Console.ForegroundColor = ConsoleColor.Gray;
- Console.WriteLine("minion killed paeon {0} after she completed {1} tasks and failed at {2} in {3}.", username, completed, failed, new TimeSpan(results.Sum(r => r.TotalProcessorTime.Ticks)));
- Console.ResetColor();
- }
- Console.ReadKey();
- }
- static SecureString ToSecureString(this string s)
- {
- var ss = new SecureString();
- if (!string.IsNullOrEmpty(s))
- foreach (var c in s.ToCharArray())
- ss.AppendChar(c);
- return ss;
- }
- private static UserPrincipal CreateUser(string username, string password, string homeDirectory, params string[] groups)
- {
- UserPrincipal up;
- using (var mc = new PrincipalContext(ContextType.Machine))
- {
- up = new UserPrincipal(mc, username, password, true)
- {
- PasswordNeverExpires = true,
- HomeDirectory = homeDirectory
- };
- up.Save();
- groups.Select(group => GroupPrincipal.FindByIdentity(mc, group))
- .AsParallel()
- .Where(gp => gp != null)
- .ForAll(gp =>
- {
- gp.Members.Add(up);
- gp.Save();
- });
- }
- var folders = new List<string>();
- var files = new List<string>();
- foreach (var path in RequiredAccessPaths)
- {
- GetSubfoldersAndFiles(path, ref folders, ref files);
- foreach (var folder in folders)
- {
- AddPathSecurity(folder, username, FileSystemRights.Read | FileSystemRights.Traverse, AccessControlType.Allow);
- }
- foreach (var file in files)
- {
- AddPathSecurity(file, username, FileSystemRights.Read, AccessControlType.Allow);
- }
- }
- Console.ForegroundColor = ConsoleColor.Gray;
- Console.WriteLine("minion spawned a paeon {0} and commanded {1} to take her into their fold.", username, string.Join(", ", groups));
- Console.ResetColor();
- return up;
- }
- private static void DeleteUser(UserPrincipal user)
- {
- var username = user.SamAccountName;
- foreach (var path in RequiredAccessPaths)
- {
- var folders = new List<string>();
- var files = new List<string>();
- GetSubfoldersAndFiles(path, ref folders, ref files);
- foreach (var folder in folders)
- {
- RemovePathSecurity(folder, username, FileSystemRights.Read | FileSystemRights.Traverse, AccessControlType.Allow);
- }
- foreach (var file in files)
- {
- RemovePathSecurity(file, username, FileSystemRights.Read, AccessControlType.Allow);
- }
- }
- user.Delete();
- }
- private static void AddPathSecurity(string path, string username, FileSystemRights fsr, AccessControlType act)
- {
- var di = new DirectoryInfo(path);
- var ds = di.GetAccessControl();
- ds.AddAccessRule(new FileSystemAccessRule(username, fsr, act));
- try
- {
- di.SetAccessControl(ds);
- Console.ForegroundColor = ConsoleColor.Green;
- Console.WriteLine("worker access granted: {0}.", path);
- Console.ResetColor();
- }
- catch
- {
- Console.ForegroundColor = ConsoleColor.Magenta;
- Console.WriteLine("worker access not granted: {0}.", path);
- Console.ResetColor();
- }
- }
- private static void RemovePathSecurity(string path, string username, FileSystemRights fsr, AccessControlType act)
- {
- var di = new DirectoryInfo(path);
- var ds = di.GetAccessControl();
- ds.RemoveAccessRule(new FileSystemAccessRule(username, fsr, act));
- try
- {
- di.SetAccessControl(ds);
- Console.ForegroundColor = ConsoleColor.Green;
- Console.WriteLine("worker access removed: {0}.", path);
- Console.ResetColor();
- }
- catch
- {
- Console.ForegroundColor = ConsoleColor.Magenta;
- Console.WriteLine("worker access not removed: {0}.", path);
- Console.ResetColor();
- }
- }
- private static void GetSubfoldersAndFiles(string path, ref List<string> folders, ref List<string> files)
- {
- if (!folders.Any())
- folders.Add(path);
- foreach (string folder in Directory.GetDirectories(path))
- {
- folders.Add(folder);
- foreach (string file in Directory.GetFiles(folder))
- {
- files.Add(file);
- }
- GetSubfoldersAndFiles(folder, ref folders, ref files);
- }
- }
- private static string ExpandEnvironmentVariables(string value, IEnumerable<EnvironmentVariable> environmentVariables)
- {
- foreach (var ev in environmentVariables)
- if (value != ev.Value)
- value = Regex.Replace(value, string.Format("%{0}%", ev.Name), ev.Value, RegexOptions.IgnoreCase);
- return value;
- }
- private static string ExpandEnvironmentVariablesWithSubstitution(string value, string workingDirectory = null, string username = null, string password = null)
- {
- string result = string.Empty;
- var process = new Process
- {
- StartInfo = new ProcessStartInfo
- {
- FileName = "cmd",
- Arguments = string.Concat("/c echo ", value),
- UseShellExecute = false,
- CreateNoWindow = true,
- RedirectStandardOutput = true,
- WorkingDirectory = workingDirectory,
- UserName = username,
- Password = password.ToSecureString()
- }
- };
- process.OutputDataReceived += (s, e) => result = string.IsNullOrWhiteSpace(e.Data) ? result: e.Data;
- process.Start();
- process.BeginOutputReadLine();
- process.WaitForExit();
- process.CancelOutputRead();
- if (!process.HasExited)
- process.Kill();
- return result;
- }
- }
- public class Payload
- {
- public IEnumerable<Command> Commands { get; set; }
- public IEnumerable<EnvironmentVariable> Environment { get; set; }
- }
- public class Command
- {
- public string File { get; set; }
- public IEnumerable<string> Arguments { get; set; }
- }
- public class EnvironmentVariable
- {
- public EnvironmentVariable() { }
- public EnvironmentVariable(string name, string value)
- {
- Name = name;
- Value = value;
- }
- public string Name { get; set; }
- public string Value { get; set; }
- }
- public class CommandResult
- {
- public IEnumerable<EnvironmentVariable> EnvironmentBefore { get; set; }
- public IEnumerable<EnvironmentVariable> EnvironmentAfter { get; set; }
- public int ExitCode { get; set; }
- public DateTime StartTime { get; set; }
- public DateTime ExitTime { get; set; }
- public TimeSpan TotalProcessorTime { get; set; }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement