Skip to content

Commit

Permalink
Merge pull request #8 from mvelazc0/bh-arsenal-2021
Browse files Browse the repository at this point in the history
BlackHat Arsenal 2021
  • Loading branch information
mvelazc0 authored Sep 18, 2021
2 parents 2de7fd6 + 7946b06 commit 2efdf00
Show file tree
Hide file tree
Showing 15 changed files with 853 additions and 506 deletions.
6 changes: 3 additions & 3 deletions PurpleSharp/Lib/Json.cs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ public static void ExportAttackLayer(string[] techniques)
{

NavigatorLayer layer = new NavigatorLayer();
layer.version = "3.0";
layer.version = "4.2";
layer.name = "PurpleSharp Coverage";
layer.domain = "mitre-enterprise";
layer.description = "Layer of techniques supported by PurpleSharp";
Expand Down Expand Up @@ -294,7 +294,7 @@ public static NavigatorLayer ReadNavigatorLayer(string jsoninput)

}

public static SimulationExercise ConvertNavigatorToSimulationExercise(NavigatorLayer layer, string[] supportedtechniques)
public static SimulationExercise ConvertNavigatorToSimulationExercise(NavigatorLayer layer, string[] supportedtechniques, string[] supportedsubtechniques)
{
SimulationExercise engagement = new SimulationExercise();
List<SimulationPlaybook> playbooks = new List<SimulationPlaybook>();
Expand All @@ -303,7 +303,7 @@ public static SimulationExercise ConvertNavigatorToSimulationExercise(NavigatorL
foreach (NavigatorTechnique technique in layer.techniques)
{

if (Array.IndexOf(supportedtechniques, technique.techniqueID) > -1)
if (Array.IndexOf(supportedtechniques, technique.techniqueID) > -1 || Array.IndexOf(supportedsubtechniques, technique.techniqueID) > -1)
{
SimulationPlaybook playbook = new SimulationPlaybook();
playbook.name = layer.name;
Expand Down
1 change: 1 addition & 0 deletions PurpleSharp/Lib/Ldap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public Computer(string hostname, string ip)
{
ComputerName = hostname;
IPv4 = ip;
Fqdn = "";
}
public Computer()
{
Expand Down
2 changes: 2 additions & 0 deletions PurpleSharp/Lib/Logger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public void SimulationFinished()
public void SimulationFailed(Exception ex)
{
WriteFormattedLog(LogLevel.TINFO, "Exception: "+ ex.Message.ToString().Replace(Environment.NewLine,""));
//WriteFormattedLog(LogLevel.TINFO, "Exception: " + ex.StackTrace);

WriteFormattedLog(LogLevel.TINFO, "Simulation Failed");
}
private void WriteLine(string text, bool append = true)
Expand Down
17 changes: 16 additions & 1 deletion PurpleSharp/Lib/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public class SimulationExercise
public string password { get; set; }
public string domain_controller { get; set; }
public int sleep { get; set; }
public string type { get; set; }
public string type { get; set; } = "local";
public List<SimulationPlaybook> playbooks { get; set; }
}
public class SimulationPlaybook
Expand All @@ -109,6 +109,7 @@ public SimulationPlaybook()
public class PlaybookTask
{
// Generic variables
public string tactic { get; set; } = "";
public string technique_id { get; set; }
public int variation { get; set; } = 1;
public int task_sleep { get; set; } = 0;
Expand All @@ -119,6 +120,7 @@ public class PlaybookTask
public string spray_password { get; set; } = "Passw0rd1";

// User target variables
// User by Password Spraying & Kerberoasting
public int user_target_type { get; set; } = 1;
public int user_target_total { get; set; } = 5;
public string[] user_targets { get; set; }
Expand All @@ -134,6 +136,19 @@ public class PlaybookTask
// Network Service Scanning
public int[] ports { get; set; } = { 135, 139, 443, 445, 1433, 3306, 3389 };

// Remote Service Creation
public string serviceName { get; set; } ="PurpleSharp Updater";
public string servicePath { get; set; } = @"C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe";

// WinRM remote execution and WMI remote execution
public string command { get; set; } = @"C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe";

// Creating local and remote scheduled tasks
public string taskName { get; set; } = @"PurpleSharp Updater";
public string taskPath { get; set; } = @"C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe";



public PlaybookTask()
{
}
Expand Down
10 changes: 5 additions & 5 deletions PurpleSharp/Lib/NamedPipes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -192,24 +192,24 @@ public static SimulationPlaybook RunSimulationServiceSerialized(string npipe, st
PipeSecurity ps = new PipeSecurity();
ps.SetAccessRule(new PipeAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), PipeAccessRights.ReadWrite, AccessControlType.Allow));

logger.TimestampInfo("starting Simulator!");
//logger.TimestampInfo("starting Simulator!");
using (var pipeServer = new NamedPipeServerStream(npipe, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous, 4028, 4028, ps))

{
SimulationResponse sim_response;
logger.TimestampInfo("Waiting for client connection...");
//logger.TimestampInfo("Waiting for client connection...");
pipeServer.WaitForConnection();
logger.TimestampInfo("Client connected.");
//logger.TimestampInfo("Client connected.");
var messageBytes = ReadMessage(pipeServer);
var line = Encoding.UTF8.GetString(messageBytes);
logger.TimestampInfo("Received from client: " + line);
//logger.TimestampInfo("Received from client: " + line);
SimulationRequest sim_request = JsonConvert.DeserializeObject<SimulationRequest>(line);

playbook = sim_request.playbook;
sim_response = new SimulationResponse("ACK");
byte[] bytes_sim_response = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(sim_response));
pipeServer.Write(bytes_sim_response, 0, bytes_sim_response.Length);
logger.TimestampInfo("Replied to client: " + Encoding.UTF8.GetString(bytes_sim_response));
//logger.TimestampInfo("Replied to client: " + Encoding.UTF8.GetString(bytes_sim_response));
pipeServer.Disconnect();
return playbook;
}
Expand Down
17 changes: 9 additions & 8 deletions PurpleSharp/Lib/SharpRoast.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,35 +86,36 @@ public static void GetDomainSPNTicket(string samaccountname, string spn, string
}
else
{
logger.TimestampInfo(String.Format("Obtained service ticket and hash for SPN {0} ({1})", spn, samaccountname));
// output to hashcat format
string hash = String.Format("$krb5tgs${0}$*{1}${2}${3}*${4}${5}", eType, userName, domain, spn, cipherText.Substring(0, 32), cipherText.Substring(32));

bool header = false;
foreach (string line in Split(hash, 80))
{
if (!header)
{
//Console.WriteLine("Hash : {0}", line);
DateTime dtime = DateTime.Now;
//Console.WriteLine("{0}[{1}] Obtained service ticket and hash for SPN {2} ({3})", "".PadLeft(4), dtime.ToString("MM/dd/yyyy HH:mm:ss"), spn, samaccountname);
logger.TimestampInfo(String.Format("Obtained service ticket and hash for SPN {0} ({1})", spn, samaccountname));

}
else
{
//Console.WriteLine(" {0}", line);
//Console.WriteLine(hash);
}
header = true;
}
//Console.WriteLine();
}
}
}
catch (Exception ex)
{
logger.TimestampInfo(String.Format("Error obtaining service ticket and hash for SPN {0} ({1})", spn, samaccountname));

//Console.WriteLine("\r\n [X] Error during request for SPN {0} : {1}\r\n", spn, ex.InnerException.Message);
DateTime dtime = DateTime.Now;
Console.WriteLine("{0}[{1}] Error obtaining service ticket and hash for SPN {2} ({3})", "".PadLeft(4), dtime.ToString("MM/dd/yyyy HH:mm:ss"), spn, samaccountname);
Console.WriteLine(ex);
//DateTime dtime = DateTime.Now;
//Console.WriteLine("{0}[{1}] Error obtaining service ticket and hash for SPN {2} ({3})", "".PadLeft(4), dtime.ToString("MM/dd/yyyy HH:mm:ss"), spn, samaccountname);
//Console.WriteLine(ex);
}
}

Expand Down
14 changes: 14 additions & 0 deletions PurpleSharp/Lib/Structs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,20 @@ public struct CONTEXT64
public ulong LastExceptionFromRip;
}

[StructLayout(LayoutKind.Sequential)]
public struct QueryServiceConfig
{
public int serviceType;
public int startType;
public int errorControl;
public IntPtr binaryPathName;
public IntPtr loadOrderGroup;
public int tagID;
public IntPtr dependencies;
public IntPtr startName;
public IntPtr displayName;
}




Expand Down
57 changes: 28 additions & 29 deletions PurpleSharp/Lib/Targets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static List<Computer> GetNetworkNeighborTargets(int count, Logger logger)
}


public static List<Computer> GetDomainNeighborTargets(int count, Lib.Logger logger)
public static List<Computer> GetDomainNeighborTargets(int count, Logger logger)
{

List<Computer> targets = new List<Computer>();
Expand Down Expand Up @@ -216,50 +216,49 @@ public static List<Computer> GetHostTargets(PlaybookTask playbook_task, Logger l
{
List<Computer> host_targets = new List<Computer>();
Computer host_target = new Computer();
IPAddress ipAddress = null;

bool isValidIp;

switch (playbook_task.host_target_type)
{
case 1:
IPAddress ipAddress = null;
isValidIp = IPAddress.TryParse(playbook_task.host_targets[0], out ipAddress);
if (isValidIp) host_target = new Computer("", playbook_task.host_targets[0]);
else host_target = new Computer(playbook_task.host_targets[0], Networking.ResolveHostname(playbook_task.host_targets[0]).ToString());
logger.TimestampInfo(String.Format("Using {0} {1} as the target", host_target.ComputerName, host_target.IPv4));
host_targets.Add(host_target);

if (playbook_task.host_targets.Length > 1)
{
foreach (string target in playbook_task.host_targets)
{
isValidIp = IPAddress.TryParse(target, out ipAddress);
if (isValidIp) host_target = new Computer("", target);
else host_target = new Computer(target, Networking.ResolveHostname(target).ToString());
host_targets.Add(host_target);
}
logger.TimestampInfo(String.Format("Using {0} targets defined in the playbook", playbook_task.host_targets.Length.ToString()));
}
else
{
isValidIp = IPAddress.TryParse(playbook_task.host_targets[0], out ipAddress);
if (isValidIp) host_target = new Computer("", playbook_task.host_targets[0]);
else host_target = new Computer(playbook_task.host_targets[0], Networking.ResolveHostname(playbook_task.host_targets[0]).ToString());
logger.TimestampInfo(String.Format("Using {0} {1} as the target", host_target.ComputerName, host_target.IPv4));
host_targets.Add(host_target);
}
break;

case 2:
logger.TimestampInfo("Targeting a random domain host target");
logger.TimestampInfo("Targeting a random domain hosts");
host_targets = GetDomainNeighborTargets(playbook_task.host_target_total, logger);
logger.TimestampInfo(String.Format("Obtained {0} host records", host_targets.Count));
/*
// Pick one random host
var random = new Random();
int index = random.Next(host_targets.Count);
host_target = host_targets[index];
logger.TimestampInfo(String.Format("Randomly picked {0} {1} as the target", host_target.ComputerName, host_target.IPv4));
host_targets.Clear();
host_targets.Add(host_target);
*/
break;

case 3:
//TODO: This option is not needed, It can be part of case 1.
logger.TimestampInfo(String.Format("Targeting {0} hosts defined in playbook", playbook_task.host_targets.Length));
for (int i = 0; i < playbook_task.host_targets.Length; i++)
{
isValidIp = IPAddress.TryParse(playbook_task.host_targets[i], out ipAddress);
if (isValidIp) host_target = new Computer("", playbook_task.host_targets[i]);
else host_target = new Computer(playbook_task.host_targets[i], Networking.ResolveHostname(playbook_task.host_targets[i]).ToString());
host_targets.Add(host_target);
}
break;

case 4:
logger.TimestampInfo("Targeting random domain hosts");
host_targets = GetDomainNeighborTargets(playbook_task.host_target_total, logger);
logger.TimestampInfo(String.Format("Obtained {0} host records", host_targets.Count));
break;


default:
return host_targets;
}
Expand Down
5 changes: 5 additions & 0 deletions PurpleSharp/Lib/WinAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ public static extern IntPtr CreateService(
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteService(IntPtr serviceHandle);

[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern int QueryServiceConfig(IntPtr hService, IntPtr queryServiceConfig, int bufferSize, ref int bytesNeeded);

[DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool ChangeServiceConfig(IntPtr hService, uint dwServiceType, int dwStartType, int dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId, string lpDependencies, string lpServiceStartName, string lpPassword, string lpDisplayName);


[DllImport("advapi32.dll", SetLastError = true)]
Expand Down
Loading

0 comments on commit 2efdf00

Please sign in to comment.