Advertisement
Guest User

Untitled

a guest
Apr 28th, 2016
247
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.63 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.DirectoryServices.AccountManagement;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Security;
  8. using System.Security.AccessControl;
  9. using Newtonsoft.Json;
  10. using System.Collections;
  11. using System.ComponentModel;
  12. using System.Text.RegularExpressions;
  13. using System.Security.Cryptography.X509Certificates;
  14.  
  15. namespace ConsoleApplication1
  16. {
  17. static class Program
  18. {
  19. static string[] RequiredAccessPaths = new[]
  20. {
  21. @"C:\Users\worker\workspace",
  22. //@"C:\ProgramData\Microsoft\Crypto",
  23. //@"C:\Windows\SysWOW64\config\systemprofile\AppData\Local\Programs\Common\Microsoft\Visual C++ for Python",
  24. };
  25. static void Main(string[] args)
  26. {
  27. var workingDrive = Environment.GetEnvironmentVariable("SystemDrive").ToLower();
  28. for (char d = 'x'; d <= 'z'; d++)
  29. {
  30. if(Directory.Exists(string.Concat(d, ":\\")))
  31. {
  32. workingDrive = string.Concat(d, ':');
  33. break;
  34. }
  35. }
  36. var results = new List<CommandResult>();
  37. string username = string.Format("task-{0}", Guid.NewGuid().ToString().Substring(0, 8));
  38. string password = Guid.NewGuid().ToString().Substring(0, 13);
  39. string workingDirectory = Path.Combine(string.Concat(workingDrive, '\\'), username);
  40. var user = CreateUser(username, password, workingDirectory, "Users");
  41. var ds = new DirectorySecurity();
  42. foreach (var sid in new[] { GroupPrincipal.FindByIdentity(new PrincipalContext(ContextType.Machine), "Administrators").Sid, user.Sid })
  43. {
  44. var fsar = new FileSystemAccessRule(sid, FileSystemRights.FullControl, AccessControlType.Allow);
  45. ds.AddAccessRule(fsar);
  46. }
  47. foreach(var dir in new[] { workingDirectory, Path.Combine(workingDirectory, "Temp"), Path.Combine(workingDirectory, "AppData", "Roaming"), Path.Combine(workingDirectory, "AppData", "Local") })
  48. Directory.CreateDirectory(workingDirectory, ds);
  49.  
  50. var protectedEnvironmentVariables = new List<EnvironmentVariable>()
  51. {
  52. new EnvironmentVariable("USERNAME", username),
  53. new EnvironmentVariable("HOME", workingDirectory),
  54. new EnvironmentVariable("HOMEDRIVE", workingDirectory.Split(':').First()),
  55. new EnvironmentVariable("HOMEPATH", workingDirectory.Split(':').Last()),
  56. new EnvironmentVariable("USERPROFILE", workingDirectory),
  57. new EnvironmentVariable("TEMP", Path.Combine(workingDirectory, "Temp")),
  58. new EnvironmentVariable("TMP", Path.Combine(workingDirectory, "Temp")),
  59. new EnvironmentVariable("APPDATA", Path.Combine(workingDirectory, "AppData", "Roaming")),
  60. new EnvironmentVariable("LOCALAPPDATA", Path.Combine(workingDirectory, "AppData", "Local"))
  61. };
  62.  
  63. var payload = JsonConvert.DeserializeObject<Payload>(System.IO.File.ReadAllText(@"c:\data\payload.json"));
  64. var environmentVariables = new List<EnvironmentVariable>(payload.Environment.Select(v => new EnvironmentVariable(v.Name, ExpandEnvironmentVariablesWithSubstitution(ExpandEnvironmentVariables(v.Value, payload.Environment), workingDirectory, username, password))));
  65. protectedEnvironmentVariables.ForEach(pev =>
  66. {
  67. if (environmentVariables.Any(ev => Regex.IsMatch(ev.Name, pev.Name, RegexOptions.IgnoreCase)))
  68. environmentVariables.First(ev => Regex.IsMatch(ev.Name, pev.Name, RegexOptions.IgnoreCase)).Value = pev.Value;
  69. else
  70. environmentVariables.Add(pev);
  71. });
  72. var impossibleSubstitutions = new Dictionary<string, string>();
  73. 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()))))
  74. {
  75. foreach (var v in environmentVariables.Where(v => Regex.IsMatch(v.Value, "%[^%^;]+%") && !Regex.IsMatch(v.Value, string.Format("%{0}%", v.Name), RegexOptions.IgnoreCase)))
  76. {
  77. foreach (Match m in Regex.Matches(v.Value, "%([^%^;]+)%"))
  78. if (!environmentVariables.Select(x=>x.Name).Any(name=> string.Equals(name, m.Groups[1].Value)) && string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable(m.Groups[1].Value)))
  79. {
  80. if (!impossibleSubstitutions.ContainsKey(m.Groups[1].Value.ToUpperInvariant()))
  81. impossibleSubstitutions.Add(m.Groups[1].Value.ToUpperInvariant(), m.Groups[1].Value);
  82. v.Value = v.Value.Replace(string.Format("%{0}%", m.Groups[1].Value), string.Empty);
  83. }
  84. }
  85. environmentVariables = new List<EnvironmentVariable>(environmentVariables.Select(v => new EnvironmentVariable(v.Name, ExpandEnvironmentVariablesWithSubstitution(ExpandEnvironmentVariables(v.Value, environmentVariables), workingDirectory, username, password))));
  86. }
  87. // merge system environment variables
  88. //foreach (DictionaryEntry sev in Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine))
  89. // if (!environmentVariables.Any(v => string.Equals(v.Name, (string)sev.Key, StringComparison.OrdinalIgnoreCase)))
  90. // environmentVariables.Add(new EnvironmentVariable((string)sev.Key, (string)sev.Value));
  91.  
  92. // replace any variables in variable values
  93. //for (int i = 0; i < environmentVariables.Count; i++)
  94. //{
  95. // var any = new Regex("%([^%^;]+)%");
  96. // if (any.IsMatch(environmentVariables[i].Value))
  97. // {
  98. // //todo: deal with multiple matches var matchCOunt = any.Match(environmentVariables[i].Value).Groups.Count;
  99. // var key = any.Match(environmentVariables[i].Value).Groups[1].Value;
  100. // if (environmentVariables.Any(v => string.Equals(v.Name, key, StringComparison.OrdinalIgnoreCase)))
  101. // {
  102. // var value = environmentVariables.First(v => string.Equals(v.Name, key, StringComparison.OrdinalIgnoreCase)).Value;
  103. // environmentVariables[i].Value = Regex.Replace(environmentVariables[i].Value, string.Format("%{0}%", key), value, RegexOptions.IgnoreCase);
  104. // }
  105. // else
  106. // {
  107. // environmentVariables[i].Value = ExpandEnvironmentVariablesWithSubstitution(environmentVariables[i].Value);
  108. // }
  109. // }
  110. //}
  111.  
  112. // atempt to import moz certs
  113. //var mozCertPath = Path.Combine(@"c:\", "mozilla-build", "msys", "etc", "ca-bundle.crt");
  114. //if (File.Exists(mozCertPath))
  115. //{
  116. // var mozCert = new X509Certificate2(X509Certificate.CreateFromCertFile(mozCertPath));
  117. // X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
  118. // store.Open(OpenFlags.ReadWrite);
  119. // var existing = store.Certificates.Find(X509FindType.FindByThumbprint, mozCert.Thumbprint, true);
  120. // if (existing == null)
  121. // store.Add(mozCert);
  122. // store.Close();
  123. //}
  124.  
  125. try
  126. {
  127. Console.ForegroundColor = ConsoleColor.Gray;
  128. Console.WriteLine("minion found a payload with {0} commands and {1} environment variables.", payload.Commands.Count(), payload.Environment.Count());
  129. Console.ResetColor();
  130. var interrupt = false;
  131. foreach (var command in payload.Commands)
  132. {
  133. var environmentBefore = new List<EnvironmentVariable>(environmentVariables);
  134. command.File = ExpandEnvironmentVariablesWithSubstitution(ExpandEnvironmentVariables(command.File, environmentVariables), workingDirectory);
  135. command.Arguments = command.Arguments.Select(a => ExpandEnvironmentVariablesWithSubstitution(ExpandEnvironmentVariables(a, environmentVariables), workingDirectory));
  136.  
  137. Console.ForegroundColor = ConsoleColor.Yellow;
  138. Console.WriteLine("{0} {1}", command.File, string.Join(" ", command.Arguments));
  139. Console.ResetColor();
  140. if (interrupt)
  141. {
  142. results.Add(new CommandResult()
  143. {
  144. ExitCode = -100000
  145. });
  146. Console.ForegroundColor = ConsoleColor.Gray;
  147. Console.WriteLine("skipped due to previous errors.");
  148. Console.ResetColor();
  149. }
  150. else
  151. {
  152. var errors = new List<string>();
  153. var output = new List<string>();
  154. var process = new Process
  155. {
  156. StartInfo = new ProcessStartInfo
  157. {
  158. FileName = command.File,
  159. Arguments = command.Arguments.Any() ? string.Join(" ", command.Arguments) : null,
  160. UseShellExecute = false,
  161. CreateNoWindow = true,
  162. RedirectStandardOutput = true,
  163. RedirectStandardError = true,
  164. WorkingDirectory = workingDirectory,
  165. UserName = username,
  166. Password = password.ToSecureString()
  167. }
  168. };
  169. try
  170. {
  171. // pass environment changes to the command
  172. environmentVariables.ForEach(e => {
  173. if (process.StartInfo.EnvironmentVariables.ContainsKey(e.Name))
  174. process.StartInfo.EnvironmentVariables[e.Name] = e.Value;
  175. else
  176. process.StartInfo.EnvironmentVariables.Add(e.Name, e.Value);
  177. });
  178. process.ErrorDataReceived += (s, ea) => {
  179. errors.Add(ea.Data);
  180. Console.ForegroundColor = ConsoleColor.Red;
  181. Console.WriteLine(ea.Data);
  182. Console.ResetColor();
  183. };
  184. process.OutputDataReceived += (s, ea) => {
  185. output.Add(ea.Data);
  186. Console.ForegroundColor = ConsoleColor.Blue;
  187. Console.WriteLine(ea.Data);
  188. Console.ResetColor();
  189. };
  190. process.Start();
  191. process.BeginOutputReadLine();
  192. process.BeginErrorReadLine();
  193. process.WaitForExit();
  194. if (process.ExitCode != 0)
  195. {
  196. if (!process.HasExited)
  197. process.Kill();
  198. interrupt = true;
  199. }
  200.  
  201. // propagate environment changes from the command
  202. // todo: validate that changes show up here
  203. environmentVariables.Clear();
  204. process.StartInfo.EnvironmentVariables.Cast<DictionaryEntry>().AsParallel().ForAll(v => environmentVariables.Add(new EnvironmentVariable((string)v.Key, (string)v.Value)));
  205.  
  206. if(process.ExitCode != 0)
  207. {
  208. results.Add(new CommandResult()
  209. {
  210. StartTime = process.StartTime,
  211. ExitTime = process.ExitTime,
  212. TotalProcessorTime = process.TotalProcessorTime,
  213. ExitCode = process.ExitCode,
  214. EnvironmentBefore = environmentBefore,
  215. EnvironmentAfter = environmentVariables
  216. });
  217. foreach (var ev in environmentVariables.OrderBy(o => o.Name))
  218. {
  219. Console.ForegroundColor = ConsoleColor.Cyan;
  220. Console.Write(ev.Name);
  221. Console.ForegroundColor = ConsoleColor.Gray;
  222. Console.Write(": ");
  223. Console.ForegroundColor = ConsoleColor.Magenta;
  224. Console.Write(ev.Value);
  225. Console.Write('\n');
  226. Console.ResetColor();
  227. }
  228. }
  229. Console.ForegroundColor = ConsoleColor.Gray;
  230. Console.WriteLine("paeon completed this task in {0} seconds.", process.TotalProcessorTime.TotalSeconds);
  231. Console.ResetColor();
  232. }
  233. catch (Win32Exception win32Exception)
  234. {
  235. Console.ForegroundColor = ConsoleColor.DarkYellow;
  236. Console.WriteLine(win32Exception);
  237. Console.ResetColor();
  238. }
  239. finally
  240. {
  241. process.CancelOutputRead();
  242. process.CancelErrorRead();
  243. if (!process.HasExited)
  244. {
  245. process.Kill();
  246. }
  247. }
  248. }
  249. }
  250. }
  251. catch (Exception exception)
  252. {
  253. Console.ForegroundColor = ConsoleColor.DarkYellow;
  254. Console.WriteLine(exception);
  255. Console.ResetColor();
  256. }
  257. finally
  258. {
  259. var completed = results.Count(r => r.ExitCode == 0);
  260. var skipped = results.Count(r => r.ExitCode == -100000);
  261. var failed = results.Count(r => r.ExitCode != -100000 && r.ExitCode != 0);
  262.  
  263. DeleteUser(user);
  264. Console.ForegroundColor = ConsoleColor.Gray;
  265. 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)));
  266. Console.ResetColor();
  267. }
  268. Console.ReadKey();
  269. }
  270.  
  271. static SecureString ToSecureString(this string s)
  272. {
  273. var ss = new SecureString();
  274. if (!string.IsNullOrEmpty(s))
  275. foreach (var c in s.ToCharArray())
  276. ss.AppendChar(c);
  277. return ss;
  278. }
  279.  
  280. private static UserPrincipal CreateUser(string username, string password, string homeDirectory, params string[] groups)
  281. {
  282. UserPrincipal up;
  283. using (var mc = new PrincipalContext(ContextType.Machine))
  284. {
  285. up = new UserPrincipal(mc, username, password, true)
  286. {
  287. PasswordNeverExpires = true,
  288. HomeDirectory = homeDirectory
  289. };
  290. up.Save();
  291. groups.Select(group => GroupPrincipal.FindByIdentity(mc, group))
  292. .AsParallel()
  293. .Where(gp => gp != null)
  294. .ForAll(gp =>
  295. {
  296. gp.Members.Add(up);
  297. gp.Save();
  298. });
  299. }
  300. var folders = new List<string>();
  301. var files = new List<string>();
  302. foreach (var path in RequiredAccessPaths)
  303. {
  304. GetSubfoldersAndFiles(path, ref folders, ref files);
  305. foreach (var folder in folders)
  306. {
  307. AddPathSecurity(folder, username, FileSystemRights.Read | FileSystemRights.Traverse, AccessControlType.Allow);
  308. }
  309. foreach (var file in files)
  310. {
  311. AddPathSecurity(file, username, FileSystemRights.Read, AccessControlType.Allow);
  312. }
  313. }
  314. Console.ForegroundColor = ConsoleColor.Gray;
  315. Console.WriteLine("minion spawned a paeon {0} and commanded {1} to take her into their fold.", username, string.Join(", ", groups));
  316. Console.ResetColor();
  317. return up;
  318. }
  319.  
  320. private static void DeleteUser(UserPrincipal user)
  321. {
  322. var username = user.SamAccountName;
  323. foreach (var path in RequiredAccessPaths)
  324. {
  325. var folders = new List<string>();
  326. var files = new List<string>();
  327. GetSubfoldersAndFiles(path, ref folders, ref files);
  328. foreach (var folder in folders)
  329. {
  330. RemovePathSecurity(folder, username, FileSystemRights.Read | FileSystemRights.Traverse, AccessControlType.Allow);
  331. }
  332. foreach (var file in files)
  333. {
  334. RemovePathSecurity(file, username, FileSystemRights.Read, AccessControlType.Allow);
  335. }
  336. }
  337. user.Delete();
  338. }
  339.  
  340. private static void AddPathSecurity(string path, string username, FileSystemRights fsr, AccessControlType act)
  341. {
  342. var di = new DirectoryInfo(path);
  343. var ds = di.GetAccessControl();
  344. ds.AddAccessRule(new FileSystemAccessRule(username, fsr, act));
  345. try
  346. {
  347. di.SetAccessControl(ds);
  348. Console.ForegroundColor = ConsoleColor.Green;
  349. Console.WriteLine("worker access granted: {0}.", path);
  350. Console.ResetColor();
  351. }
  352. catch
  353. {
  354. Console.ForegroundColor = ConsoleColor.Magenta;
  355. Console.WriteLine("worker access not granted: {0}.", path);
  356. Console.ResetColor();
  357. }
  358. }
  359.  
  360. private static void RemovePathSecurity(string path, string username, FileSystemRights fsr, AccessControlType act)
  361. {
  362. var di = new DirectoryInfo(path);
  363. var ds = di.GetAccessControl();
  364. ds.RemoveAccessRule(new FileSystemAccessRule(username, fsr, act));
  365. try
  366. {
  367. di.SetAccessControl(ds);
  368. Console.ForegroundColor = ConsoleColor.Green;
  369. Console.WriteLine("worker access removed: {0}.", path);
  370. Console.ResetColor();
  371. }
  372. catch
  373. {
  374. Console.ForegroundColor = ConsoleColor.Magenta;
  375. Console.WriteLine("worker access not removed: {0}.", path);
  376. Console.ResetColor();
  377. }
  378. }
  379.  
  380. private static void GetSubfoldersAndFiles(string path, ref List<string> folders, ref List<string> files)
  381. {
  382. if (!folders.Any())
  383. folders.Add(path);
  384. foreach (string folder in Directory.GetDirectories(path))
  385. {
  386. folders.Add(folder);
  387. foreach (string file in Directory.GetFiles(folder))
  388. {
  389. files.Add(file);
  390. }
  391. GetSubfoldersAndFiles(folder, ref folders, ref files);
  392. }
  393. }
  394.  
  395. private static string ExpandEnvironmentVariables(string value, IEnumerable<EnvironmentVariable> environmentVariables)
  396. {
  397. foreach (var ev in environmentVariables)
  398. if (value != ev.Value)
  399. value = Regex.Replace(value, string.Format("%{0}%", ev.Name), ev.Value, RegexOptions.IgnoreCase);
  400. return value;
  401. }
  402.  
  403. private static string ExpandEnvironmentVariablesWithSubstitution(string value, string workingDirectory = null, string username = null, string password = null)
  404. {
  405. string result = string.Empty;
  406. var process = new Process
  407. {
  408. StartInfo = new ProcessStartInfo
  409. {
  410. FileName = "cmd",
  411. Arguments = string.Concat("/c echo ", value),
  412. UseShellExecute = false,
  413. CreateNoWindow = true,
  414. RedirectStandardOutput = true,
  415. WorkingDirectory = workingDirectory,
  416. UserName = username,
  417. Password = password.ToSecureString()
  418. }
  419. };
  420. process.OutputDataReceived += (s, e) => result = string.IsNullOrWhiteSpace(e.Data) ? result: e.Data;
  421. process.Start();
  422. process.BeginOutputReadLine();
  423. process.WaitForExit();
  424. process.CancelOutputRead();
  425. if (!process.HasExited)
  426. process.Kill();
  427. return result;
  428. }
  429. }
  430. public class Payload
  431. {
  432. public IEnumerable<Command> Commands { get; set; }
  433. public IEnumerable<EnvironmentVariable> Environment { get; set; }
  434. }
  435. public class Command
  436. {
  437. public string File { get; set; }
  438. public IEnumerable<string> Arguments { get; set; }
  439. }
  440. public class EnvironmentVariable
  441. {
  442. public EnvironmentVariable() { }
  443. public EnvironmentVariable(string name, string value)
  444. {
  445. Name = name;
  446. Value = value;
  447. }
  448.  
  449. public string Name { get; set; }
  450.  
  451. public string Value { get; set; }
  452. }
  453.  
  454. public class CommandResult
  455. {
  456. public IEnumerable<EnvironmentVariable> EnvironmentBefore { get; set; }
  457. public IEnumerable<EnvironmentVariable> EnvironmentAfter { get; set; }
  458. public int ExitCode { get; set; }
  459. public DateTime StartTime { get; set; }
  460. public DateTime ExitTime { get; set; }
  461. public TimeSpan TotalProcessorTime { get; set; }
  462. }
  463. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement